From 2bda8f7717adf28da4af0d34fb82f63d2868c31d Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeutils@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- AUTHORS | 28 + COPYING | 346 ++ COPYING-DOCS | 397 ++ INSTALL | 176 + Mainpage.dox | 11 + Makefile.am.in | 10 + Makefile.cvs | 14 + README | 51 + ark/AUTHORS | 5 + ark/ChangeLog | 277 ++ ark/Makefile.am | 54 + ark/README | 4 + ark/TODO | 11 + ark/ace.cpp | 181 + ark/ace.h | 55 + ark/addition.ui | 79 + ark/ar.cpp | 263 + ark/ar.h | 61 + ark/arch.cpp | 403 ++ ark/arch.h | 221 + ark/archiveformatdlg.cpp | 71 + ark/archiveformatdlg.h | 39 + ark/archiveformatinfo.cpp | 278 ++ ark/archiveformatinfo.h | 73 + ark/ark.desktop | 87 + ark/ark.kcfg | 90 + ark/ark_part.cpp | 533 ++ ark/ark_part.desktop | 135 + ark/ark_part.h | 148 + ark/ark_part.rc | 57 + ark/ark_part_readonly.rc | 42 + ark/arkapp.cpp | 294 ++ ark/arkapp.h | 93 + ark/arkfactory.cpp | 68 + ark/arkfactory.h | 43 + ark/arkui.rc | 22 + ark/arkutils.cpp | 230 + ark/arkutils.h | 56 + ark/arkviewer.cpp | 103 + ark/arkviewer.h | 47 + ark/arkwidget.cpp | 2262 +++++++++ ark/arkwidget.h | 318 ++ ark/common_texts.cpp | 35 + ark/compressedfile.cpp | 376 ++ ark/compressedfile.h | 86 + ark/configure.in.in | 11 + ark/extraction.ui | 79 + ark/extractiondialog.cpp | 195 + ark/extractiondialog.h | 97 + ark/filelistview.cpp | 587 +++ ark/filelistview.h | 163 + ark/general.ui | 93 + ark/hi128-app-ark.png | Bin 0 -> 11259 bytes ark/hi16-app-ark.png | Bin 0 -> 1094 bytes ark/hi22-app-ark.png | Bin 0 -> 1431 bytes ark/hi32-app-ark.png | Bin 0 -> 2259 bytes ark/hi48-app-ark.png | Bin 0 -> 3778 bytes ark/hi64-app-ark.png | Bin 0 -> 5013 bytes ark/hisc-app-ark.svgz | Bin 0 -> 7499 bytes ark/lha.cpp | 302 ++ ark/lha.h | 61 + ark/main.cpp | 128 + ark/mainwindow.cpp | 481 ++ ark/mainwindow.h | 112 + ark/pics/Makefile.am | 2 + ark/pics/cr22-action-ark_adddir.png | Bin 0 -> 1303 bytes ark/pics/cr22-action-ark_addfile.png | Bin 0 -> 1287 bytes ark/pics/cr22-action-ark_delete.png | Bin 0 -> 1346 bytes ark/pics/cr22-action-ark_extract.png | Bin 0 -> 1227 bytes ark/pics/cr22-action-ark_selectall.png | Bin 0 -> 989 bytes ark/pics/cr22-action-ark_view.png | Bin 0 -> 833 bytes ark/pics/cr32-action-ark_adddir.png | Bin 0 -> 2285 bytes ark/pics/cr32-action-ark_addfile.png | Bin 0 -> 2126 bytes ark/pics/cr32-action-ark_delete.png | Bin 0 -> 2284 bytes ark/pics/cr32-action-ark_extract.png | Bin 0 -> 2084 bytes ark/pics/cr32-action-ark_view.png | Bin 0 -> 1134 bytes ark/rar.cpp | 306 ++ ark/rar.h | 68 + ark/searchbar.cpp | 49 + ark/searchbar.h | 40 + ark/settings.kcfgc | 5 + ark/sevenzip.cpp | 367 ++ ark/sevenzip.h | 54 + ark/tar.cpp | 774 +++ ark/tar.h | 135 + ark/tarlistingthread.cpp | 161 + ark/tarlistingthread.h | 63 + ark/zip.cpp | 277 ++ ark/zip.h | 58 + ark/zoo.cpp | 317 ++ ark/zoo.h | 59 + charselectapplet/Makefile.am | 19 + charselectapplet/charselectapplet.cpp | 366 ++ charselectapplet/charselectapplet.h | 115 + charselectapplet/kcharselectapplet.desktop | 100 + configure.in.in | 12 + doc/KRegExpEditor/Makefile.am | 5 + doc/KRegExpEditor/altn.png | Bin 0 -> 310 bytes doc/KRegExpEditor/altntool.png | Bin 0 -> 1282 bytes doc/KRegExpEditor/anychar.png | Bin 0 -> 616 bytes doc/KRegExpEditor/anychartool.png | Bin 0 -> 531 bytes doc/KRegExpEditor/begline.png | Bin 0 -> 244 bytes doc/KRegExpEditor/boundarytools.png | Bin 0 -> 861 bytes doc/KRegExpEditor/characters.png | Bin 0 -> 240 bytes doc/KRegExpEditor/charactertool.png | Bin 0 -> 983 bytes doc/KRegExpEditor/compound.png | Bin 0 -> 285 bytes doc/KRegExpEditor/compoundtool.png | Bin 0 -> 1432 bytes doc/KRegExpEditor/endline.png | Bin 0 -> 245 bytes doc/KRegExpEditor/index.docbook | 652 +++ doc/KRegExpEditor/linestartendtool.png | Bin 0 -> 817 bytes doc/KRegExpEditor/lookaheadtools.png | Bin 0 -> 774 bytes doc/KRegExpEditor/neglookahead.png | Bin 0 -> 297 bytes doc/KRegExpEditor/nonwordboundary.png | Bin 0 -> 225 bytes doc/KRegExpEditor/poslookahead.png | Bin 0 -> 297 bytes doc/KRegExpEditor/repeat.png | Bin 0 -> 632 bytes doc/KRegExpEditor/repeattool.png | Bin 0 -> 1160 bytes doc/KRegExpEditor/select.png | Bin 0 -> 742 bytes doc/KRegExpEditor/text.png | Bin 0 -> 338 bytes doc/KRegExpEditor/texttool.png | Bin 0 -> 396 bytes doc/KRegExpEditor/theEditor.png | Bin 0 -> 10004 bytes doc/KRegExpEditor/wordboundary.png | Bin 0 -> 210 bytes doc/Makefile.am | 5 + doc/ark/Makefile.am | 5 + doc/ark/index.docbook | 793 +++ doc/ark/man-ark.1.docbook | 174 + doc/kcalc/Makefile.am | 4 + doc/kcalc/commands.docbook | 254 + doc/kcalc/index.docbook | 774 +++ doc/kcalc/kcalc_on_Aix.txt | 123 + doc/kcalc/kcalc_on_OSF.txt | 62 + doc/kcharselect/Makefile.am | 4 + doc/kcharselect/index.docbook | 66 + doc/kcontrol/Makefile.am | 6 + doc/kcontrol/kcmlowbatcrit/Makefile.am | 2 + doc/kcontrol/kcmlowbatcrit/index.docbook | 47 + doc/kcontrol/kcmlowbatwarn/Makefile.am | 2 + doc/kcontrol/kcmlowbatwarn/index.docbook | 104 + doc/kcontrol/laptop/Makefile.am | 2 + doc/kcontrol/laptop/index.docbook | 111 + doc/kcontrol/powerctrl/Makefile.am | 2 + doc/kcontrol/powerctrl/index.docbook | 77 + doc/kdelirc/Makefile.am | 5 + doc/kdelirc/irkick/Makefile.am | 4 + doc/kdelirc/irkick/index.docbook | 131 + doc/kdelirc/kcmlirc/Makefile.am | 4 + doc/kdelirc/kcmlirc/index.docbook | 165 + doc/kdf/Makefile.am | 4 + doc/kdf/index.docbook | 266 + doc/kdf/kdf.png | Bin 0 -> 22869 bytes doc/kdf/kdf_config.png | Bin 0 -> 32396 bytes doc/kedit/Makefile.am | 4 + doc/kedit/index.docbook | 1255 +++++ doc/kfloppy/Makefile.am | 4 + doc/kfloppy/index.docbook | 614 +++ doc/kgpg/Makefile.am | 4 + doc/kgpg/editor.png | Bin 0 -> 15541 bytes doc/kgpg/index.docbook | 354 ++ doc/kgpg/keygen.png | Bin 0 -> 9522 bytes doc/kgpg/keymanage.png | Bin 0 -> 23651 bytes doc/kgpg/keys.png | Bin 0 -> 13790 bytes doc/kgpg/kicker.png | Bin 0 -> 4582 bytes doc/kgpg/options.png | Bin 0 -> 18367 bytes doc/khexedit/Makefile.am | 4 + doc/khexedit/index.docbook | 1063 ++++ doc/khexedit/khexedit1.png | Bin 0 -> 3266 bytes doc/kinfocenter/Makefile.am | 6 + doc/kinfocenter/blockdevices/Makefile.am | 3 + doc/kinfocenter/blockdevices/index.docbook | 89 + doc/kjots/Makefile.am | 4 + doc/kjots/index.docbook | 552 +++ doc/ksim/Makefile.am | 4 + doc/ksim/index.docbook | 66 + doc/ktimer/Makefile.am | 4 + doc/ktimer/index.docbook | 66 + doc/kwallet/Makefile.am | 4 + doc/kwallet/cr22-action-wallet_closed.png | Bin 0 -> 997 bytes doc/kwallet/cr22-action-wallet_open.png | Bin 0 -> 1098 bytes doc/kwallet/edit1.png | Bin 0 -> 19314 bytes doc/kwallet/edit2.png | Bin 0 -> 26113 bytes doc/kwallet/edit3.png | Bin 0 -> 59244 bytes doc/kwallet/index.docbook | 396 ++ doc/kwallet/kwalletmanager.png | Bin 0 -> 11282 bytes doc/kwallet/password1.png | Bin 0 -> 19088 bytes doc/kwallet/password2.png | Bin 0 -> 21999 bytes doc/superkaramba/Makefile.am | 4 + doc/superkaramba/index.docbook | 261 + kcalc/ChangeLog | 387 ++ kcalc/Makefile.am | 40 + kcalc/README | 8 + kcalc/TODO | 15 + kcalc/colors.ui | 278 ++ kcalc/configure.in.bot | 12 + kcalc/configure.in.in | 78 + kcalc/confvalues.h | 48 + kcalc/constants.ui | 491 ++ kcalc/dlabel.cpp | 184 + kcalc/dlabel.h | 64 + kcalc/general.ui | 199 + kcalc/hi16-app-kcalc.png | Bin 0 -> 983 bytes kcalc/hi22-app-kcalc.png | Bin 0 -> 1421 bytes kcalc/hi32-app-kcalc.png | Bin 0 -> 2701 bytes kcalc/hi48-app-kcalc.png | Bin 0 -> 5023 bytes kcalc/hi64-app-kcalc.png | Bin 0 -> 6760 bytes kcalc/hisc-app-kcalc.svgz | Bin 0 -> 5247 bytes kcalc/kcalc.cpp | 2306 +++++++++ kcalc/kcalc.desktop | 88 + kcalc/kcalc.h | 239 + kcalc/kcalc.kcfg | 127 + kcalc/kcalc_button.cpp | 168 + kcalc/kcalc_button.h | 105 + kcalc/kcalc_const_button.cpp | 109 + kcalc/kcalc_const_button.h | 58 + kcalc/kcalc_const_menu.cpp | 89 + kcalc/kcalc_const_menu.h | 55 + kcalc/kcalc_core.cpp | 1004 ++++ kcalc/kcalc_core.h | 181 + kcalc/kcalc_settings.kcfgc | 8 + kcalc/kcalcdisplay.cpp | 608 +++ kcalc/kcalcdisplay.h | 152 + kcalc/kcalcrc.upd | 4 + kcalc/kcalctype.h | 135 + kcalc/kcalcui.rc | 17 + kcalc/knumber/Makefile.am | 16 + kcalc/knumber/configure.in.in | 73 + kcalc/knumber/knumber.cpp | 693 +++ kcalc/knumber/knumber.h | 289 ++ kcalc/knumber/knumber_priv.cpp | 1083 +++++ kcalc/knumber/knumber_priv.h | 313 ++ kcalc/knumber/tests/Makefile.am | 32 + kcalc/knumber/tests/knumbertest.cpp | 582 +++ kcalc/knumber/tests/knumbertest.h | 9 + kcalc/stats.cpp | 196 + kcalc/stats.h | 60 + kcalc/version.h | 1 + kcharselect/KCharSelect.desktop | 98 + kcharselect/Makefile.am | 21 + kcharselect/TODO | 6 + kcharselect/hi16-app-kcharselect.png | Bin 0 -> 325 bytes kcharselect/hi32-app-kcharselect.png | Bin 0 -> 1666 bytes kcharselect/hi48-app-kcharselect.png | Bin 0 -> 1353 bytes kcharselect/kcharselect.upd | 5 + kcharselect/kcharselectdia.cc | 289 ++ kcharselect/kcharselectdia.h | 71 + kcharselect/kcharselectui.rc | 16 + kcharselect/main.cc | 49 + kdelirc/AUTHORS | 3 + kdelirc/COPYING | 340 ++ kdelirc/ChangeLog | 0 kdelirc/Makefile.am | 3 + kdelirc/README | 55 + kdelirc/README.profile-creation | 145 + kdelirc/README.remote-creation | 129 + kdelirc/TODO | 6 + kdelirc/icons/Makefile.am | 3 + kdelirc/icons/hi16-action-ledblue.png | Bin 0 -> 709 bytes kdelirc/icons/hi16-action-ledgreen.png | Bin 0 -> 641 bytes kdelirc/icons/hi16-action-ledlightblue.png | Bin 0 -> 732 bytes kdelirc/icons/hi16-action-ledlightgreen.png | Bin 0 -> 718 bytes kdelirc/icons/hi16-action-ledorange.png | Bin 0 -> 698 bytes kdelirc/icons/hi16-action-ledpurple.png | Bin 0 -> 702 bytes kdelirc/icons/hi16-action-ledred.png | Bin 0 -> 659 bytes kdelirc/icons/hi16-action-ledyellow.png | Bin 0 -> 672 bytes kdelirc/icons/hi32-action-ledblue.png | Bin 0 -> 1384 bytes kdelirc/icons/hi32-action-ledgreen.png | Bin 0 -> 1265 bytes kdelirc/icons/hi32-action-ledlightblue.png | Bin 0 -> 1378 bytes kdelirc/icons/hi32-action-ledlightgreen.png | Bin 0 -> 1464 bytes kdelirc/icons/hi32-action-ledorange.png | Bin 0 -> 1378 bytes kdelirc/icons/hi32-action-ledpurple.png | Bin 0 -> 1327 bytes kdelirc/icons/hi32-action-ledred.png | Bin 0 -> 1207 bytes kdelirc/icons/hi32-action-ledyellow.png | Bin 0 -> 1354 bytes kdelirc/irkick/Makefile.am | 42 + kdelirc/irkick/hi16-app-irkick.png | Bin 0 -> 954 bytes kdelirc/irkick/hi22-app-irkick.png | Bin 0 -> 1457 bytes kdelirc/irkick/hi32-app-irkick.png | Bin 0 -> 2421 bytes kdelirc/irkick/icons/Makefile.am | 3 + kdelirc/irkick/icons/hi16-action-irkick.png | Bin 0 -> 954 bytes kdelirc/irkick/icons/hi16-action-irkickflash.png | Bin 0 -> 892 bytes kdelirc/irkick/icons/hi16-action-irkickoff.png | Bin 0 -> 1016 bytes kdelirc/irkick/irkick.cpp | 336 ++ kdelirc/irkick/irkick.desktop | 116 + kdelirc/irkick/irkick.h | 132 + kdelirc/irkick/irkick.project | 12 + kdelirc/irkick/kdedmodule_stub.h | 34 + kdelirc/irkick/klircclient.cpp | 241 + kdelirc/irkick/klircclient.h | 114 + kdelirc/irkick/lo16-app-irkick.png | Bin 0 -> 381 bytes kdelirc/irkick/lo32-app-irkick.png | Bin 0 -> 603 bytes kdelirc/irkick/main.cpp | 39 + kdelirc/kcmlirc/Makefile.am | 15 + kdelirc/kcmlirc/addaction.cpp | 375 ++ kdelirc/kcmlirc/addaction.h | 73 + kdelirc/kcmlirc/addactionbase.ui | 1608 ++++++ kdelirc/kcmlirc/editaction.cpp | 362 ++ kdelirc/kcmlirc/editaction.h | 55 + kdelirc/kcmlirc/editactionbase.ui | 1287 +++++ kdelirc/kcmlirc/editmode.cpp | 38 + kdelirc/kcmlirc/editmode.h | 33 + kdelirc/kcmlirc/editmodebase.ui | 303 ++ kdelirc/kcmlirc/kcmlirc.cpp | 544 +++ kdelirc/kcmlirc/kcmlirc.desktop | 119 + kdelirc/kcmlirc/kcmlirc.h | 83 + kdelirc/kcmlirc/kcmlircbase.ui | 506 ++ kdelirc/kcmlirc/kcmlircbase.ui.h | 37 + kdelirc/kcmlirc/modeslist.cpp | 33 + kdelirc/kcmlirc/modeslist.h | 33 + kdelirc/kcmlirc/newmode.ui | 158 + kdelirc/kcmlirc/newmode.ui.h | 24 + kdelirc/kcmlirc/selectprofile.ui | 128 + kdelirc/kdelirc/Makefile.am | 45 + kdelirc/kdelirc/arguments.cpp | 36 + kdelirc/kdelirc/arguments.h | 32 + kdelirc/kdelirc/iraction.cpp | 155 + kdelirc/kdelirc/iraction.h | 88 + kdelirc/kdelirc/iractions.cpp | 90 + kdelirc/kdelirc/iractions.h | 52 + kdelirc/kdelirc/mode.cpp | 51 + kdelirc/kdelirc/mode.h | 50 + kdelirc/kdelirc/modes.cpp | 128 + kdelirc/kdelirc/modes.h | 62 + kdelirc/kdelirc/profileserver.cpp | 159 + kdelirc/kdelirc/profileserver.h | 142 + kdelirc/kdelirc/prototype.cpp | 67 + kdelirc/kdelirc/prototype.h | 54 + kdelirc/kdelirc/remoteserver.cpp | 109 + kdelirc/kdelirc/remoteserver.h | 89 + kdelirc/profiles/Makefile.am | 5 + kdelirc/profiles/klauncher.profile.xml | 18 + kdelirc/profiles/konqueror.profile.xml | 17 + kdelirc/profiles/noatun.profile.xml | 75 + kdelirc/profiles/profile.dtd | 28 + kdelirc/remotes/Makefile.am | 6 + kdelirc/remotes/RM-0010.remote.xml | 49 + kdelirc/remotes/cimr100.remote.xml | 31 + kdelirc/remotes/hauppauge.remote.xml | 29 + kdelirc/remotes/remote.dtd | 15 + kdelirc/remotes/sherwood.remote.xml | 61 + kdelirc/remotes/sonytv.remote.xml | 30 + kdessh/LICENSE.readme | 124 + kdessh/Makefile.am | 17 + kdessh/README | 3 + kdessh/kdessh.cpp | 201 + kdessh/sshdlg.cpp | 80 + kdessh/sshdlg.h | 32 + kdeutils.lsm | 11 + kdf/Makefile.am | 37 + kdf/disklist.cpp | 506 ++ kdf/disklist.h | 138 + kdf/disks.cpp | 335 ++ kdf/disks.h | 148 + kdf/kcmdf.cpp | 66 + kdf/kcmdf.desktop | 138 + kdf/kcmdf.h | 49 + kdf/kconftest.cpp | 80 + kdf/kdf.cpp | 96 + kdf/kdf.desktop | 88 + kdf/kdf.h | 45 + kdf/kdfconfig.cpp | 263 + kdf/kdfconfig.h | 97 + kdf/kdfui.rc | 11 + kdf/kdfwidget.cpp | 652 +++ kdf/kdfwidget.h | 153 + kdf/kwikdisk.cpp | 346 ++ kdf/kwikdisk.desktop | 78 + kdf/kwikdisk.h | 78 + kdf/listview.cpp | 113 + kdf/listview.h | 53 + kdf/mntconfig.cpp | 364 ++ kdf/mntconfig.h | 102 + kdf/optiondialog.cpp | 85 + kdf/optiondialog.h | 50 + kdf/pics/Makefile.am | 4 + kdf/pics/cr16-app-kcmdf.png | Bin 0 -> 924 bytes kdf/pics/cr22-app-kcmdf.png | Bin 0 -> 1152 bytes kdf/pics/cr32-app-kcmdf.png | Bin 0 -> 1771 bytes kdf/pics/delete.png | Bin 0 -> 963 bytes kdf/pics/hi128-app-kdf.png | Bin 0 -> 10332 bytes kdf/pics/hi128-app-kwikdisk.png | Bin 0 -> 11838 bytes kdf/pics/hi16-app-kdf.png | Bin 0 -> 924 bytes kdf/pics/hi16-app-kwikdisk.png | Bin 0 -> 818 bytes kdf/pics/hi22-app-kdf.png | Bin 0 -> 1152 bytes kdf/pics/hi22-app-kwikdisk.png | Bin 0 -> 1229 bytes kdf/pics/hi32-app-kdf.png | Bin 0 -> 1771 bytes kdf/pics/hi32-app-kwikdisk.png | Bin 0 -> 2079 bytes kdf/pics/hi48-app-kdf.png | Bin 0 -> 2851 bytes kdf/pics/hi48-app-kwikdisk.png | Bin 0 -> 3510 bytes kdf/pics/hi64-app-kdf.png | Bin 0 -> 3801 bytes kdf/pics/hi64-app-kwikdisk.png | Bin 0 -> 5185 bytes kdf/pics/mini-root.png | Bin 0 -> 785 bytes kdf/pics/tick.png | Bin 0 -> 661 bytes kdf/stdoption.cpp | 148 + kdf/stdoption.h | 72 + kdf/unix_outputs/df-g.hpux | 392 ++ kdf/unix_outputs/df-k.digital | 42 + kdf/unix_outputs/df-k.hpux | 196 + kdf/unix_outputs/df.man.hpux | 198 + kdf/unix_outputs/etcfstab.digital | 43 + kdf/unix_outputs/etcfstab.hpux | 75 + kdf/unix_outputs/unix-defines.txt | 125 + kedit/ChangeLog | 113 + kedit/KEdit.desktop | 82 + kedit/Makefile.am | 35 + kedit/README | 192 + kedit/TODO | 6 + kedit/color.ui | 129 + kedit/kedit.cpp | 1377 ++++++ kedit/kedit.h | 229 + kedit/kedit.kcfg | 45 + kedit/keditui.rc | 10 + kedit/ktextfiledlg.cpp | 212 + kedit/ktextfiledlg.h | 74 + kedit/misc.ui | 123 + kedit/misc.ui.h | 14 + kedit/pixmaps/Makefile.am | 2 + kedit/pixmaps/hi16-app-kedit.png | Bin 0 -> 990 bytes kedit/pixmaps/hi22-app-kedit.png | Bin 0 -> 1654 bytes kedit/pixmaps/hi32-app-kedit.png | Bin 0 -> 2683 bytes kedit/pixmaps/hi48-app-kedit.png | Bin 0 -> 4385 bytes kedit/pixmaps/hi64-app-kedit.png | Bin 0 -> 8377 bytes kedit/prefs.kcfgc | 7 + kedit/version.h | 2 + kfloppy/KFloppy.desktop | 96 + kfloppy/Makefile.am | 23 + kfloppy/README | 23 + kfloppy/TODO | 47 + kfloppy/debug.h | 65 + kfloppy/floppy.cpp | 741 +++ kfloppy/floppy.h | 128 + kfloppy/floppy_format.desktop | 54 + kfloppy/format.cpp | 996 ++++ kfloppy/format.h | 426 ++ kfloppy/hi128-app-kfloppy.png | Bin 0 -> 12698 bytes kfloppy/hi16-app-kfloppy.png | Bin 0 -> 1008 bytes kfloppy/hi22-app-kfloppy.png | Bin 0 -> 1397 bytes kfloppy/hi32-app-kfloppy.png | Bin 0 -> 2374 bytes kfloppy/hi48-app-kfloppy.png | Bin 0 -> 3812 bytes kfloppy/hi64-app-kfloppy.png | Bin 0 -> 5298 bytes kfloppy/main.cpp | 79 + kfloppy/zip.cpp | 305 ++ kfloppy/zip.h | 106 + kgpg/AUTHORS | 1 + kgpg/ChangeLog | 310 ++ kgpg/INSTALL | 160 + kgpg/Makefile.am | 46 + kgpg/adduid.ui | 64 + kgpg/conf_decryption.ui | 69 + kgpg/conf_encryption.ui | 321 ++ kgpg/conf_encryption.ui.h | 22 + kgpg/conf_gpg.ui | 219 + kgpg/conf_misc.ui | 413 ++ kgpg/conf_servers.ui | 118 + kgpg/conf_ui2.ui | 178 + kgpg/dcopiface.h | 35 + kgpg/detailedconsole.cpp | 65 + kgpg/detailedconsole.h | 43 + kgpg/encryptfile.desktop | 62 + kgpg/encryptfolder.desktop | 52 + kgpg/groupedit.ui | 212 + kgpg/hi16-app-kgpg.png | Bin 0 -> 1013 bytes kgpg/hi22-app-kgpg.png | Bin 0 -> 1255 bytes kgpg/hi32-app-kgpg.png | Bin 0 -> 2073 bytes kgpg/hi48-app-kgpg.png | Bin 0 -> 3477 bytes kgpg/icons/Makefile.am | 2 + kgpg/icons/cr16-action-kgpg_key1.png | Bin 0 -> 267 bytes kgpg/icons/cr16-action-kgpg_key2.png | Bin 0 -> 440 bytes kgpg/icons/cr16-action-kgpg_key3.png | Bin 0 -> 671 bytes kgpg/icons/cr16-action-kgpg_key4.png | Bin 0 -> 353 bytes kgpg/icons/cr22-action-kgpg_edit.png | Bin 0 -> 3797 bytes kgpg/icons/cr22-action-kgpg_export.png | Bin 0 -> 346 bytes kgpg/icons/cr22-action-kgpg_gen.png | Bin 0 -> 585 bytes kgpg/icons/cr22-action-kgpg_identity.png | Bin 0 -> 1358 bytes kgpg/icons/cr22-action-kgpg_import.png | Bin 0 -> 371 bytes kgpg/icons/cr22-action-kgpg_info.png | Bin 0 -> 408 bytes kgpg/icons/cr22-action-kgpg_photo.png | Bin 0 -> 626 bytes kgpg/icons/cr22-action-kgpg_show.png | Bin 0 -> 375 bytes kgpg/icons/cr22-action-kgpg_sign.png | Bin 0 -> 437 bytes kgpg/icons/cr22-action-kgpg_term.png | Bin 0 -> 544 bytes kgpg/keyexport.ui | 142 + kgpg/keyexport.ui.h | 21 + kgpg/keygener.cpp | 176 + kgpg/keygener.h | 50 + kgpg/keyinfowidget.cpp | 465 ++ kgpg/keyinfowidget.h | 84 + kgpg/keyproperties.ui | 507 ++ kgpg/keyserver.ui | 336 ++ kgpg/keyservers.cpp | 574 +++ kgpg/keyservers.h | 81 + kgpg/kgpg.cpp | 1057 ++++ kgpg/kgpg.desktop | 123 + kgpg/kgpg.h | 168 + kgpg/kgpg.kcfg | 206 + kgpg/kgpg.rc | 27 + kgpg/kgpg_anim.gif | Bin 0 -> 954 bytes kgpg/kgpg_blank.png | Bin 0 -> 170 bytes kgpg/kgpg_docked.gif | Bin 0 -> 1602 bytes kgpg/kgpg_docked.png | Bin 0 -> 1167 bytes kgpg/kgpg_fill.png | Bin 0 -> 156 bytes kgpg/kgpgeditor.cpp | 554 +++ kgpg/kgpgeditor.h | 123 + kgpg/kgpginterface.cpp | 2166 +++++++++ kgpg/kgpginterface.h | 404 ++ kgpg/kgpglibrary.cpp | 245 + kgpg/kgpglibrary.h | 81 + kgpg/kgpgoptions.cpp | 601 +++ kgpg/kgpgoptions.h | 106 + kgpg/kgpgrevokewidget.ui | 152 + kgpg/kgpgrevokewidget.ui.h | 21 + kgpg/kgpgsettings.kcfgc | 9 + kgpg/kgpgsettings_addons.h | 41 + kgpg/kgpgview.cpp | 409 ++ kgpg/kgpgview.h | 121 + kgpg/kgpgwizard.ui | 405 ++ kgpg/listkeys.cpp | 3149 ++++++++++++ kgpg/listkeys.h | 302 ++ kgpg/listkeys.rc | 137 + kgpg/main.cpp | 79 + kgpg/newkey.ui | 196 + kgpg/newkey.ui.h | 21 + kgpg/popuppublic.cpp | 480 ++ kgpg/popuppublic.h | 76 + kgpg/searchres.ui | 124 + kgpg/sourceselect.ui | 112 + kgpg/tips | 44 + khexedit/Makefile.am | 35 + khexedit/README | 34 + khexedit/bitswapwidget.cc | 323 ++ khexedit/bitswapwidget.h | 101 + khexedit/chartabledialog.cc | 212 + khexedit/chartabledialog.h | 72 + khexedit/configure.in.in | 8 + khexedit/conversion.cc | 395 ++ khexedit/conversion.h | 71 + khexedit/converterdialog.cc | 163 + khexedit/converterdialog.h | 83 + khexedit/dialog.cc | 1433 ++++++ khexedit/dialog.h | 350 ++ khexedit/draglabel.cc | 149 + khexedit/draglabel.h | 60 + khexedit/exportdialog.cc | 696 +++ khexedit/exportdialog.h | 138 + khexedit/fileinfodialog.cc | 330 ++ khexedit/fileinfodialog.h | 74 + khexedit/hexbuffer.cc | 5099 ++++++++++++++++++++ khexedit/hexbuffer.h | 2040 ++++++++ khexedit/hexclipboard.cc | 254 + khexedit/hexclipboard.h | 40 + khexedit/hexdrag.cc | 130 + khexedit/hexdrag.h | 54 + khexedit/hexeditorwidget.cc | 2443 ++++++++++ khexedit/hexeditorwidget.h | 301 ++ khexedit/hexeditstate.h | 596 +++ khexedit/hexerror.cc | 69 + khexedit/hexerror.h | 57 + khexedit/hexmanagerwidget.cc | 370 ++ khexedit/hexmanagerwidget.h | 202 + khexedit/hexprinter.cc | 168 + khexedit/hexprinter.h | 108 + khexedit/hextoolwidget.cc | 416 ++ khexedit/hextoolwidget.h | 81 + khexedit/hexvalidator.cc | 329 ++ khexedit/hexvalidator.h | 63 + khexedit/hexviewwidget.cc | 2286 +++++++++ khexedit/hexviewwidget.h | 584 +++ khexedit/hi16-app-khexedit.png | Bin 0 -> 411 bytes khexedit/hi32-app-khexedit.png | Bin 0 -> 1146 bytes khexedit/hi48-app-khexedit.png | Bin 0 -> 1878 bytes khexedit/khexedit.desktop | 86 + khexedit/khexeditui.rc | 137 + khexedit/lib/Makefile.am | 39 + khexedit/lib/README | 36 + khexedit/lib/codecs/Makefile.am | 15 + khexedit/lib/codecs/README | 1 + khexedit/lib/codecs/kbinarybytecodec.cpp | 80 + khexedit/lib/codecs/kbinarybytecodec.h | 59 + khexedit/lib/codecs/kbytecodec.cpp | 63 + khexedit/lib/codecs/kcharcodec.cpp | 74 + khexedit/lib/codecs/kdecimalbytecodec.cpp | 92 + khexedit/lib/codecs/kdecimalbytecodec.h | 59 + khexedit/lib/codecs/kebcdic1047charcodec.cpp | 124 + khexedit/lib/codecs/kebcdic1047charcodec.h | 50 + khexedit/lib/codecs/khexadecimalbytecodec.cpp | 113 + khexedit/lib/codecs/khexadecimalbytecodec.h | 69 + khexedit/lib/codecs/koctalbytecodec.cpp | 80 + khexedit/lib/codecs/koctalbytecodec.h | 59 + khexedit/lib/codecs/ktextcharcodec.cpp | 236 + khexedit/lib/codecs/ktextcharcodec.h | 66 + khexedit/lib/controller/Makefile.am | 12 + khexedit/lib/controller/kchareditor.cpp | 58 + khexedit/lib/controller/kchareditor.h | 43 + khexedit/lib/controller/kcontroller.cpp | 34 + khexedit/lib/controller/kcontroller.h | 44 + khexedit/lib/controller/keditor.cpp | 197 + khexedit/lib/controller/keditor.h | 52 + khexedit/lib/controller/knavigator.cpp | 142 + khexedit/lib/controller/knavigator.h | 46 + khexedit/lib/controller/ktabcontroller.cpp | 70 + khexedit/lib/controller/ktabcontroller.h | 52 + khexedit/lib/controller/kvalueeditor.cpp | 226 + khexedit/lib/controller/kvalueeditor.h | 75 + khexedit/lib/helper.h | 31 + khexedit/lib/kadds.h | 36 + khexedit/lib/kbigbuffer.cpp | 216 + khexedit/lib/kbigbuffer.h | 119 + khexedit/lib/kbordercoltextexport.cpp | 47 + khexedit/lib/kbordercoltextexport.h | 40 + khexedit/lib/kbordercolumn.cpp | 82 + khexedit/lib/kbordercolumn.h | 52 + khexedit/lib/kbuffercoltextexport.cpp | 108 + khexedit/lib/kbuffercoltextexport.h | 73 + khexedit/lib/kbuffercolumn.cpp | 700 +++ khexedit/lib/kbuffercolumn.h | 253 + khexedit/lib/kbuffercoord.h | 293 ++ khexedit/lib/kbuffercursor.cpp | 365 ++ khexedit/lib/kbuffercursor.h | 172 + khexedit/lib/kbufferdrag.cpp | 237 + khexedit/lib/kbufferdrag.h | 76 + khexedit/lib/kbufferlayout.cpp | 240 + khexedit/lib/kbufferlayout.h | 196 + khexedit/lib/kbufferranges.cpp | 307 ++ khexedit/lib/kbufferranges.h | 130 + khexedit/lib/kbytecodec.h | 73 + khexedit/lib/kbytesedit.cpp | 162 + khexedit/lib/kbytesedit.h | 163 + khexedit/lib/kcharcodec.h | 55 + khexedit/lib/kcharcoltextexport.cpp | 71 + khexedit/lib/kcharcoltextexport.h | 50 + khexedit/lib/kcharcolumn.cpp | 61 + khexedit/lib/kcharcolumn.h | 116 + khexedit/lib/kcoltextexport.h | 40 + khexedit/lib/kcolumn.cpp | 60 + khexedit/lib/kcolumn.h | 126 + khexedit/lib/kcolumnsview.cpp | 236 + khexedit/lib/kcolumnsview.h | 168 + khexedit/lib/kcoordrange.h | 95 + khexedit/lib/kcoordrangelist.cpp | 78 + khexedit/lib/kcoordrangelist.h | 44 + khexedit/lib/kcursor.cpp | 49 + khexedit/lib/kcursor.h | 68 + khexedit/lib/kdatabuffer.cpp | 51 + khexedit/lib/kdatabuffer.h | 246 + khexedit/lib/kfixedsizebuffer.cpp | 272 ++ khexedit/lib/kfixedsizebuffer.h | 116 + khexedit/lib/khe.h | 95 + khexedit/lib/khechar.h | 44 + khexedit/lib/khexedit.cpp | 2032 ++++++++ khexedit/lib/khexedit.h | 562 +++ khexedit/lib/khexedit_export.h | 25 + khexedit/lib/koffsetcoltextexport.cpp | 61 + khexedit/lib/koffsetcoltextexport.h | 57 + khexedit/lib/koffsetcolumn.cpp | 110 + khexedit/lib/koffsetcolumn.h | 109 + khexedit/lib/koffsetformat.cpp | 48 + khexedit/lib/koffsetformat.h | 70 + khexedit/lib/kplainbuffer.cpp | 344 ++ khexedit/lib/kplainbuffer.h | 131 + khexedit/lib/krange.h | 123 + khexedit/lib/kreadonlybuffer.h | 45 + khexedit/lib/ksection.h | 108 + khexedit/lib/ksectionlist.cpp | 79 + khexedit/lib/ksectionlist.h | 44 + khexedit/lib/kselection.h | 178 + khexedit/lib/kvaluecoltextexport.cpp | 69 + khexedit/lib/kvaluecoltextexport.h | 47 + khexedit/lib/kvaluecolumn.cpp | 134 + khexedit/lib/kvaluecolumn.h | 92 + khexedit/lib/kwordbufferservice.cpp | 209 + khexedit/lib/kwordbufferservice.h | 137 + khexedit/lib/kwrappingrobuffer.cpp | 61 + khexedit/lib/kwrappingrobuffer.h | 85 + khexedit/listview.cc | 54 + khexedit/listview.h | 49 + khexedit/main.cc | 130 + khexedit/optiondialog.cc | 1224 +++++ khexedit/optiondialog.h | 269 ++ khexedit/parts/Makefile.am | 1 + khexedit/parts/README | 3 + khexedit/parts/kbytesedit/Makefile.am | 15 + khexedit/parts/kbytesedit/README | 23 + khexedit/parts/kbytesedit/kbyteseditwidget.cpp | 319 ++ khexedit/parts/kbytesedit/kbyteseditwidget.desktop | 52 + khexedit/parts/kbytesedit/kbyteseditwidget.h | 185 + khexedit/parts/kpart/Makefile.am | 21 + khexedit/parts/kpart/khebrowserextension.cpp | 95 + khexedit/parts/kpart/khebrowserextension.h | 58 + khexedit/parts/kpart/khepart.cpp | 213 + khexedit/parts/kpart/khepart.h | 95 + khexedit/parts/kpart/khepartfactory.cpp | 90 + khexedit/parts/kpart/khepartfactory.h | 47 + khexedit/parts/kpart/khexedit2part.desktop | 101 + khexedit/parts/kpart/khexedit2partui.rc | 42 + khexedit/pics/Makefile.am | 3 + khexedit/pics/hexdrag.png | Bin 0 -> 459 bytes khexedit/pics/hexmask.png | Bin 0 -> 188 bytes khexedit/pics/hexwrite.png | Bin 0 -> 381 bytes khexedit/printdialogpage.cc | 386 ++ khexedit/printdialogpage.h | 73 + khexedit/progress.h | 130 + khexedit/searchbar.cc | 188 + khexedit/searchbar.h | 73 + khexedit/statusbarprogress.cc | 374 ++ khexedit/statusbarprogress.h | 159 + khexedit/stringdialog.cc | 412 ++ khexedit/stringdialog.h | 110 + khexedit/toplevel.cc | 1366 ++++++ khexedit/toplevel.h | 279 ++ khexedit/version.h | 32 + kjots/ANNOUNCE | 26 + kjots/BUGS | 6 + kjots/CHANGES | 75 + kjots/KJotsMain.cpp | 1199 +++++ kjots/KJotsMain.h | 165 + kjots/KJotsSettings.kcfgc | 8 + kjots/Kjots.desktop | 80 + kjots/Makefile.am | 28 + kjots/README | 33 + kjots/confpagefont.ui | 38 + kjots/confpagemisc.ui | 152 + kjots/icons/Makefile.am | 6 + kjots/icons/README | 24 + kjots/icons/filedel.png | Bin 0 -> 892 bytes kjots/icons/hi16-app-kjots.png | Bin 0 -> 902 bytes kjots/icons/hi22-app-kjots.png | Bin 0 -> 1318 bytes kjots/icons/hi32-app-kjots.png | Bin 0 -> 2287 bytes kjots/icons/hi48-app-kjots.png | Bin 0 -> 3755 bytes kjots/icons/hi64-app-kjots.png | Bin 0 -> 5426 bytes kjots/kjots.kcfg | 35 + kjots/kjotsbookmarks.cpp | 51 + kjots/kjotsbookmarks.h | 51 + kjots/kjotsedit.cpp | 150 + kjots/kjotsedit.h | 54 + kjots/kjotsentry.cpp | 1234 +++++ kjots/kjotsentry.h | 179 + kjots/kjotsui.rc | 41 + kjots/main.cpp | 98 + klaptopdaemon/Makefile.am | 49 + klaptopdaemon/README | 8 + klaptopdaemon/acpi.cpp | 281 ++ klaptopdaemon/acpi.h | 72 + klaptopdaemon/acpi_helper.cpp | 325 ++ klaptopdaemon/apm.cpp | 285 ++ klaptopdaemon/apm.h | 71 + klaptopdaemon/applnk/.directory | 48 + klaptopdaemon/applnk/Makefile.am | 4 + klaptopdaemon/applnk/klaptopdaemon.desktop | 116 + klaptopdaemon/applnk/laptop.desktop | 135 + klaptopdaemon/applnk/pcmcia.desktop | 84 + klaptopdaemon/battery.cpp | 390 ++ klaptopdaemon/battery.h | 100 + klaptopdaemon/buttons.cpp | 620 +++ klaptopdaemon/buttons.h | 92 + klaptopdaemon/checkcrc.h | 53 + klaptopdaemon/configure.in.bot | 9 + klaptopdaemon/configure.in.in | 49 + klaptopdaemon/daemon_state.cpp | 282 ++ klaptopdaemon/daemon_state.h | 141 + klaptopdaemon/daemondock.cpp | 756 +++ klaptopdaemon/daemondock.h | 108 + klaptopdaemon/kpcmcia.cpp | 547 +++ klaptopdaemon/kpcmcia.h | 214 + klaptopdaemon/kpcmciainfo.cpp | 313 ++ klaptopdaemon/kpcmciainfo.h | 116 + klaptopdaemon/krichtextlabel.cpp | 112 + klaptopdaemon/krichtextlabel.h | 65 + klaptopdaemon/laptop_check.cpp | 53 + klaptopdaemon/laptop_daemon.cpp | 1083 +++++ klaptopdaemon/laptop_daemon.h | 186 + klaptopdaemon/linux/bulkmem.h | 184 + klaptopdaemon/linux/ciscode.h | 96 + klaptopdaemon/linux/cisreg.h | 105 + klaptopdaemon/linux/cistpl.h | 543 +++ klaptopdaemon/linux/cs.h | 455 ++ klaptopdaemon/linux/cs_types.h | 50 + klaptopdaemon/linux/driver_ops.h | 71 + klaptopdaemon/linux/ds.h | 142 + klaptopdaemon/linux/ftl.h | 62 + klaptopdaemon/linux/k_compat.h | 246 + klaptopdaemon/linux/mem_op.h | 120 + klaptopdaemon/linux/memory.h | 30 + klaptopdaemon/linux/ss.h | 113 + klaptopdaemon/linux/version.h | 4 + klaptopdaemon/main.cpp | 305 ++ klaptopdaemon/main.h | 82 + klaptopdaemon/makecrc.cpp | 38 + klaptopdaemon/pcmcia.cpp | 122 + klaptopdaemon/pcmcia.h | 70 + klaptopdaemon/pics/Makefile.am | 6 + klaptopdaemon/pics/README | 36 + klaptopdaemon/pics/actions/Makefile.am | 3 + .../actions/cr16-action-alt2_laptop_nobattery.png | Bin 0 -> 395 bytes .../actions/cr16-action-alt2_laptop_nocharge.png | Bin 0 -> 280 bytes .../pics/actions/cr16-action-alt2_laptop_power.png | Bin 0 -> 317 bytes .../actions/cr16-action-alt3_laptop_nocharge.png | Bin 0 -> 280 bytes .../pics/actions/cr16-action-alt3_laptop_power.png | Bin 0 -> 284 bytes .../actions/cr16-action-alt_laptop_nocharge.png | Bin 0 -> 795 bytes .../pics/actions/cr16-action-alt_laptop_power.png | Bin 0 -> 775 bytes .../pics/actions/cr16-action-laptop_charge.png | Bin 0 -> 296 bytes .../pics/actions/cr16-action-laptop_nobattery.png | Bin 0 -> 352 bytes .../pics/actions/cr16-action-laptop_nocharge.png | Bin 0 -> 305 bytes klaptopdaemon/pics/actions/cr16-action-power.png | Bin 0 -> 335 bytes .../pics/actions/cr22-action-laptop_charge.png | Bin 0 -> 966 bytes .../pics/actions/cr22-action-laptop_nobattery.png | Bin 0 -> 1022 bytes .../pics/actions/cr22-action-laptop_nocharge.png | Bin 0 -> 395 bytes .../pics/actions/cr22-action-laptop_power.png | Bin 0 -> 832 bytes klaptopdaemon/pics/actions/cr32-action-power.png | Bin 0 -> 421 bytes klaptopdaemon/pics/cr128-app-laptop_battery.png | Bin 0 -> 10017 bytes klaptopdaemon/pics/cr16-app-laptop_battery.png | Bin 0 -> 912 bytes klaptopdaemon/pics/cr16-app-laptop_pcmcia.png | Bin 0 -> 477 bytes klaptopdaemon/pics/cr32-app-laptop_battery.png | Bin 0 -> 2374 bytes klaptopdaemon/pics/cr32-app-laptop_pcmcia.png | Bin 0 -> 1375 bytes klaptopdaemon/pics/cr48-app-laptop_battery.png | Bin 0 -> 3544 bytes klaptopdaemon/pics/cr48-app-laptop_pcmcia.png | Bin 0 -> 1751 bytes klaptopdaemon/pics/cr64-app-laptop_battery.png | Bin 0 -> 4730 bytes klaptopdaemon/pics/crsc-app-laptop_battery.svgz | Bin 0 -> 4371 bytes klaptopdaemon/portable.cpp | 3087 ++++++++++++ klaptopdaemon/portable.h | 147 + klaptopdaemon/power.cpp | 587 +++ klaptopdaemon/power.h | 98 + klaptopdaemon/profile.cpp | 424 ++ klaptopdaemon/profile.h | 82 + klaptopdaemon/smapi.h | 54 + klaptopdaemon/smapibios.h | 93 + klaptopdaemon/smapidev.c | 743 +++ klaptopdaemon/smapidev.h | 273 ++ klaptopdaemon/sony.cpp | 200 + klaptopdaemon/sony.h | 71 + klaptopdaemon/thinkpad_common.h | 127 + klaptopdaemon/version.h | 19 + klaptopdaemon/wake_laptop.cpp | 39 + klaptopdaemon/warning.cpp | 602 +++ klaptopdaemon/warning.h | 106 + klaptopdaemon/xautolock.cc | 277 ++ klaptopdaemon/xautolock.h | 77 + klaptopdaemon/xautolock_c.h | 76 + klaptopdaemon/xautolock_diy.c | 289 ++ klaptopdaemon/xautolock_engine.c | 419 ++ kmilo/Makefile.am | 18 + kmilo/README | 17 + kmilo/TODO | 7 + kmilo/asus/Makefile.am | 37 + kmilo/asus/README | 43 + kmilo/asus/asus.cpp | 213 + kmilo/asus/asus.h | 88 + kmilo/asus/kmilo_asus.desktop | 97 + kmilo/configure.in.in | 60 + kmilo/delli8k/Makefile.am | 36 + kmilo/delli8k/README | 98 + kmilo/delli8k/delli8k.cpp | 256 + kmilo/delli8k/delli8k.h | 89 + kmilo/delli8k/i8k.h | 46 + kmilo/delli8k/kmilo_delli8k.desktop | 96 + kmilo/demo/Makefile.am | 32 + kmilo/demo/demo.cpp | 56 + kmilo/demo/demo.h | 39 + kmilo/demo/kmilo_demo.desktop | 110 + kmilo/generic/Makefile.am | 34 + kmilo/generic/README | 38 + kmilo/generic/generic_monitor.cpp | 324 ++ kmilo/generic/generic_monitor.h | 94 + kmilo/generic/kmilo_generic.desktop | 108 + kmilo/kmilo_kvaio/Makefile.am | 39 + kmilo/kmilo_kvaio/README.sonypi.h | 18 + kmilo/kmilo_kvaio/kcmkvaio/Makefile.am | 15 + kmilo/kmilo_kvaio/kcmkvaio/kcmkvaio_general.ui | 273 ++ kmilo/kmilo_kvaio/kcmkvaio/kcmkvaio_general.ui.h | 15 + kmilo/kmilo_kvaio/kcmkvaio/kvaio.desktop | 146 + kmilo/kmilo_kvaio/kcmkvaio/main.cpp | 176 + kmilo/kmilo_kvaio/kcmkvaio/main.h | 53 + kmilo/kmilo_kvaio/kmilo_kvaio.cpp | 68 + kmilo/kmilo_kvaio/kmilo_kvaio.desktop | 106 + kmilo/kmilo_kvaio/kmilo_kvaio.h | 66 + kmilo/kmilo_kvaio/kvaio.cpp | 606 +++ kmilo/kmilo_kvaio/kvaio.h | 113 + kmilo/kmilo_kvaio/kvaiodriverinterface.cpp | 221 + kmilo/kmilo_kvaio/kvaiodriverinterface.h | 62 + kmilo/kmilo_kvaio/sonypi.h | 158 + kmilo/kmilod/Makefile.am | 43 + kmilo/kmilod/defaultskin.cpp | 107 + kmilo/kmilod/defaultskin.h | 56 + kmilo/kmilod/defaultwidget.ui | 195 + kmilo/kmilod/displayskin.cpp | 34 + kmilo/kmilod/displayskin.h | 47 + kmilo/kmilod/kmilod.cpp | 227 + kmilo/kmilod/kmilod.desktop | 59 + kmilo/kmilod/kmilod.h | 72 + kmilo/kmilod/kmilointerface.cpp | 26 + kmilo/kmilod/kmilointerface.h | 57 + kmilo/kmilod/kmilopluginsvc.desktop | 9 + kmilo/kmilod/monitor.cpp | 44 + kmilo/kmilod/monitor.h | 98 + kmilo/powerbook/Makefile.am | 34 + kmilo/powerbook/kmilo_powerbook.desktop | 105 + kmilo/powerbook/pb_monitor.cpp | 127 + kmilo/powerbook/pb_monitor.h | 42 + kmilo/powerbook2/Makefile.am | 34 + kmilo/powerbook2/kmilo_powerbook.desktop | 106 + kmilo/powerbook2/pb_monitor.cpp | 165 + kmilo/powerbook2/pb_monitor.h | 55 + kmilo/thinkpad/Makefile.am | 36 + kmilo/thinkpad/README | 61 + kmilo/thinkpad/kcmthinkpad/Makefile.am | 15 + kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui | 307 ++ .../thinkpad/kcmthinkpad/kcmthinkpad_general.ui.h | 36 + kmilo/thinkpad/kcmthinkpad/main.cpp | 189 + kmilo/thinkpad/kcmthinkpad/main.h | 49 + kmilo/thinkpad/kcmthinkpad/thinkpad.desktop | 145 + kmilo/thinkpad/kmilo_thinkpad.desktop | 101 + kmilo/thinkpad/thinkpad.cpp | 556 +++ kmilo/thinkpad/thinkpad.h | 208 + kregexpeditor/Comments | 4 + kregexpeditor/KMultiFormListBox/Makefile.am | 15 + kregexpeditor/KMultiFormListBox/TODO | 1 + kregexpeditor/KMultiFormListBox/ccp.cpp | 83 + kregexpeditor/KMultiFormListBox/ccp.h | 61 + kregexpeditor/KMultiFormListBox/idx.xbm | 5 + kregexpeditor/KMultiFormListBox/indexWindow.cpp | 97 + kregexpeditor/KMultiFormListBox/indexWindow.h | 83 + .../kmultiformlistbox-multivisible.cpp | 305 ++ .../kmultiformlistbox-multivisible.h | 135 + .../KMultiFormListBox/kmultiformlistbox-shower.h | 53 + .../kmultiformlistbox-windowed.cpp | 213 + .../KMultiFormListBox/kmultiformlistbox-windowed.h | 83 + .../KMultiFormListBox/kmultiformlistbox.cpp | 104 + .../KMultiFormListBox/kmultiformlistbox.h | 125 + .../KMultiFormListBox/kmultiformlistboxentry.cpp | 44 + .../KMultiFormListBox/kmultiformlistboxentry.h | 73 + .../KMultiFormListBox/kmultiformlistboxfactory.cpp | 26 + .../KMultiFormListBox/kmultiformlistboxfactory.h | 70 + kregexpeditor/KMultiFormListBox/widgetwindow.cpp | 117 + kregexpeditor/KMultiFormListBox/widgetwindow.h | 60 + .../KMultiFormListBox/windowlistboxitem.cpp | 45 + .../KMultiFormListBox/windowlistboxitem.h | 44 + kregexpeditor/KWidgetStreamer/Makefile.am | 9 + kregexpeditor/KWidgetStreamer/kwidgetstreamer.cpp | 177 + kregexpeditor/KWidgetStreamer/kwidgetstreamer.h | 74 + kregexpeditor/Makefile.am | 65 + kregexpeditor/TODO | 49 + kregexpeditor/altnregexp.cpp | 102 + kregexpeditor/altnregexp.h | 47 + kregexpeditor/altnwidget.cpp | 254 + kregexpeditor/altnwidget.h | 65 + kregexpeditor/auxbuttons.cpp | 121 + kregexpeditor/auxbuttons.h | 60 + kregexpeditor/characterswidget.cpp | 447 ++ kregexpeditor/characterswidget.h | 144 + kregexpeditor/charselector.cpp | 185 + kregexpeditor/charselector.h | 52 + kregexpeditor/compoundregexp.cpp | 115 + kregexpeditor/compoundregexp.h | 54 + kregexpeditor/compoundwidget.cpp | 324 ++ kregexpeditor/compoundwidget.h | 104 + kregexpeditor/concregexp.cpp | 157 + kregexpeditor/concregexp.h | 49 + kregexpeditor/concwidget.cpp | 400 ++ kregexpeditor/concwidget.h | 69 + kregexpeditor/dcbutton.cpp | 37 + kregexpeditor/dcbutton.h | 42 + kregexpeditor/dotregexp.cpp | 39 + kregexpeditor/dotregexp.h | 41 + kregexpeditor/drag.cpp | 77 + kregexpeditor/drag.h | 45 + kregexpeditor/dragaccepter.cpp | 139 + kregexpeditor/dragaccepter.h | 53 + kregexpeditor/editorwindow.cpp | 453 ++ kregexpeditor/editorwindow.h | 269 ++ kregexpeditor/emacsregexpconverter.cpp | 253 + kregexpeditor/emacsregexpconverter.h | 43 + kregexpeditor/errormap.cpp | 73 + kregexpeditor/errormap.h | 36 + kregexpeditor/extractrc-from-regexp | 85 + kregexpeditor/gen_qregexplexer.cpp | 1980 ++++++++ kregexpeditor/gen_qregexpparser.cc | 1447 ++++++ kregexpeditor/gen_qregexpparser.hh | 93 + kregexpeditor/hi128-app-kregexpeditor.png | Bin 0 -> 6933 bytes kregexpeditor/hi16-app-kregexpeditor.png | Bin 0 -> 801 bytes kregexpeditor/hi22-app-kregexpeditor.png | Bin 0 -> 1235 bytes kregexpeditor/hi32-app-kregexpeditor.png | Bin 0 -> 1391 bytes kregexpeditor/hi48-app-kregexpeditor.png | Bin 0 -> 2090 bytes kregexpeditor/hi64-app-kregexpeditor.png | Bin 0 -> 2895 bytes kregexpeditor/infopage.cpp | 97 + kregexpeditor/infopage.h | 37 + kregexpeditor/kregexpeditor.desktop | 76 + kregexpeditor/kregexpeditor.svgz | Bin 0 -> 1098 bytes kregexpeditor/kregexpeditorfactory.cpp | 25 + kregexpeditor/kregexpeditorgui.cpp | 161 + kregexpeditor/kregexpeditorgui.desktop | 62 + kregexpeditor/kregexpeditorgui.h | 93 + kregexpeditor/kregexpeditorprivate.cpp | 424 ++ kregexpeditor/kregexpeditorprivate.h | 106 + kregexpeditor/limitedcharlineedit.cpp | 75 + kregexpeditor/limitedcharlineedit.h | 43 + kregexpeditor/lookaheadregexp.cpp | 72 + kregexpeditor/lookaheadregexp.h | 49 + kregexpeditor/lookaheadwidget.cpp | 110 + kregexpeditor/lookaheadwidget.h | 51 + kregexpeditor/main.cpp | 68 + kregexpeditor/multicontainerwidget.cpp | 265 + kregexpeditor/multicontainerwidget.h | 50 + kregexpeditor/myfontmetrics.cpp | 31 + kregexpeditor/myfontmetrics.h | 27 + kregexpeditor/pair.h | 37 + kregexpeditor/picts/Makefile.am | 2 + kregexpeditor/picts/altn.png | Bin 0 -> 310 bytes kregexpeditor/picts/anychar.png | Bin 0 -> 616 bytes kregexpeditor/picts/autoverify.png | Bin 0 -> 142 bytes kregexpeditor/picts/begline.png | Bin 0 -> 244 bytes kregexpeditor/picts/characters.png | Bin 0 -> 240 bytes kregexpeditor/picts/compound.png | Bin 0 -> 285 bytes kregexpeditor/picts/endline.png | Bin 0 -> 245 bytes kregexpeditor/picts/error.png | Bin 0 -> 234 bytes kregexpeditor/picts/neglookahead.png | Bin 0 -> 297 bytes kregexpeditor/picts/nonwordboundary.png | Bin 0 -> 225 bytes kregexpeditor/picts/poslookahead.png | Bin 0 -> 297 bytes kregexpeditor/picts/repeat.png | Bin 0 -> 632 bytes kregexpeditor/picts/select.png | Bin 0 -> 742 bytes kregexpeditor/picts/text.png | Bin 0 -> 338 bytes kregexpeditor/picts/verify.png | Bin 0 -> 141 bytes kregexpeditor/picts/wordboundary.png | Bin 0 -> 210 bytes kregexpeditor/positionregexp.cpp | 53 + kregexpeditor/positionregexp.h | 46 + kregexpeditor/predefined/General/Makefile.am | 5 + kregexpeditor/predefined/General/anything.regexp | 11 + kregexpeditor/predefined/General/spaces.regexp | 11 + kregexpeditor/predefined/Makefile.am | 1 + kregexpeditor/predefined/README | 2 + kregexpeditor/qregexpparser.l | 319 ++ kregexpeditor/qregexpparser.y | 203 + kregexpeditor/qt-only/clean | 14 + kregexpeditor/qt-only/compat.cpp | 115 + kregexpeditor/qt-only/compat.h | 85 + kregexpeditor/qt-only/compile | 28 + kregexpeditor/qt-only/qt-only.pro | 137 + kregexpeditor/qt-only/win-release.bat | 7 + kregexpeditor/qtregexpconverter.cpp | 299 ++ kregexpeditor/qtregexpconverter.h | 43 + kregexpeditor/qtregexphighlighter.cpp | 71 + kregexpeditor/qtregexphighlighter.h | 34 + kregexpeditor/regexp.cpp | 95 + kregexpeditor/regexp.h | 72 + kregexpeditor/regexpbuttons.cpp | 217 + kregexpeditor/regexpbuttons.h | 70 + kregexpeditor/regexpconverter.cpp | 93 + kregexpeditor/regexpconverter.h | 79 + kregexpeditor/regexphighlighter.cpp | 44 + kregexpeditor/regexphighlighter.h | 38 + kregexpeditor/regexpwidget.cpp | 227 + kregexpeditor/regexpwidget.h | 203 + kregexpeditor/repeatregexp.cpp | 94 + kregexpeditor/repeatregexp.h | 49 + kregexpeditor/repeatwidget.cpp | 326 ++ kregexpeditor/repeatwidget.h | 103 + kregexpeditor/scrollededitorwindow.cpp | 144 + kregexpeditor/scrollededitorwindow.h | 92 + kregexpeditor/selectablelineedit.cpp | 73 + kregexpeditor/selectablelineedit.h | 53 + kregexpeditor/singlecontainerwidget.cpp | 132 + kregexpeditor/singlecontainerwidget.h | 53 + kregexpeditor/test-without-dl/Makefile.am | 8 + kregexpeditor/test-without-dl/main.cpp | 66 + kregexpeditor/textrangeregexp.cpp | 143 + kregexpeditor/textrangeregexp.h | 75 + kregexpeditor/textregexp.cpp | 81 + kregexpeditor/textregexp.h | 50 + kregexpeditor/textwidget.cpp | 157 + kregexpeditor/textwidget.h | 63 + kregexpeditor/triple.h | 40 + kregexpeditor/userdefinedregexps.cpp | 266 + kregexpeditor/userdefinedregexps.h | 75 + kregexpeditor/util.cpp | 58 + kregexpeditor/util.h | 34 + kregexpeditor/verifier.cpp | 117 + kregexpeditor/verifier.h | 61 + kregexpeditor/verifybuttons.cpp | 214 + kregexpeditor/verifybuttons.h | 79 + kregexpeditor/widgetfactory.cpp | 209 + kregexpeditor/widgetfactory.h | 60 + kregexpeditor/zerowidgets.cpp | 145 + kregexpeditor/zerowidgets.h | 125 + ksim/AUTHORS | 2 + ksim/BUGS | 3 + ksim/COPYING | 340 ++ ksim/ChangeLog | 363 ++ ksim/Makefile.am | 34 + ksim/README | 42 + ksim/TODO | 5 + ksim/baselist.h | 97 + ksim/configure.in.in | 36 + ksim/generalprefs.cpp | 574 +++ ksim/generalprefs.h | 185 + ksim/ksim.cpp | 129 + ksim/ksim.desktop | 134 + ksim/ksim.h | 67 + ksim/ksim_panelextensionrc | 81 + ksim/ksimframe.cpp | 94 + ksim/ksimframe.h | 63 + ksim/ksimpref.cpp | 260 + ksim/ksimpref.h | 112 + ksim/ksimsysinfo.cpp | 325 ++ ksim/ksimsysinfo.h | 70 + ksim/ksimview.cpp | 467 ++ ksim/ksimview.h | 112 + ksim/library/Makefile.am | 25 + ksim/library/chart.cpp | 627 +++ ksim/library/chart.h | 184 + ksim/library/common.cpp | 102 + ksim/library/common.h | 134 + ksim/library/ksimconfig.cpp | 427 ++ ksim/library/ksimconfig.h | 109 + ksim/library/label.cpp | 301 ++ ksim/library/label.h | 210 + ksim/library/led.cpp | 349 ++ ksim/library/led.h | 193 + ksim/library/pluginglobal.cpp | 207 + ksim/library/pluginglobal.h | 161 + ksim/library/pluginloader.cpp | 326 ++ ksim/library/pluginloader.h | 183 + ksim/library/pluginmodule.cpp | 174 + ksim/library/pluginmodule.h | 205 + ksim/library/progress.cpp | 231 + ksim/library/progress.h | 181 + ksim/library/themeloader.cpp | 1266 +++++ ksim/library/themeloader.h | 511 ++ ksim/library/themetypes.h | 81 + ksim/monitorprefs.cpp | 98 + ksim/monitorprefs.h | 45 + ksim/monitors/Makefile.am | 9 + ksim/monitors/cpu/Makefile.am | 16 + ksim/monitors/cpu/cpu.desktop | 94 + ksim/monitors/cpu/cr16-device-ksim_cpu.png | Bin 0 -> 249 bytes ksim/monitors/cpu/ksimcpu.cpp | 514 ++ ksim/monitors/cpu/ksimcpu.h | 228 + ksim/monitors/disk/Makefile.am | 15 + ksim/monitors/disk/configure.in.in | 13 + ksim/monitors/disk/disk.desktop | 106 + ksim/monitors/disk/ksimdisk.cpp | 570 +++ ksim/monitors/disk/ksimdisk.h | 154 + ksim/monitors/filesystem/DFree.desktop | 87 + ksim/monitors/filesystem/Makefile.am | 16 + ksim/monitors/filesystem/configure.in.in | 2 + ksim/monitors/filesystem/filesystemstats.cpp | 224 + ksim/monitors/filesystem/filesystemstats.h | 40 + ksim/monitors/filesystem/filesystemwidget.cpp | 232 + ksim/monitors/filesystem/filesystemwidget.h | 78 + ksim/monitors/filesystem/fsystemconfig.cpp | 184 + ksim/monitors/filesystem/fsystemconfig.h | 58 + ksim/monitors/filesystem/fsystemiface.h | 32 + ksim/monitors/filesystem/ksimfsystem.cpp | 202 + ksim/monitors/filesystem/ksimfsystem.h | 76 + ksim/monitors/i8k/Makefile.am | 15 + ksim/monitors/i8k/i8k.desktop | 62 + ksim/monitors/i8k/ksimi8k.cpp | 257 + ksim/monitors/i8k/ksimi8k.h | 102 + ksim/monitors/lm_sensors/Lm_sensors.desktop | 84 + ksim/monitors/lm_sensors/Makefile.am | 26 + ksim/monitors/lm_sensors/NVCtrl.c | 357 ++ ksim/monitors/lm_sensors/NVCtrl.h | 807 ++++ ksim/monitors/lm_sensors/NVCtrlLib.h | 184 + ksim/monitors/lm_sensors/ksimsensors.cpp | 189 + ksim/monitors/lm_sensors/ksimsensors.h | 91 + ksim/monitors/lm_sensors/ksimsensorsiface.h | 33 + ksim/monitors/lm_sensors/nv_control.h | 205 + ksim/monitors/lm_sensors/sensorbase.cpp | 254 + ksim/monitors/lm_sensors/sensorbase.h | 175 + ksim/monitors/lm_sensors/sensorsconfig.cpp | 241 + ksim/monitors/lm_sensors/sensorsconfig.h | 69 + ksim/monitors/mail/Makefile.am | 15 + ksim/monitors/mail/ksimmail.cpp | 160 + ksim/monitors/mail/ksimmail.h | 90 + ksim/monitors/mail/mail.desktop | 119 + ksim/monitors/net/Makefile.am | 14 + ksim/monitors/net/Net.desktop | 112 + ksim/monitors/net/ksimnet.cpp | 672 +++ ksim/monitors/net/ksimnet.h | 90 + ksim/monitors/net/netconfig.cpp | 296 ++ ksim/monitors/net/netconfig.h | 67 + ksim/monitors/net/netdevices.h | 218 + ksim/monitors/net/netdialog.cpp | 328 ++ ksim/monitors/net/netdialog.h | 85 + ksim/monitors/snmp/Makefile.am | 16 + ksim/monitors/snmp/Snmp.desktop | 70 + ksim/monitors/snmp/browsedialog.cpp | 147 + ksim/monitors/snmp/browsedialog.h | 71 + ksim/monitors/snmp/browsedialogbase.ui | 262 + ksim/monitors/snmp/chartmonitor.cpp | 83 + ksim/monitors/snmp/chartmonitor.h | 54 + ksim/monitors/snmp/configpage.cpp | 313 ++ ksim/monitors/snmp/configpage.h | 120 + ksim/monitors/snmp/configure.in.in | 40 + ksim/monitors/snmp/configwidget.ui | 215 + ksim/monitors/snmp/hostconfig.cpp | 152 + ksim/monitors/snmp/hostconfig.h | 86 + ksim/monitors/snmp/hostdialog.cpp | 193 + ksim/monitors/snmp/hostdialog.h | 59 + ksim/monitors/snmp/hostdialogbase.ui | 526 ++ ksim/monitors/snmp/identifier.cpp | 129 + ksim/monitors/snmp/identifier.h | 72 + ksim/monitors/snmp/labelmonitor.cpp | 45 + ksim/monitors/snmp/labelmonitor.h | 52 + ksim/monitors/snmp/monitor.cpp | 96 + ksim/monitors/snmp/monitor.h | 77 + ksim/monitors/snmp/monitorconfig.cpp | 183 + ksim/monitors/snmp/monitorconfig.h | 84 + ksim/monitors/snmp/monitordialog.cpp | 178 + ksim/monitors/snmp/monitordialog.h | 60 + ksim/monitors/snmp/monitordialogbase.ui | 440 ++ ksim/monitors/snmp/pdu.cpp | 98 + ksim/monitors/snmp/pdu.h | 60 + ksim/monitors/snmp/plugin.cpp | 52 + ksim/monitors/snmp/plugin.h | 49 + ksim/monitors/snmp/probedialog.cpp | 117 + ksim/monitors/snmp/probedialog.h | 87 + ksim/monitors/snmp/proberesultdialog.cpp | 55 + ksim/monitors/snmp/proberesultdialog.h | 49 + ksim/monitors/snmp/proberesultdialogbase.ui | 124 + ksim/monitors/snmp/session.cpp | 283 ++ ksim/monitors/snmp/session.h | 64 + ksim/monitors/snmp/snmp.cpp | 320 ++ ksim/monitors/snmp/snmp.h | 165 + ksim/monitors/snmp/snmp_p.h | 59 + ksim/monitors/snmp/snmplib.cpp | 151 + ksim/monitors/snmp/snmplib.h | 143 + ksim/monitors/snmp/value.cpp | 333 ++ ksim/monitors/snmp/value.h | 106 + ksim/monitors/snmp/value_p.h | 63 + ksim/monitors/snmp/view.cpp | 80 + ksim/monitors/snmp/view.h | 55 + ksim/monitors/snmp/walker.cpp | 121 + ksim/monitors/snmp/walker.h | 82 + ksim/pics/Makefile.am | 2 + ksim/pics/cr16-app-ksim.png | Bin 0 -> 1086 bytes ksim/pics/cr32-app-ksim.png | Bin 0 -> 3314 bytes ksim/pics/cr48-app-ksim.png | Bin 0 -> 6222 bytes ksim/pics/misc/Makefile.am | 5 + ksim/pics/misc/clock.png | Bin 0 -> 875 bytes ksim/pics/misc/uptime.png | Bin 0 -> 654 bytes ksim/systeminfo.cpp | 277 ++ ksim/systeminfo.h | 137 + ksim/themeprefs.cpp | 272 ++ ksim/themeprefs.h | 115 + ksim/themes/Makefile.am | 1 + ksim/themes/ksim/Makefile.am | 24 + ksim/themes/ksim/bg_chart.png | Bin 0 -> 263 bytes ksim/themes/ksim/bg_grid.png | Bin 0 -> 172 bytes ksim/themes/ksim/bg_meter.png | Bin 0 -> 246 bytes ksim/themes/ksim/bg_panel.png | Bin 0 -> 245 bytes ksim/themes/ksim/decal_net_leds.png | Bin 0 -> 285 bytes ksim/themes/ksim/frame_bottom.png | Bin 0 -> 206 bytes ksim/themes/ksim/frame_left.png | Bin 0 -> 153 bytes ksim/themes/ksim/frame_right.png | Bin 0 -> 153 bytes ksim/themes/ksim/frame_top.png | Bin 0 -> 211 bytes ksim/themes/ksim/gkrellmrc | 47 + ksim/themes/ksim/gkrellmrc_ksim | 47 + ksim/themes/ksim/host/Makefile.am | 4 + ksim/themes/ksim/host/bg_meter.png | Bin 0 -> 246 bytes ksim/themes/ksim/krell_meter.png | Bin 0 -> 544 bytes ksim/themes/ksim/krell_panel.png | Bin 0 -> 149 bytes ksim/themes/ksim/krell_slider.png | Bin 0 -> 314 bytes ksim/themes/ksim/mail/Makefile.am | 3 + ksim/themes/ksim/mail/decal_mail.png | Bin 0 -> 3935 bytes ksim/themes/ksim/mail/krell_mail.png | Bin 0 -> 3942 bytes ksim/themes/ksim/mail/krell_mail_daemon.png | Bin 0 -> 126 bytes ktimer/Makefile.am | 24 + ktimer/hi128-app-ktimer.png | Bin 0 -> 17753 bytes ktimer/hi16-app-ktimer.png | Bin 0 -> 875 bytes ktimer/hi32-app-ktimer.png | Bin 0 -> 2458 bytes ktimer/hi48-app-ktimer.png | Bin 0 -> 4736 bytes ktimer/ktimer.cpp | 516 ++ ktimer/ktimer.desktop | 63 + ktimer/ktimer.h | 113 + ktimer/main.cpp | 46 + ktimer/prefwidget.ui | 278 ++ kwallet/Makefile.am | 26 + kwallet/TODO | 13 + kwallet/allyourbase.cpp | 733 +++ kwallet/allyourbase.h | 178 + kwallet/hi128-app-kwalletmanager.png | Bin 0 -> 24094 bytes kwallet/hi128-app-kwalletmanager2.png | Bin 0 -> 28434 bytes kwallet/hi16-app-kwalletmanager.png | Bin 0 -> 1209 bytes kwallet/hi16-app-kwalletmanager2.png | Bin 0 -> 1139 bytes kwallet/hi22-app-kwalletmanager.png | Bin 0 -> 1601 bytes kwallet/hi32-app-kwalletmanager.png | Bin 0 -> 3273 bytes kwallet/hi32-app-kwalletmanager2.png | Bin 0 -> 3225 bytes kwallet/hi48-app-kwalletmanager.png | Bin 0 -> 6355 bytes kwallet/hi48-app-kwalletmanager2.png | Bin 0 -> 6332 bytes kwallet/hi64-app-kwalletmanager.png | Bin 0 -> 9728 bytes kwallet/hi64-app-kwalletmanager2.png | Bin 0 -> 9702 bytes kwallet/icons/Makefile.am | 5 + kwallet/icons/cr22-action-folder_closed.png | Bin 0 -> 1149 bytes kwallet/icons/cr22-action-folder_open.png | Bin 0 -> 1349 bytes kwallet/icons/cr22-action-wallet_closed.png | Bin 0 -> 997 bytes kwallet/icons/cr22-action-wallet_open.png | Bin 0 -> 1098 bytes kwallet/kbetterthankdialogbase.ui | 154 + kwallet/kbetterthankdialogbase.ui.h | 50 + kwallet/konfigurator/Makefile.am | 15 + kwallet/konfigurator/konfigurator.cpp | 323 ++ kwallet/konfigurator/konfigurator.h | 57 + kwallet/konfigurator/kwallet_config.desktop | 47 + kwallet/konfigurator/kwalletconfig.desktop | 152 + kwallet/konfigurator/kwalletmanager_show.desktop | 60 + kwallet/konfigurator/walletconfigwidget.ui | 499 ++ kwallet/kwalleteditor.cpp | 1143 +++++ kwallet/kwalleteditor.h | 110 + kwallet/kwalleteditor.rc | 17 + kwallet/kwalletmanager-kwalletd.desktop | 60 + kwallet/kwalletmanager.cpp | 423 ++ kwallet/kwalletmanager.desktop | 63 + kwallet/kwalletmanager.h | 84 + kwallet/kwalletmanager.rc | 14 + kwallet/kwalletpopup.cpp | 110 + kwallet/kwalletpopup.h | 54 + kwallet/kwmapeditor.cpp | 187 + kwallet/kwmapeditor.h | 61 + kwallet/main.cpp | 100 + kwallet/walletwidget.ui | 416 ++ superkaramba/AUTHORS | 49 + superkaramba/COPYING | 280 ++ superkaramba/ChangeLog | 710 +++ superkaramba/Doxyfile | 0 superkaramba/INSTALL | 167 + superkaramba/Makefile.am | 4 + superkaramba/NEWS | 0 superkaramba/README | 42 + superkaramba/TODO | 1 + superkaramba/configure.in.bot | 7 + superkaramba/configure.in.in | 77 + superkaramba/doc/Makefile.am | 6 + superkaramba/doc/faq/faq.css | 36 + superkaramba/doc/faq/faq.dat | 75 + superkaramba/doc/faq/faq.html | 111 + superkaramba/doc/faq/faq.txt | 159 + superkaramba/doc/faq/faqfooter.html | 9 + superkaramba/doc/faq/faqfooter.txt | 9 + superkaramba/doc/faq/faqheader.html | 12 + superkaramba/doc/faq/faqheader.txt | 4 + superkaramba/doc/python_api/api.css | 40 + superkaramba/doc/python_api/api_html.rc | 36 + superkaramba/doc/python_api/make_api_doc.sh | 42 + superkaramba/examples/API | 6 + superkaramba/examples/README | 62 + superkaramba/examples/api.html | 4016 +++++++++++++++ superkaramba/examples/autoHide/main.py | 62 + superkaramba/examples/autoHide/main.theme | 42 + superkaramba/examples/autoHide/pics/MSN-64x64.png | Bin 0 -> 6178 bytes superkaramba/examples/autoHide/pics/MSN-96x96.png | Bin 0 -> 11529 bytes .../examples/autoHide/pics/Tux_House-64x64.png | Bin 0 -> 4485 bytes .../examples/autoHide/pics/Tux_House-96x96.png | Bin 0 -> 7462 bytes .../examples/autoHide/pics/Tux_Mail-64x64.png | Bin 0 -> 8572 bytes .../examples/autoHide/pics/Tux_Mail-96x96.png | Bin 0 -> 15942 bytes .../examples/autoHide/pics/Tux_Mozilla-64x64.png | Bin 0 -> 7373 bytes .../examples/autoHide/pics/Tux_Mozilla-96x96.png | Bin 0 -> 13570 bytes .../examples/autoHide/pics/Tux_Sherlock-64x64.png | Bin 0 -> 5635 bytes .../examples/autoHide/pics/Tux_Sherlock-96x96.png | Bin 0 -> 10369 bytes .../examples/autoHide/pics/Tux_Terminal-64x64.png | Bin 0 -> 3489 bytes .../examples/autoHide/pics/Tux_Terminal-96x96.png | Bin 0 -> 5985 bytes .../examples/autoHide/pics/Tux_iPhoto-64x64.png | Bin 0 -> 8036 bytes .../examples/autoHide/pics/Tux_iPhoto-96x96.png | Bin 0 -> 14876 bytes superkaramba/examples/autoHide/pics/bar3.png | Bin 0 -> 393 bytes superkaramba/examples/autoHide/pics/bar4.png | Bin 0 -> 310 bytes superkaramba/examples/autoHide/pics/calendar.png | Bin 0 -> 1950 bytes .../examples/autoHide/pics/ctrl center-64x64.png | Bin 0 -> 5582 bytes .../examples/autoHide/pics/ctrl center-96x96.png | Bin 0 -> 9770 bytes .../examples/autoHide/pics/iconbarback.png | Bin 0 -> 2475 bytes superkaramba/examples/autoHide/pics/label3.png | Bin 0 -> 300 bytes superkaramba/examples/autoHide/pics/label4.png | Bin 0 -> 256 bytes superkaramba/examples/autoHide/pics/osxbarback.png | Bin 0 -> 6463 bytes .../examples/autoHide/pics/osxbarbackBig.png | Bin 0 -> 6473 bytes superkaramba/examples/autoHide/pics/pointer.png | Bin 0 -> 309 bytes superkaramba/examples/bar/bar.py | 93 + superkaramba/examples/bar/bar.theme | 26 + superkaramba/examples/bar/hor.png | Bin 0 -> 300 bytes superkaramba/examples/bar/ver.png | Bin 0 -> 321 bytes superkaramba/examples/change_interval/interval.py | 60 + .../examples/change_interval/interval.theme | 2 + superkaramba/examples/control_management/mgmt.py | 49 + .../examples/control_management/mgmt.theme | 1 + .../examples/disableRightClickMenu/disable_menu.py | 176 + .../disableRightClickMenu/disable_menu.theme | 1 + superkaramba/examples/globalMouse/README | 29 + .../examples/globalMouse/extension/setup.py | 12 + .../examples/globalMouse/extension/xcursor.c | 104 + superkaramba/examples/globalMouse/eyes.py | 192 + superkaramba/examples/globalMouse/eyes.theme | 3 + superkaramba/examples/globalMouse/pics/eyes.png | Bin 0 -> 2819 bytes superkaramba/examples/globalMouse/pics/eyes.xcf | Bin 0 -> 18677 bytes superkaramba/examples/globalMouse/pics/mask.png | Bin 0 -> 495 bytes superkaramba/examples/globalMouse/pics/pupille.png | Bin 0 -> 256 bytes superkaramba/examples/globalMouse/xcursor.so | Bin 0 -> 7465 bytes superkaramba/examples/graph/graph.py | 89 + superkaramba/examples/graph/graph.theme | 26 + superkaramba/examples/image/flag.png | Bin 0 -> 1072 bytes superkaramba/examples/image/flag2.png | Bin 0 -> 2130 bytes superkaramba/examples/image/image.py | 121 + superkaramba/examples/image/image.theme | 34 + superkaramba/examples/image/test1.sh | 2 + superkaramba/examples/image/test2.sh | 2 + superkaramba/examples/input_api/input_api.py | 185 + superkaramba/examples/input_api/input_api.theme | 5 + .../examples/input_example/input_example.py | 169 + .../examples/input_example/input_example.theme | 5 + .../examples/mouseDrag/karmix/images/bar.png | Bin 0 -> 207 bytes .../examples/mouseDrag/karmix/images/bg.png | Bin 0 -> 4719 bytes superkaramba/examples/mouseDrag/karmix/karmix.py | 190 + .../examples/mouseDrag/karmix/karmix.theme | 17 + superkaramba/examples/mouseDrop/mousedrop.py | 138 + superkaramba/examples/mouseDrop/mousedrop.theme | 5 + superkaramba/examples/openCloseTheme/1.py | 22 + superkaramba/examples/openCloseTheme/1.theme | 2 + superkaramba/examples/openCloseTheme/2.theme | 2 + superkaramba/examples/popupMenu/calendar.png | Bin 0 -> 1950 bytes superkaramba/examples/popupMenu/popupMenu.png | Bin 0 -> 6221 bytes superkaramba/examples/popupMenu/popupMenu.py | 117 + superkaramba/examples/popupMenu/popupMenu.theme | 4 + superkaramba/examples/richtext/info.png | Bin 0 -> 641 bytes .../examples/richtext/penguin_executive.png | Bin 0 -> 5159 bytes superkaramba/examples/richtext/richtext.py | 136 + superkaramba/examples/richtext/richtext.theme | 1 + superkaramba/examples/richtext/rtext.py | 99 + superkaramba/examples/richtext/rtext.theme | 26 + .../examples/service_group/service_group.py | 143 + .../examples/service_group/service_group.theme | 4 + superkaramba/examples/setIncomingData/1.py | 27 + superkaramba/examples/setIncomingData/1.theme | 2 + superkaramba/examples/setIncomingData/2.py | 78 + superkaramba/examples/setIncomingData/2.theme | 2 + superkaramba/examples/taskBar/cleanbar/README | 25 + superkaramba/examples/taskBar/cleanbar/cleanbar.py | 267 + .../examples/taskBar/cleanbar/cleanbar.theme | 14 + .../examples/taskBar/cleanbar/pics/bar2.png | Bin 0 -> 7508 bytes .../examples/taskBar/cleanbar/pics/rightend.png | Bin 0 -> 434 bytes .../taskBar/cleanbar/pics/rightend_new.png | Bin 0 -> 5267 bytes .../examples/taskBar/cleanbar/pics/slickbar.png | Bin 0 -> 3130 bytes .../examples/taskBar/cleanbar/pics/startup.png | Bin 0 -> 2584 bytes .../examples/taskBar/cleanbar/pics/task.png | Bin 0 -> 429 bytes .../examples/taskBar/cleanbar/pics/task_new.png | Bin 0 -> 2470 bytes superkaramba/examples/template.py | 160 + superkaramba/examples/test_all.sh | 27 + superkaramba/examples/text/text.py | 110 + superkaramba/examples/text/text.theme | 35 + superkaramba/examples/unicode/unicode.py | 116 + superkaramba/examples/unicode/unicode.theme | 1 + superkaramba/icons/Makefile.am | 1 + superkaramba/icons/cr128-app-superkaramba.png | Bin 0 -> 10111 bytes .../icons/cr128-mime-superkaramba_theme.png | Bin 0 -> 9438 bytes superkaramba/icons/cr16-app-superkaramba.png | Bin 0 -> 697 bytes .../icons/cr16-mime-superkaramba_theme.png | Bin 0 -> 694 bytes superkaramba/icons/cr22-app-superkaramba.png | Bin 0 -> 1030 bytes .../icons/cr22-mime-superkaramba_theme.png | Bin 0 -> 1008 bytes superkaramba/icons/cr32-app-superkaramba.png | Bin 0 -> 1657 bytes .../icons/cr32-mime-superkaramba_theme.png | Bin 0 -> 1642 bytes superkaramba/icons/cr48-app-superkaramba.png | Bin 0 -> 2757 bytes .../icons/cr48-mime-superkaramba_theme.png | Bin 0 -> 2746 bytes superkaramba/icons/cr64-app-superkaramba.png | Bin 0 -> 4039 bytes .../icons/cr64-mime-superkaramba_theme.png | Bin 0 -> 3901 bytes superkaramba/icons/crsc-app-superkaramba.svgz | Bin 0 -> 4263 bytes .../icons/crsc-mime-superkaramba_theme.svgz | Bin 0 -> 10765 bytes superkaramba/karamba.kdevelop | 257 + superkaramba/karamba.kdevses | 29 + superkaramba/mimetypes/Makefile.am | 2 + superkaramba/mimetypes/x-superkaramba.desktop | 52 + superkaramba/src/Makefile.am | 54 + superkaramba/src/bar.cpp | 134 + superkaramba/src/bar.h | 55 + superkaramba/src/bar_python.cpp | 168 + superkaramba/src/bar_python.h | 316 ++ superkaramba/src/clickable.cpp | 37 + superkaramba/src/clickable.h | 46 + superkaramba/src/clickarea.cpp | 107 + superkaramba/src/clickarea.h | 69 + superkaramba/src/clickmap.cpp | 96 + superkaramba/src/clickmap.h | 43 + superkaramba/src/config_python.cpp | 182 + superkaramba/src/config_python.h | 138 + superkaramba/src/cpusensor.cpp | 167 + superkaramba/src/cpusensor.h | 44 + superkaramba/src/datesensor.cpp | 129 + superkaramba/src/datesensor.h | 47 + superkaramba/src/dcopinterface.h | 37 + superkaramba/src/disksensor.cpp | 175 + superkaramba/src/disksensor.h | 51 + superkaramba/src/graph.cpp | 74 + superkaramba/src/graph.h | 39 + superkaramba/src/graph_python.cpp | 137 + superkaramba/src/graph_python.h | 289 ++ superkaramba/src/imagelabel.cpp | 632 +++ superkaramba/src/imagelabel.h | 191 + superkaramba/src/imagelabel_python.cpp | 331 ++ superkaramba/src/imagelabel_python.h | 449 ++ superkaramba/src/input.cpp | 196 + superkaramba/src/input.h | 84 + superkaramba/src/input_python.cpp | 355 ++ superkaramba/src/input_python.h | 475 ++ superkaramba/src/karamba.cpp | 2098 ++++++++ superkaramba/src/karamba.h | 363 ++ superkaramba/src/karamba_python.cpp | 635 +++ superkaramba/src/karamba_python.h | 85 + superkaramba/src/karambaapp.cpp | 427 ++ superkaramba/src/karambaapp.h | 95 + superkaramba/src/karambainterface.cpp | 153 + superkaramba/src/karambainterface.h | 42 + superkaramba/src/karambalistboxitem.cpp | 25 + superkaramba/src/karambalistboxitem.h | 31 + superkaramba/src/karambarootpixmap.cpp | 36 + superkaramba/src/karambarootpixmap.h | 39 + superkaramba/src/karambasessionmanaged.cpp | 63 + superkaramba/src/karambasessionmanaged.h | 30 + superkaramba/src/kwidgetlistbox.cpp | 200 + superkaramba/src/kwidgetlistbox.h | 68 + superkaramba/src/lineparser.cpp | 96 + superkaramba/src/lineparser.h | 53 + superkaramba/src/main.cpp | 156 + superkaramba/src/memsensor.cpp | 359 ++ superkaramba/src/memsensor.h | 67 + superkaramba/src/menu_python.cpp | 200 + superkaramba/src/menu_python.h | 124 + superkaramba/src/meter.cpp | 111 + superkaramba/src/meter.h | 99 + superkaramba/src/meter_python.cpp | 373 ++ superkaramba/src/meter_python.h | 44 + superkaramba/src/misc_python.cpp | 852 ++++ superkaramba/src/misc_python.h | 606 +++ superkaramba/src/networksensor.cpp | 164 + superkaramba/src/networksensor.h | 47 + superkaramba/src/noatunsensor.cpp | 234 + superkaramba/src/noatunsensor.h | 48 + superkaramba/src/programsensor.cpp | 93 + superkaramba/src/programsensor.h | 38 + superkaramba/src/richtextlabel.cpp | 212 + superkaramba/src/richtextlabel.h | 64 + superkaramba/src/richtextlabel_python.cpp | 182 + superkaramba/src/richtextlabel_python.h | 338 ++ superkaramba/src/rsssensor.cpp | 136 + superkaramba/src/rsssensor.h | 39 + superkaramba/src/sensor.cpp | 64 + superkaramba/src/sensor.h | 47 + superkaramba/src/sensorparams.cpp | 34 + superkaramba/src/sensorparams.h | 48 + superkaramba/src/sensorsensor.cpp | 115 + superkaramba/src/sensorsensor.h | 49 + superkaramba/src/showdesktop.cpp | 123 + superkaramba/src/showdesktop.h | 58 + superkaramba/src/sklineedit.cpp | 82 + superkaramba/src/sklineedit.h | 57 + superkaramba/src/sknewstuff.cpp | 140 + superkaramba/src/sknewstuff.h | 53 + superkaramba/src/superkaramba.desktop | 99 + superkaramba/src/superkaramba.kcfg | 16 + superkaramba/src/superkaramba.lsm | 16 + superkaramba/src/superkarambasettings.kcfgc | 4 + superkaramba/src/superkarambaui.rc | 8 + superkaramba/src/svcgrp_python.cpp | 156 + superkaramba/src/svcgrp_python.h | 44 + superkaramba/src/systemtray.cpp | 231 + superkaramba/src/systemtray.h | 69 + superkaramba/src/systray_python.cpp | 199 + superkaramba/src/systray_python.h | 117 + superkaramba/src/task_python.cpp | 375 ++ superkaramba/src/task_python.h | 153 + superkaramba/src/taskbartest.cpp | 183 + superkaramba/src/taskbartest.h | 23 + superkaramba/src/taskmanager.cpp | 829 ++++ superkaramba/src/taskmanager.h | 550 +++ superkaramba/src/textfield.cpp | 159 + superkaramba/src/textfield.h | 59 + superkaramba/src/textfilesensor.cpp | 109 + superkaramba/src/textfilesensor.h | 53 + superkaramba/src/textlabel.cpp | 379 ++ superkaramba/src/textlabel.h | 87 + superkaramba/src/textlabel_python.cpp | 235 + superkaramba/src/textlabel_python.h | 397 ++ superkaramba/src/themefile.cpp | 414 ++ superkaramba/src/themefile.h | 107 + superkaramba/src/themelocale.cpp | 438 ++ superkaramba/src/themelocale.h | 61 + superkaramba/src/themes_layout.ui | 241 + superkaramba/src/themesdlg.cpp | 543 +++ superkaramba/src/themesdlg.h | 80 + superkaramba/src/themewidget.cpp | 113 + superkaramba/src/themewidget.h | 57 + superkaramba/src/themewidget_layout.ui | 182 + superkaramba/src/uptimesensor.cpp | 119 + superkaramba/src/uptimesensor.h | 30 + superkaramba/src/widget_python.cpp | 214 + superkaramba/src/widget_python.h | 131 + superkaramba/src/xmmssensor.cpp | 149 + superkaramba/src/xmmssensor.h | 38 + 1583 files changed, 223413 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 COPYING-DOCS create mode 100644 INSTALL create mode 100644 Mainpage.dox create mode 100644 Makefile.am.in create mode 100644 Makefile.cvs create mode 100644 README create mode 100644 ark/AUTHORS create mode 100644 ark/ChangeLog create mode 100644 ark/Makefile.am create mode 100644 ark/README create mode 100644 ark/TODO create mode 100644 ark/ace.cpp create mode 100644 ark/ace.h create mode 100644 ark/addition.ui create mode 100644 ark/ar.cpp create mode 100644 ark/ar.h create mode 100644 ark/arch.cpp create mode 100644 ark/arch.h create mode 100644 ark/archiveformatdlg.cpp create mode 100644 ark/archiveformatdlg.h create mode 100644 ark/archiveformatinfo.cpp create mode 100644 ark/archiveformatinfo.h create mode 100644 ark/ark.desktop create mode 100644 ark/ark.kcfg create mode 100644 ark/ark_part.cpp create mode 100644 ark/ark_part.desktop create mode 100644 ark/ark_part.h create mode 100644 ark/ark_part.rc create mode 100644 ark/ark_part_readonly.rc create mode 100644 ark/arkapp.cpp create mode 100644 ark/arkapp.h create mode 100644 ark/arkfactory.cpp create mode 100644 ark/arkfactory.h create mode 100644 ark/arkui.rc create mode 100644 ark/arkutils.cpp create mode 100644 ark/arkutils.h create mode 100644 ark/arkviewer.cpp create mode 100644 ark/arkviewer.h create mode 100644 ark/arkwidget.cpp create mode 100644 ark/arkwidget.h create mode 100644 ark/common_texts.cpp create mode 100644 ark/compressedfile.cpp create mode 100644 ark/compressedfile.h create mode 100644 ark/configure.in.in create mode 100644 ark/extraction.ui create mode 100644 ark/extractiondialog.cpp create mode 100644 ark/extractiondialog.h create mode 100644 ark/filelistview.cpp create mode 100644 ark/filelistview.h create mode 100644 ark/general.ui create mode 100644 ark/hi128-app-ark.png create mode 100644 ark/hi16-app-ark.png create mode 100644 ark/hi22-app-ark.png create mode 100644 ark/hi32-app-ark.png create mode 100644 ark/hi48-app-ark.png create mode 100644 ark/hi64-app-ark.png create mode 100644 ark/hisc-app-ark.svgz create mode 100644 ark/lha.cpp create mode 100644 ark/lha.h create mode 100644 ark/main.cpp create mode 100644 ark/mainwindow.cpp create mode 100644 ark/mainwindow.h create mode 100644 ark/pics/Makefile.am create mode 100644 ark/pics/cr22-action-ark_adddir.png create mode 100644 ark/pics/cr22-action-ark_addfile.png create mode 100644 ark/pics/cr22-action-ark_delete.png create mode 100644 ark/pics/cr22-action-ark_extract.png create mode 100644 ark/pics/cr22-action-ark_selectall.png create mode 100644 ark/pics/cr22-action-ark_view.png create mode 100644 ark/pics/cr32-action-ark_adddir.png create mode 100644 ark/pics/cr32-action-ark_addfile.png create mode 100644 ark/pics/cr32-action-ark_delete.png create mode 100644 ark/pics/cr32-action-ark_extract.png create mode 100644 ark/pics/cr32-action-ark_view.png create mode 100644 ark/rar.cpp create mode 100644 ark/rar.h create mode 100644 ark/searchbar.cpp create mode 100644 ark/searchbar.h create mode 100644 ark/settings.kcfgc create mode 100644 ark/sevenzip.cpp create mode 100644 ark/sevenzip.h create mode 100644 ark/tar.cpp create mode 100644 ark/tar.h create mode 100644 ark/tarlistingthread.cpp create mode 100644 ark/tarlistingthread.h create mode 100644 ark/zip.cpp create mode 100644 ark/zip.h create mode 100644 ark/zoo.cpp create mode 100644 ark/zoo.h create mode 100644 charselectapplet/Makefile.am create mode 100644 charselectapplet/charselectapplet.cpp create mode 100644 charselectapplet/charselectapplet.h create mode 100644 charselectapplet/kcharselectapplet.desktop create mode 100644 configure.in.in create mode 100644 doc/KRegExpEditor/Makefile.am create mode 100644 doc/KRegExpEditor/altn.png create mode 100644 doc/KRegExpEditor/altntool.png create mode 100644 doc/KRegExpEditor/anychar.png create mode 100644 doc/KRegExpEditor/anychartool.png create mode 100644 doc/KRegExpEditor/begline.png create mode 100644 doc/KRegExpEditor/boundarytools.png create mode 100644 doc/KRegExpEditor/characters.png create mode 100644 doc/KRegExpEditor/charactertool.png create mode 100644 doc/KRegExpEditor/compound.png create mode 100644 doc/KRegExpEditor/compoundtool.png create mode 100644 doc/KRegExpEditor/endline.png create mode 100644 doc/KRegExpEditor/index.docbook create mode 100644 doc/KRegExpEditor/linestartendtool.png create mode 100644 doc/KRegExpEditor/lookaheadtools.png create mode 100644 doc/KRegExpEditor/neglookahead.png create mode 100644 doc/KRegExpEditor/nonwordboundary.png create mode 100644 doc/KRegExpEditor/poslookahead.png create mode 100644 doc/KRegExpEditor/repeat.png create mode 100644 doc/KRegExpEditor/repeattool.png create mode 100644 doc/KRegExpEditor/select.png create mode 100644 doc/KRegExpEditor/text.png create mode 100644 doc/KRegExpEditor/texttool.png create mode 100644 doc/KRegExpEditor/theEditor.png create mode 100644 doc/KRegExpEditor/wordboundary.png create mode 100644 doc/Makefile.am create mode 100644 doc/ark/Makefile.am create mode 100644 doc/ark/index.docbook create mode 100644 doc/ark/man-ark.1.docbook create mode 100644 doc/kcalc/Makefile.am create mode 100644 doc/kcalc/commands.docbook create mode 100644 doc/kcalc/index.docbook create mode 100644 doc/kcalc/kcalc_on_Aix.txt create mode 100644 doc/kcalc/kcalc_on_OSF.txt create mode 100644 doc/kcharselect/Makefile.am create mode 100644 doc/kcharselect/index.docbook create mode 100644 doc/kcontrol/Makefile.am create mode 100644 doc/kcontrol/kcmlowbatcrit/Makefile.am create mode 100644 doc/kcontrol/kcmlowbatcrit/index.docbook create mode 100644 doc/kcontrol/kcmlowbatwarn/Makefile.am create mode 100644 doc/kcontrol/kcmlowbatwarn/index.docbook create mode 100644 doc/kcontrol/laptop/Makefile.am create mode 100644 doc/kcontrol/laptop/index.docbook create mode 100644 doc/kcontrol/powerctrl/Makefile.am create mode 100644 doc/kcontrol/powerctrl/index.docbook create mode 100644 doc/kdelirc/Makefile.am create mode 100644 doc/kdelirc/irkick/Makefile.am create mode 100644 doc/kdelirc/irkick/index.docbook create mode 100644 doc/kdelirc/kcmlirc/Makefile.am create mode 100644 doc/kdelirc/kcmlirc/index.docbook create mode 100644 doc/kdf/Makefile.am create mode 100644 doc/kdf/index.docbook create mode 100644 doc/kdf/kdf.png create mode 100644 doc/kdf/kdf_config.png create mode 100644 doc/kedit/Makefile.am create mode 100644 doc/kedit/index.docbook create mode 100644 doc/kfloppy/Makefile.am create mode 100644 doc/kfloppy/index.docbook create mode 100644 doc/kgpg/Makefile.am create mode 100644 doc/kgpg/editor.png create mode 100644 doc/kgpg/index.docbook create mode 100644 doc/kgpg/keygen.png create mode 100644 doc/kgpg/keymanage.png create mode 100644 doc/kgpg/keys.png create mode 100644 doc/kgpg/kicker.png create mode 100644 doc/kgpg/options.png create mode 100644 doc/khexedit/Makefile.am create mode 100644 doc/khexedit/index.docbook create mode 100644 doc/khexedit/khexedit1.png create mode 100644 doc/kinfocenter/Makefile.am create mode 100644 doc/kinfocenter/blockdevices/Makefile.am create mode 100644 doc/kinfocenter/blockdevices/index.docbook create mode 100644 doc/kjots/Makefile.am create mode 100644 doc/kjots/index.docbook create mode 100644 doc/ksim/Makefile.am create mode 100644 doc/ksim/index.docbook create mode 100644 doc/ktimer/Makefile.am create mode 100644 doc/ktimer/index.docbook create mode 100644 doc/kwallet/Makefile.am create mode 100644 doc/kwallet/cr22-action-wallet_closed.png create mode 100644 doc/kwallet/cr22-action-wallet_open.png create mode 100644 doc/kwallet/edit1.png create mode 100644 doc/kwallet/edit2.png create mode 100644 doc/kwallet/edit3.png create mode 100644 doc/kwallet/index.docbook create mode 100644 doc/kwallet/kwalletmanager.png create mode 100644 doc/kwallet/password1.png create mode 100644 doc/kwallet/password2.png create mode 100644 doc/superkaramba/Makefile.am create mode 100644 doc/superkaramba/index.docbook create mode 100644 kcalc/ChangeLog create mode 100644 kcalc/Makefile.am create mode 100644 kcalc/README create mode 100644 kcalc/TODO create mode 100644 kcalc/colors.ui create mode 100644 kcalc/configure.in.bot create mode 100644 kcalc/configure.in.in create mode 100644 kcalc/confvalues.h create mode 100644 kcalc/constants.ui create mode 100644 kcalc/dlabel.cpp create mode 100644 kcalc/dlabel.h create mode 100644 kcalc/general.ui create mode 100644 kcalc/hi16-app-kcalc.png create mode 100644 kcalc/hi22-app-kcalc.png create mode 100644 kcalc/hi32-app-kcalc.png create mode 100644 kcalc/hi48-app-kcalc.png create mode 100644 kcalc/hi64-app-kcalc.png create mode 100644 kcalc/hisc-app-kcalc.svgz create mode 100644 kcalc/kcalc.cpp create mode 100644 kcalc/kcalc.desktop create mode 100644 kcalc/kcalc.h create mode 100644 kcalc/kcalc.kcfg create mode 100644 kcalc/kcalc_button.cpp create mode 100644 kcalc/kcalc_button.h create mode 100644 kcalc/kcalc_const_button.cpp create mode 100644 kcalc/kcalc_const_button.h create mode 100644 kcalc/kcalc_const_menu.cpp create mode 100644 kcalc/kcalc_const_menu.h create mode 100644 kcalc/kcalc_core.cpp create mode 100644 kcalc/kcalc_core.h create mode 100644 kcalc/kcalc_settings.kcfgc create mode 100644 kcalc/kcalcdisplay.cpp create mode 100644 kcalc/kcalcdisplay.h create mode 100644 kcalc/kcalcrc.upd create mode 100644 kcalc/kcalctype.h create mode 100644 kcalc/kcalcui.rc create mode 100644 kcalc/knumber/Makefile.am create mode 100644 kcalc/knumber/configure.in.in create mode 100644 kcalc/knumber/knumber.cpp create mode 100644 kcalc/knumber/knumber.h create mode 100644 kcalc/knumber/knumber_priv.cpp create mode 100644 kcalc/knumber/knumber_priv.h create mode 100644 kcalc/knumber/tests/Makefile.am create mode 100644 kcalc/knumber/tests/knumbertest.cpp create mode 100644 kcalc/knumber/tests/knumbertest.h create mode 100644 kcalc/stats.cpp create mode 100644 kcalc/stats.h create mode 100644 kcalc/version.h create mode 100644 kcharselect/KCharSelect.desktop create mode 100644 kcharselect/Makefile.am create mode 100644 kcharselect/TODO create mode 100644 kcharselect/hi16-app-kcharselect.png create mode 100644 kcharselect/hi32-app-kcharselect.png create mode 100644 kcharselect/hi48-app-kcharselect.png create mode 100644 kcharselect/kcharselect.upd create mode 100644 kcharselect/kcharselectdia.cc create mode 100644 kcharselect/kcharselectdia.h create mode 100644 kcharselect/kcharselectui.rc create mode 100644 kcharselect/main.cc create mode 100644 kdelirc/AUTHORS create mode 100644 kdelirc/COPYING create mode 100644 kdelirc/ChangeLog create mode 100644 kdelirc/Makefile.am create mode 100644 kdelirc/README create mode 100644 kdelirc/README.profile-creation create mode 100644 kdelirc/README.remote-creation create mode 100644 kdelirc/TODO create mode 100644 kdelirc/icons/Makefile.am create mode 100644 kdelirc/icons/hi16-action-ledblue.png create mode 100644 kdelirc/icons/hi16-action-ledgreen.png create mode 100644 kdelirc/icons/hi16-action-ledlightblue.png create mode 100644 kdelirc/icons/hi16-action-ledlightgreen.png create mode 100644 kdelirc/icons/hi16-action-ledorange.png create mode 100644 kdelirc/icons/hi16-action-ledpurple.png create mode 100644 kdelirc/icons/hi16-action-ledred.png create mode 100644 kdelirc/icons/hi16-action-ledyellow.png create mode 100644 kdelirc/icons/hi32-action-ledblue.png create mode 100644 kdelirc/icons/hi32-action-ledgreen.png create mode 100644 kdelirc/icons/hi32-action-ledlightblue.png create mode 100644 kdelirc/icons/hi32-action-ledlightgreen.png create mode 100644 kdelirc/icons/hi32-action-ledorange.png create mode 100644 kdelirc/icons/hi32-action-ledpurple.png create mode 100644 kdelirc/icons/hi32-action-ledred.png create mode 100644 kdelirc/icons/hi32-action-ledyellow.png create mode 100644 kdelirc/irkick/Makefile.am create mode 100644 kdelirc/irkick/hi16-app-irkick.png create mode 100644 kdelirc/irkick/hi22-app-irkick.png create mode 100644 kdelirc/irkick/hi32-app-irkick.png create mode 100644 kdelirc/irkick/icons/Makefile.am create mode 100644 kdelirc/irkick/icons/hi16-action-irkick.png create mode 100644 kdelirc/irkick/icons/hi16-action-irkickflash.png create mode 100644 kdelirc/irkick/icons/hi16-action-irkickoff.png create mode 100644 kdelirc/irkick/irkick.cpp create mode 100644 kdelirc/irkick/irkick.desktop create mode 100644 kdelirc/irkick/irkick.h create mode 100644 kdelirc/irkick/irkick.project create mode 100644 kdelirc/irkick/kdedmodule_stub.h create mode 100644 kdelirc/irkick/klircclient.cpp create mode 100644 kdelirc/irkick/klircclient.h create mode 100644 kdelirc/irkick/lo16-app-irkick.png create mode 100644 kdelirc/irkick/lo32-app-irkick.png create mode 100644 kdelirc/irkick/main.cpp create mode 100644 kdelirc/kcmlirc/Makefile.am create mode 100644 kdelirc/kcmlirc/addaction.cpp create mode 100644 kdelirc/kcmlirc/addaction.h create mode 100644 kdelirc/kcmlirc/addactionbase.ui create mode 100644 kdelirc/kcmlirc/editaction.cpp create mode 100644 kdelirc/kcmlirc/editaction.h create mode 100644 kdelirc/kcmlirc/editactionbase.ui create mode 100644 kdelirc/kcmlirc/editmode.cpp create mode 100644 kdelirc/kcmlirc/editmode.h create mode 100644 kdelirc/kcmlirc/editmodebase.ui create mode 100644 kdelirc/kcmlirc/kcmlirc.cpp create mode 100644 kdelirc/kcmlirc/kcmlirc.desktop create mode 100644 kdelirc/kcmlirc/kcmlirc.h create mode 100644 kdelirc/kcmlirc/kcmlircbase.ui create mode 100644 kdelirc/kcmlirc/kcmlircbase.ui.h create mode 100644 kdelirc/kcmlirc/modeslist.cpp create mode 100644 kdelirc/kcmlirc/modeslist.h create mode 100644 kdelirc/kcmlirc/newmode.ui create mode 100644 kdelirc/kcmlirc/newmode.ui.h create mode 100644 kdelirc/kcmlirc/selectprofile.ui create mode 100644 kdelirc/kdelirc/Makefile.am create mode 100644 kdelirc/kdelirc/arguments.cpp create mode 100644 kdelirc/kdelirc/arguments.h create mode 100644 kdelirc/kdelirc/iraction.cpp create mode 100644 kdelirc/kdelirc/iraction.h create mode 100644 kdelirc/kdelirc/iractions.cpp create mode 100644 kdelirc/kdelirc/iractions.h create mode 100644 kdelirc/kdelirc/mode.cpp create mode 100644 kdelirc/kdelirc/mode.h create mode 100644 kdelirc/kdelirc/modes.cpp create mode 100644 kdelirc/kdelirc/modes.h create mode 100644 kdelirc/kdelirc/profileserver.cpp create mode 100644 kdelirc/kdelirc/profileserver.h create mode 100644 kdelirc/kdelirc/prototype.cpp create mode 100644 kdelirc/kdelirc/prototype.h create mode 100644 kdelirc/kdelirc/remoteserver.cpp create mode 100644 kdelirc/kdelirc/remoteserver.h create mode 100644 kdelirc/profiles/Makefile.am create mode 100644 kdelirc/profiles/klauncher.profile.xml create mode 100644 kdelirc/profiles/konqueror.profile.xml create mode 100644 kdelirc/profiles/noatun.profile.xml create mode 100644 kdelirc/profiles/profile.dtd create mode 100644 kdelirc/remotes/Makefile.am create mode 100644 kdelirc/remotes/RM-0010.remote.xml create mode 100644 kdelirc/remotes/cimr100.remote.xml create mode 100644 kdelirc/remotes/hauppauge.remote.xml create mode 100644 kdelirc/remotes/remote.dtd create mode 100644 kdelirc/remotes/sherwood.remote.xml create mode 100644 kdelirc/remotes/sonytv.remote.xml create mode 100644 kdessh/LICENSE.readme create mode 100644 kdessh/Makefile.am create mode 100644 kdessh/README create mode 100644 kdessh/kdessh.cpp create mode 100644 kdessh/sshdlg.cpp create mode 100644 kdessh/sshdlg.h create mode 100644 kdeutils.lsm create mode 100644 kdf/Makefile.am create mode 100644 kdf/disklist.cpp create mode 100644 kdf/disklist.h create mode 100644 kdf/disks.cpp create mode 100644 kdf/disks.h create mode 100644 kdf/kcmdf.cpp create mode 100644 kdf/kcmdf.desktop create mode 100644 kdf/kcmdf.h create mode 100644 kdf/kconftest.cpp create mode 100644 kdf/kdf.cpp create mode 100644 kdf/kdf.desktop create mode 100644 kdf/kdf.h create mode 100644 kdf/kdfconfig.cpp create mode 100644 kdf/kdfconfig.h create mode 100644 kdf/kdfui.rc create mode 100644 kdf/kdfwidget.cpp create mode 100644 kdf/kdfwidget.h create mode 100644 kdf/kwikdisk.cpp create mode 100644 kdf/kwikdisk.desktop create mode 100644 kdf/kwikdisk.h create mode 100644 kdf/listview.cpp create mode 100644 kdf/listview.h create mode 100644 kdf/mntconfig.cpp create mode 100644 kdf/mntconfig.h create mode 100644 kdf/optiondialog.cpp create mode 100644 kdf/optiondialog.h create mode 100644 kdf/pics/Makefile.am create mode 100644 kdf/pics/cr16-app-kcmdf.png create mode 100644 kdf/pics/cr22-app-kcmdf.png create mode 100644 kdf/pics/cr32-app-kcmdf.png create mode 100644 kdf/pics/delete.png create mode 100644 kdf/pics/hi128-app-kdf.png create mode 100644 kdf/pics/hi128-app-kwikdisk.png create mode 100644 kdf/pics/hi16-app-kdf.png create mode 100644 kdf/pics/hi16-app-kwikdisk.png create mode 100644 kdf/pics/hi22-app-kdf.png create mode 100644 kdf/pics/hi22-app-kwikdisk.png create mode 100644 kdf/pics/hi32-app-kdf.png create mode 100644 kdf/pics/hi32-app-kwikdisk.png create mode 100644 kdf/pics/hi48-app-kdf.png create mode 100644 kdf/pics/hi48-app-kwikdisk.png create mode 100644 kdf/pics/hi64-app-kdf.png create mode 100644 kdf/pics/hi64-app-kwikdisk.png create mode 100644 kdf/pics/mini-root.png create mode 100644 kdf/pics/tick.png create mode 100644 kdf/stdoption.cpp create mode 100644 kdf/stdoption.h create mode 100644 kdf/unix_outputs/df-g.hpux create mode 100644 kdf/unix_outputs/df-k.digital create mode 100644 kdf/unix_outputs/df-k.hpux create mode 100644 kdf/unix_outputs/df.man.hpux create mode 100644 kdf/unix_outputs/etcfstab.digital create mode 100644 kdf/unix_outputs/etcfstab.hpux create mode 100644 kdf/unix_outputs/unix-defines.txt create mode 100644 kedit/ChangeLog create mode 100644 kedit/KEdit.desktop create mode 100644 kedit/Makefile.am create mode 100644 kedit/README create mode 100644 kedit/TODO create mode 100644 kedit/color.ui create mode 100644 kedit/kedit.cpp create mode 100644 kedit/kedit.h create mode 100644 kedit/kedit.kcfg create mode 100644 kedit/keditui.rc create mode 100644 kedit/ktextfiledlg.cpp create mode 100644 kedit/ktextfiledlg.h create mode 100644 kedit/misc.ui create mode 100644 kedit/misc.ui.h create mode 100644 kedit/pixmaps/Makefile.am create mode 100644 kedit/pixmaps/hi16-app-kedit.png create mode 100644 kedit/pixmaps/hi22-app-kedit.png create mode 100644 kedit/pixmaps/hi32-app-kedit.png create mode 100644 kedit/pixmaps/hi48-app-kedit.png create mode 100644 kedit/pixmaps/hi64-app-kedit.png create mode 100644 kedit/prefs.kcfgc create mode 100644 kedit/version.h create mode 100644 kfloppy/KFloppy.desktop create mode 100644 kfloppy/Makefile.am create mode 100644 kfloppy/README create mode 100644 kfloppy/TODO create mode 100644 kfloppy/debug.h create mode 100644 kfloppy/floppy.cpp create mode 100644 kfloppy/floppy.h create mode 100644 kfloppy/floppy_format.desktop create mode 100644 kfloppy/format.cpp create mode 100644 kfloppy/format.h create mode 100644 kfloppy/hi128-app-kfloppy.png create mode 100644 kfloppy/hi16-app-kfloppy.png create mode 100644 kfloppy/hi22-app-kfloppy.png create mode 100644 kfloppy/hi32-app-kfloppy.png create mode 100644 kfloppy/hi48-app-kfloppy.png create mode 100644 kfloppy/hi64-app-kfloppy.png create mode 100644 kfloppy/main.cpp create mode 100644 kfloppy/zip.cpp create mode 100644 kfloppy/zip.h create mode 100644 kgpg/AUTHORS create mode 100644 kgpg/ChangeLog create mode 100644 kgpg/INSTALL create mode 100644 kgpg/Makefile.am create mode 100644 kgpg/adduid.ui create mode 100644 kgpg/conf_decryption.ui create mode 100644 kgpg/conf_encryption.ui create mode 100644 kgpg/conf_encryption.ui.h create mode 100644 kgpg/conf_gpg.ui create mode 100644 kgpg/conf_misc.ui create mode 100644 kgpg/conf_servers.ui create mode 100644 kgpg/conf_ui2.ui create mode 100644 kgpg/dcopiface.h create mode 100644 kgpg/detailedconsole.cpp create mode 100644 kgpg/detailedconsole.h create mode 100644 kgpg/encryptfile.desktop create mode 100644 kgpg/encryptfolder.desktop create mode 100644 kgpg/groupedit.ui create mode 100644 kgpg/hi16-app-kgpg.png create mode 100644 kgpg/hi22-app-kgpg.png create mode 100644 kgpg/hi32-app-kgpg.png create mode 100644 kgpg/hi48-app-kgpg.png create mode 100644 kgpg/icons/Makefile.am create mode 100644 kgpg/icons/cr16-action-kgpg_key1.png create mode 100644 kgpg/icons/cr16-action-kgpg_key2.png create mode 100644 kgpg/icons/cr16-action-kgpg_key3.png create mode 100644 kgpg/icons/cr16-action-kgpg_key4.png create mode 100644 kgpg/icons/cr22-action-kgpg_edit.png create mode 100644 kgpg/icons/cr22-action-kgpg_export.png create mode 100644 kgpg/icons/cr22-action-kgpg_gen.png create mode 100644 kgpg/icons/cr22-action-kgpg_identity.png create mode 100644 kgpg/icons/cr22-action-kgpg_import.png create mode 100644 kgpg/icons/cr22-action-kgpg_info.png create mode 100644 kgpg/icons/cr22-action-kgpg_photo.png create mode 100644 kgpg/icons/cr22-action-kgpg_show.png create mode 100644 kgpg/icons/cr22-action-kgpg_sign.png create mode 100644 kgpg/icons/cr22-action-kgpg_term.png create mode 100644 kgpg/keyexport.ui create mode 100644 kgpg/keyexport.ui.h create mode 100644 kgpg/keygener.cpp create mode 100644 kgpg/keygener.h create mode 100644 kgpg/keyinfowidget.cpp create mode 100644 kgpg/keyinfowidget.h create mode 100644 kgpg/keyproperties.ui create mode 100644 kgpg/keyserver.ui create mode 100644 kgpg/keyservers.cpp create mode 100644 kgpg/keyservers.h create mode 100644 kgpg/kgpg.cpp create mode 100644 kgpg/kgpg.desktop create mode 100644 kgpg/kgpg.h create mode 100644 kgpg/kgpg.kcfg create mode 100644 kgpg/kgpg.rc create mode 100644 kgpg/kgpg_anim.gif create mode 100644 kgpg/kgpg_blank.png create mode 100644 kgpg/kgpg_docked.gif create mode 100644 kgpg/kgpg_docked.png create mode 100644 kgpg/kgpg_fill.png create mode 100644 kgpg/kgpgeditor.cpp create mode 100644 kgpg/kgpgeditor.h create mode 100644 kgpg/kgpginterface.cpp create mode 100644 kgpg/kgpginterface.h create mode 100644 kgpg/kgpglibrary.cpp create mode 100644 kgpg/kgpglibrary.h create mode 100644 kgpg/kgpgoptions.cpp create mode 100644 kgpg/kgpgoptions.h create mode 100644 kgpg/kgpgrevokewidget.ui create mode 100644 kgpg/kgpgrevokewidget.ui.h create mode 100644 kgpg/kgpgsettings.kcfgc create mode 100644 kgpg/kgpgsettings_addons.h create mode 100644 kgpg/kgpgview.cpp create mode 100644 kgpg/kgpgview.h create mode 100644 kgpg/kgpgwizard.ui create mode 100644 kgpg/listkeys.cpp create mode 100644 kgpg/listkeys.h create mode 100644 kgpg/listkeys.rc create mode 100644 kgpg/main.cpp create mode 100644 kgpg/newkey.ui create mode 100644 kgpg/newkey.ui.h create mode 100644 kgpg/popuppublic.cpp create mode 100644 kgpg/popuppublic.h create mode 100644 kgpg/searchres.ui create mode 100644 kgpg/sourceselect.ui create mode 100644 kgpg/tips create mode 100644 khexedit/Makefile.am create mode 100644 khexedit/README create mode 100644 khexedit/bitswapwidget.cc create mode 100644 khexedit/bitswapwidget.h create mode 100644 khexedit/chartabledialog.cc create mode 100644 khexedit/chartabledialog.h create mode 100644 khexedit/configure.in.in create mode 100644 khexedit/conversion.cc create mode 100644 khexedit/conversion.h create mode 100644 khexedit/converterdialog.cc create mode 100644 khexedit/converterdialog.h create mode 100644 khexedit/dialog.cc create mode 100644 khexedit/dialog.h create mode 100644 khexedit/draglabel.cc create mode 100644 khexedit/draglabel.h create mode 100644 khexedit/exportdialog.cc create mode 100644 khexedit/exportdialog.h create mode 100644 khexedit/fileinfodialog.cc create mode 100644 khexedit/fileinfodialog.h create mode 100644 khexedit/hexbuffer.cc create mode 100644 khexedit/hexbuffer.h create mode 100644 khexedit/hexclipboard.cc create mode 100644 khexedit/hexclipboard.h create mode 100644 khexedit/hexdrag.cc create mode 100644 khexedit/hexdrag.h create mode 100644 khexedit/hexeditorwidget.cc create mode 100644 khexedit/hexeditorwidget.h create mode 100644 khexedit/hexeditstate.h create mode 100644 khexedit/hexerror.cc create mode 100644 khexedit/hexerror.h create mode 100644 khexedit/hexmanagerwidget.cc create mode 100644 khexedit/hexmanagerwidget.h create mode 100644 khexedit/hexprinter.cc create mode 100644 khexedit/hexprinter.h create mode 100644 khexedit/hextoolwidget.cc create mode 100644 khexedit/hextoolwidget.h create mode 100644 khexedit/hexvalidator.cc create mode 100644 khexedit/hexvalidator.h create mode 100644 khexedit/hexviewwidget.cc create mode 100644 khexedit/hexviewwidget.h create mode 100644 khexedit/hi16-app-khexedit.png create mode 100644 khexedit/hi32-app-khexedit.png create mode 100644 khexedit/hi48-app-khexedit.png create mode 100644 khexedit/khexedit.desktop create mode 100644 khexedit/khexeditui.rc create mode 100644 khexedit/lib/Makefile.am create mode 100644 khexedit/lib/README create mode 100644 khexedit/lib/codecs/Makefile.am create mode 100644 khexedit/lib/codecs/README create mode 100644 khexedit/lib/codecs/kbinarybytecodec.cpp create mode 100644 khexedit/lib/codecs/kbinarybytecodec.h create mode 100644 khexedit/lib/codecs/kbytecodec.cpp create mode 100644 khexedit/lib/codecs/kcharcodec.cpp create mode 100644 khexedit/lib/codecs/kdecimalbytecodec.cpp create mode 100644 khexedit/lib/codecs/kdecimalbytecodec.h create mode 100644 khexedit/lib/codecs/kebcdic1047charcodec.cpp create mode 100644 khexedit/lib/codecs/kebcdic1047charcodec.h create mode 100644 khexedit/lib/codecs/khexadecimalbytecodec.cpp create mode 100644 khexedit/lib/codecs/khexadecimalbytecodec.h create mode 100644 khexedit/lib/codecs/koctalbytecodec.cpp create mode 100644 khexedit/lib/codecs/koctalbytecodec.h create mode 100644 khexedit/lib/codecs/ktextcharcodec.cpp create mode 100644 khexedit/lib/codecs/ktextcharcodec.h create mode 100644 khexedit/lib/controller/Makefile.am create mode 100644 khexedit/lib/controller/kchareditor.cpp create mode 100644 khexedit/lib/controller/kchareditor.h create mode 100644 khexedit/lib/controller/kcontroller.cpp create mode 100644 khexedit/lib/controller/kcontroller.h create mode 100644 khexedit/lib/controller/keditor.cpp create mode 100644 khexedit/lib/controller/keditor.h create mode 100644 khexedit/lib/controller/knavigator.cpp create mode 100644 khexedit/lib/controller/knavigator.h create mode 100644 khexedit/lib/controller/ktabcontroller.cpp create mode 100644 khexedit/lib/controller/ktabcontroller.h create mode 100644 khexedit/lib/controller/kvalueeditor.cpp create mode 100644 khexedit/lib/controller/kvalueeditor.h create mode 100644 khexedit/lib/helper.h create mode 100644 khexedit/lib/kadds.h create mode 100644 khexedit/lib/kbigbuffer.cpp create mode 100644 khexedit/lib/kbigbuffer.h create mode 100644 khexedit/lib/kbordercoltextexport.cpp create mode 100644 khexedit/lib/kbordercoltextexport.h create mode 100644 khexedit/lib/kbordercolumn.cpp create mode 100644 khexedit/lib/kbordercolumn.h create mode 100644 khexedit/lib/kbuffercoltextexport.cpp create mode 100644 khexedit/lib/kbuffercoltextexport.h create mode 100644 khexedit/lib/kbuffercolumn.cpp create mode 100644 khexedit/lib/kbuffercolumn.h create mode 100644 khexedit/lib/kbuffercoord.h create mode 100644 khexedit/lib/kbuffercursor.cpp create mode 100644 khexedit/lib/kbuffercursor.h create mode 100644 khexedit/lib/kbufferdrag.cpp create mode 100644 khexedit/lib/kbufferdrag.h create mode 100644 khexedit/lib/kbufferlayout.cpp create mode 100644 khexedit/lib/kbufferlayout.h create mode 100644 khexedit/lib/kbufferranges.cpp create mode 100644 khexedit/lib/kbufferranges.h create mode 100644 khexedit/lib/kbytecodec.h create mode 100644 khexedit/lib/kbytesedit.cpp create mode 100644 khexedit/lib/kbytesedit.h create mode 100644 khexedit/lib/kcharcodec.h create mode 100644 khexedit/lib/kcharcoltextexport.cpp create mode 100644 khexedit/lib/kcharcoltextexport.h create mode 100644 khexedit/lib/kcharcolumn.cpp create mode 100644 khexedit/lib/kcharcolumn.h create mode 100644 khexedit/lib/kcoltextexport.h create mode 100644 khexedit/lib/kcolumn.cpp create mode 100644 khexedit/lib/kcolumn.h create mode 100644 khexedit/lib/kcolumnsview.cpp create mode 100644 khexedit/lib/kcolumnsview.h create mode 100644 khexedit/lib/kcoordrange.h create mode 100644 khexedit/lib/kcoordrangelist.cpp create mode 100644 khexedit/lib/kcoordrangelist.h create mode 100644 khexedit/lib/kcursor.cpp create mode 100644 khexedit/lib/kcursor.h create mode 100644 khexedit/lib/kdatabuffer.cpp create mode 100644 khexedit/lib/kdatabuffer.h create mode 100644 khexedit/lib/kfixedsizebuffer.cpp create mode 100644 khexedit/lib/kfixedsizebuffer.h create mode 100644 khexedit/lib/khe.h create mode 100644 khexedit/lib/khechar.h create mode 100644 khexedit/lib/khexedit.cpp create mode 100644 khexedit/lib/khexedit.h create mode 100644 khexedit/lib/khexedit_export.h create mode 100644 khexedit/lib/koffsetcoltextexport.cpp create mode 100644 khexedit/lib/koffsetcoltextexport.h create mode 100644 khexedit/lib/koffsetcolumn.cpp create mode 100644 khexedit/lib/koffsetcolumn.h create mode 100644 khexedit/lib/koffsetformat.cpp create mode 100644 khexedit/lib/koffsetformat.h create mode 100644 khexedit/lib/kplainbuffer.cpp create mode 100644 khexedit/lib/kplainbuffer.h create mode 100644 khexedit/lib/krange.h create mode 100644 khexedit/lib/kreadonlybuffer.h create mode 100644 khexedit/lib/ksection.h create mode 100644 khexedit/lib/ksectionlist.cpp create mode 100644 khexedit/lib/ksectionlist.h create mode 100644 khexedit/lib/kselection.h create mode 100644 khexedit/lib/kvaluecoltextexport.cpp create mode 100644 khexedit/lib/kvaluecoltextexport.h create mode 100644 khexedit/lib/kvaluecolumn.cpp create mode 100644 khexedit/lib/kvaluecolumn.h create mode 100644 khexedit/lib/kwordbufferservice.cpp create mode 100644 khexedit/lib/kwordbufferservice.h create mode 100644 khexedit/lib/kwrappingrobuffer.cpp create mode 100644 khexedit/lib/kwrappingrobuffer.h create mode 100644 khexedit/listview.cc create mode 100644 khexedit/listview.h create mode 100644 khexedit/main.cc create mode 100644 khexedit/optiondialog.cc create mode 100644 khexedit/optiondialog.h create mode 100644 khexedit/parts/Makefile.am create mode 100644 khexedit/parts/README create mode 100644 khexedit/parts/kbytesedit/Makefile.am create mode 100644 khexedit/parts/kbytesedit/README create mode 100644 khexedit/parts/kbytesedit/kbyteseditwidget.cpp create mode 100644 khexedit/parts/kbytesedit/kbyteseditwidget.desktop create mode 100644 khexedit/parts/kbytesedit/kbyteseditwidget.h create mode 100644 khexedit/parts/kpart/Makefile.am create mode 100644 khexedit/parts/kpart/khebrowserextension.cpp create mode 100644 khexedit/parts/kpart/khebrowserextension.h create mode 100644 khexedit/parts/kpart/khepart.cpp create mode 100644 khexedit/parts/kpart/khepart.h create mode 100644 khexedit/parts/kpart/khepartfactory.cpp create mode 100644 khexedit/parts/kpart/khepartfactory.h create mode 100644 khexedit/parts/kpart/khexedit2part.desktop create mode 100644 khexedit/parts/kpart/khexedit2partui.rc create mode 100644 khexedit/pics/Makefile.am create mode 100644 khexedit/pics/hexdrag.png create mode 100644 khexedit/pics/hexmask.png create mode 100644 khexedit/pics/hexwrite.png create mode 100644 khexedit/printdialogpage.cc create mode 100644 khexedit/printdialogpage.h create mode 100644 khexedit/progress.h create mode 100644 khexedit/searchbar.cc create mode 100644 khexedit/searchbar.h create mode 100644 khexedit/statusbarprogress.cc create mode 100644 khexedit/statusbarprogress.h create mode 100644 khexedit/stringdialog.cc create mode 100644 khexedit/stringdialog.h create mode 100644 khexedit/toplevel.cc create mode 100644 khexedit/toplevel.h create mode 100644 khexedit/version.h create mode 100644 kjots/ANNOUNCE create mode 100644 kjots/BUGS create mode 100644 kjots/CHANGES create mode 100644 kjots/KJotsMain.cpp create mode 100644 kjots/KJotsMain.h create mode 100644 kjots/KJotsSettings.kcfgc create mode 100644 kjots/Kjots.desktop create mode 100644 kjots/Makefile.am create mode 100644 kjots/README create mode 100644 kjots/confpagefont.ui create mode 100644 kjots/confpagemisc.ui create mode 100644 kjots/icons/Makefile.am create mode 100644 kjots/icons/README create mode 100644 kjots/icons/filedel.png create mode 100644 kjots/icons/hi16-app-kjots.png create mode 100644 kjots/icons/hi22-app-kjots.png create mode 100644 kjots/icons/hi32-app-kjots.png create mode 100644 kjots/icons/hi48-app-kjots.png create mode 100644 kjots/icons/hi64-app-kjots.png create mode 100644 kjots/kjots.kcfg create mode 100644 kjots/kjotsbookmarks.cpp create mode 100644 kjots/kjotsbookmarks.h create mode 100644 kjots/kjotsedit.cpp create mode 100644 kjots/kjotsedit.h create mode 100644 kjots/kjotsentry.cpp create mode 100644 kjots/kjotsentry.h create mode 100644 kjots/kjotsui.rc create mode 100644 kjots/main.cpp create mode 100644 klaptopdaemon/Makefile.am create mode 100644 klaptopdaemon/README create mode 100644 klaptopdaemon/acpi.cpp create mode 100644 klaptopdaemon/acpi.h create mode 100644 klaptopdaemon/acpi_helper.cpp create mode 100644 klaptopdaemon/apm.cpp create mode 100644 klaptopdaemon/apm.h create mode 100644 klaptopdaemon/applnk/.directory create mode 100644 klaptopdaemon/applnk/Makefile.am create mode 100644 klaptopdaemon/applnk/klaptopdaemon.desktop create mode 100644 klaptopdaemon/applnk/laptop.desktop create mode 100644 klaptopdaemon/applnk/pcmcia.desktop create mode 100644 klaptopdaemon/battery.cpp create mode 100644 klaptopdaemon/battery.h create mode 100644 klaptopdaemon/buttons.cpp create mode 100644 klaptopdaemon/buttons.h create mode 100644 klaptopdaemon/checkcrc.h create mode 100644 klaptopdaemon/configure.in.bot create mode 100644 klaptopdaemon/configure.in.in create mode 100644 klaptopdaemon/daemon_state.cpp create mode 100644 klaptopdaemon/daemon_state.h create mode 100644 klaptopdaemon/daemondock.cpp create mode 100644 klaptopdaemon/daemondock.h create mode 100644 klaptopdaemon/kpcmcia.cpp create mode 100644 klaptopdaemon/kpcmcia.h create mode 100644 klaptopdaemon/kpcmciainfo.cpp create mode 100644 klaptopdaemon/kpcmciainfo.h create mode 100644 klaptopdaemon/krichtextlabel.cpp create mode 100644 klaptopdaemon/krichtextlabel.h create mode 100644 klaptopdaemon/laptop_check.cpp create mode 100644 klaptopdaemon/laptop_daemon.cpp create mode 100644 klaptopdaemon/laptop_daemon.h create mode 100644 klaptopdaemon/linux/bulkmem.h create mode 100644 klaptopdaemon/linux/ciscode.h create mode 100644 klaptopdaemon/linux/cisreg.h create mode 100644 klaptopdaemon/linux/cistpl.h create mode 100644 klaptopdaemon/linux/cs.h create mode 100644 klaptopdaemon/linux/cs_types.h create mode 100644 klaptopdaemon/linux/driver_ops.h create mode 100644 klaptopdaemon/linux/ds.h create mode 100644 klaptopdaemon/linux/ftl.h create mode 100644 klaptopdaemon/linux/k_compat.h create mode 100644 klaptopdaemon/linux/mem_op.h create mode 100644 klaptopdaemon/linux/memory.h create mode 100644 klaptopdaemon/linux/ss.h create mode 100644 klaptopdaemon/linux/version.h create mode 100644 klaptopdaemon/main.cpp create mode 100644 klaptopdaemon/main.h create mode 100644 klaptopdaemon/makecrc.cpp create mode 100644 klaptopdaemon/pcmcia.cpp create mode 100644 klaptopdaemon/pcmcia.h create mode 100644 klaptopdaemon/pics/Makefile.am create mode 100644 klaptopdaemon/pics/README create mode 100644 klaptopdaemon/pics/actions/Makefile.am create mode 100644 klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nobattery.png create mode 100644 klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nocharge.png create mode 100644 klaptopdaemon/pics/actions/cr16-action-alt2_laptop_power.png create mode 100644 klaptopdaemon/pics/actions/cr16-action-alt3_laptop_nocharge.png create mode 100644 klaptopdaemon/pics/actions/cr16-action-alt3_laptop_power.png create mode 100644 klaptopdaemon/pics/actions/cr16-action-alt_laptop_nocharge.png create mode 100644 klaptopdaemon/pics/actions/cr16-action-alt_laptop_power.png create mode 100644 klaptopdaemon/pics/actions/cr16-action-laptop_charge.png create mode 100644 klaptopdaemon/pics/actions/cr16-action-laptop_nobattery.png create mode 100644 klaptopdaemon/pics/actions/cr16-action-laptop_nocharge.png create mode 100644 klaptopdaemon/pics/actions/cr16-action-power.png create mode 100644 klaptopdaemon/pics/actions/cr22-action-laptop_charge.png create mode 100644 klaptopdaemon/pics/actions/cr22-action-laptop_nobattery.png create mode 100644 klaptopdaemon/pics/actions/cr22-action-laptop_nocharge.png create mode 100644 klaptopdaemon/pics/actions/cr22-action-laptop_power.png create mode 100644 klaptopdaemon/pics/actions/cr32-action-power.png create mode 100644 klaptopdaemon/pics/cr128-app-laptop_battery.png create mode 100644 klaptopdaemon/pics/cr16-app-laptop_battery.png create mode 100644 klaptopdaemon/pics/cr16-app-laptop_pcmcia.png create mode 100644 klaptopdaemon/pics/cr32-app-laptop_battery.png create mode 100644 klaptopdaemon/pics/cr32-app-laptop_pcmcia.png create mode 100644 klaptopdaemon/pics/cr48-app-laptop_battery.png create mode 100644 klaptopdaemon/pics/cr48-app-laptop_pcmcia.png create mode 100644 klaptopdaemon/pics/cr64-app-laptop_battery.png create mode 100644 klaptopdaemon/pics/crsc-app-laptop_battery.svgz create mode 100644 klaptopdaemon/portable.cpp create mode 100644 klaptopdaemon/portable.h create mode 100644 klaptopdaemon/power.cpp create mode 100644 klaptopdaemon/power.h create mode 100644 klaptopdaemon/profile.cpp create mode 100644 klaptopdaemon/profile.h create mode 100644 klaptopdaemon/smapi.h create mode 100644 klaptopdaemon/smapibios.h create mode 100644 klaptopdaemon/smapidev.c create mode 100644 klaptopdaemon/smapidev.h create mode 100644 klaptopdaemon/sony.cpp create mode 100644 klaptopdaemon/sony.h create mode 100644 klaptopdaemon/thinkpad_common.h create mode 100644 klaptopdaemon/version.h create mode 100644 klaptopdaemon/wake_laptop.cpp create mode 100644 klaptopdaemon/warning.cpp create mode 100644 klaptopdaemon/warning.h create mode 100644 klaptopdaemon/xautolock.cc create mode 100644 klaptopdaemon/xautolock.h create mode 100644 klaptopdaemon/xautolock_c.h create mode 100644 klaptopdaemon/xautolock_diy.c create mode 100644 klaptopdaemon/xautolock_engine.c create mode 100644 kmilo/Makefile.am create mode 100644 kmilo/README create mode 100644 kmilo/TODO create mode 100644 kmilo/asus/Makefile.am create mode 100644 kmilo/asus/README create mode 100644 kmilo/asus/asus.cpp create mode 100644 kmilo/asus/asus.h create mode 100644 kmilo/asus/kmilo_asus.desktop create mode 100644 kmilo/configure.in.in create mode 100644 kmilo/delli8k/Makefile.am create mode 100644 kmilo/delli8k/README create mode 100644 kmilo/delli8k/delli8k.cpp create mode 100644 kmilo/delli8k/delli8k.h create mode 100644 kmilo/delli8k/i8k.h create mode 100644 kmilo/delli8k/kmilo_delli8k.desktop create mode 100644 kmilo/demo/Makefile.am create mode 100644 kmilo/demo/demo.cpp create mode 100644 kmilo/demo/demo.h create mode 100644 kmilo/demo/kmilo_demo.desktop create mode 100644 kmilo/generic/Makefile.am create mode 100644 kmilo/generic/README create mode 100644 kmilo/generic/generic_monitor.cpp create mode 100644 kmilo/generic/generic_monitor.h create mode 100644 kmilo/generic/kmilo_generic.desktop create mode 100644 kmilo/kmilo_kvaio/Makefile.am create mode 100644 kmilo/kmilo_kvaio/README.sonypi.h create mode 100644 kmilo/kmilo_kvaio/kcmkvaio/Makefile.am create mode 100644 kmilo/kmilo_kvaio/kcmkvaio/kcmkvaio_general.ui create mode 100644 kmilo/kmilo_kvaio/kcmkvaio/kcmkvaio_general.ui.h create mode 100644 kmilo/kmilo_kvaio/kcmkvaio/kvaio.desktop create mode 100644 kmilo/kmilo_kvaio/kcmkvaio/main.cpp create mode 100644 kmilo/kmilo_kvaio/kcmkvaio/main.h create mode 100644 kmilo/kmilo_kvaio/kmilo_kvaio.cpp create mode 100644 kmilo/kmilo_kvaio/kmilo_kvaio.desktop create mode 100644 kmilo/kmilo_kvaio/kmilo_kvaio.h create mode 100644 kmilo/kmilo_kvaio/kvaio.cpp create mode 100644 kmilo/kmilo_kvaio/kvaio.h create mode 100644 kmilo/kmilo_kvaio/kvaiodriverinterface.cpp create mode 100644 kmilo/kmilo_kvaio/kvaiodriverinterface.h create mode 100644 kmilo/kmilo_kvaio/sonypi.h create mode 100644 kmilo/kmilod/Makefile.am create mode 100644 kmilo/kmilod/defaultskin.cpp create mode 100644 kmilo/kmilod/defaultskin.h create mode 100644 kmilo/kmilod/defaultwidget.ui create mode 100644 kmilo/kmilod/displayskin.cpp create mode 100644 kmilo/kmilod/displayskin.h create mode 100644 kmilo/kmilod/kmilod.cpp create mode 100644 kmilo/kmilod/kmilod.desktop create mode 100644 kmilo/kmilod/kmilod.h create mode 100644 kmilo/kmilod/kmilointerface.cpp create mode 100644 kmilo/kmilod/kmilointerface.h create mode 100644 kmilo/kmilod/kmilopluginsvc.desktop create mode 100644 kmilo/kmilod/monitor.cpp create mode 100644 kmilo/kmilod/monitor.h create mode 100644 kmilo/powerbook/Makefile.am create mode 100644 kmilo/powerbook/kmilo_powerbook.desktop create mode 100644 kmilo/powerbook/pb_monitor.cpp create mode 100644 kmilo/powerbook/pb_monitor.h create mode 100644 kmilo/powerbook2/Makefile.am create mode 100644 kmilo/powerbook2/kmilo_powerbook.desktop create mode 100644 kmilo/powerbook2/pb_monitor.cpp create mode 100644 kmilo/powerbook2/pb_monitor.h create mode 100644 kmilo/thinkpad/Makefile.am create mode 100644 kmilo/thinkpad/README create mode 100644 kmilo/thinkpad/kcmthinkpad/Makefile.am create mode 100644 kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui create mode 100644 kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui.h create mode 100644 kmilo/thinkpad/kcmthinkpad/main.cpp create mode 100644 kmilo/thinkpad/kcmthinkpad/main.h create mode 100644 kmilo/thinkpad/kcmthinkpad/thinkpad.desktop create mode 100644 kmilo/thinkpad/kmilo_thinkpad.desktop create mode 100644 kmilo/thinkpad/thinkpad.cpp create mode 100644 kmilo/thinkpad/thinkpad.h create mode 100644 kregexpeditor/Comments create mode 100644 kregexpeditor/KMultiFormListBox/Makefile.am create mode 100644 kregexpeditor/KMultiFormListBox/TODO create mode 100644 kregexpeditor/KMultiFormListBox/ccp.cpp create mode 100644 kregexpeditor/KMultiFormListBox/ccp.h create mode 100644 kregexpeditor/KMultiFormListBox/idx.xbm create mode 100644 kregexpeditor/KMultiFormListBox/indexWindow.cpp create mode 100644 kregexpeditor/KMultiFormListBox/indexWindow.h create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.cpp create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.h create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistbox-shower.h create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.cpp create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.h create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistbox.cpp create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistbox.h create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.cpp create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.h create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.cpp create mode 100644 kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.h create mode 100644 kregexpeditor/KMultiFormListBox/widgetwindow.cpp create mode 100644 kregexpeditor/KMultiFormListBox/widgetwindow.h create mode 100644 kregexpeditor/KMultiFormListBox/windowlistboxitem.cpp create mode 100644 kregexpeditor/KMultiFormListBox/windowlistboxitem.h create mode 100644 kregexpeditor/KWidgetStreamer/Makefile.am create mode 100644 kregexpeditor/KWidgetStreamer/kwidgetstreamer.cpp create mode 100644 kregexpeditor/KWidgetStreamer/kwidgetstreamer.h create mode 100644 kregexpeditor/Makefile.am create mode 100644 kregexpeditor/TODO create mode 100644 kregexpeditor/altnregexp.cpp create mode 100644 kregexpeditor/altnregexp.h create mode 100644 kregexpeditor/altnwidget.cpp create mode 100644 kregexpeditor/altnwidget.h create mode 100644 kregexpeditor/auxbuttons.cpp create mode 100644 kregexpeditor/auxbuttons.h create mode 100644 kregexpeditor/characterswidget.cpp create mode 100644 kregexpeditor/characterswidget.h create mode 100644 kregexpeditor/charselector.cpp create mode 100644 kregexpeditor/charselector.h create mode 100644 kregexpeditor/compoundregexp.cpp create mode 100644 kregexpeditor/compoundregexp.h create mode 100644 kregexpeditor/compoundwidget.cpp create mode 100644 kregexpeditor/compoundwidget.h create mode 100644 kregexpeditor/concregexp.cpp create mode 100644 kregexpeditor/concregexp.h create mode 100644 kregexpeditor/concwidget.cpp create mode 100644 kregexpeditor/concwidget.h create mode 100644 kregexpeditor/dcbutton.cpp create mode 100644 kregexpeditor/dcbutton.h create mode 100644 kregexpeditor/dotregexp.cpp create mode 100644 kregexpeditor/dotregexp.h create mode 100644 kregexpeditor/drag.cpp create mode 100644 kregexpeditor/drag.h create mode 100644 kregexpeditor/dragaccepter.cpp create mode 100644 kregexpeditor/dragaccepter.h create mode 100644 kregexpeditor/editorwindow.cpp create mode 100644 kregexpeditor/editorwindow.h create mode 100644 kregexpeditor/emacsregexpconverter.cpp create mode 100644 kregexpeditor/emacsregexpconverter.h create mode 100644 kregexpeditor/errormap.cpp create mode 100644 kregexpeditor/errormap.h create mode 100755 kregexpeditor/extractrc-from-regexp create mode 100644 kregexpeditor/gen_qregexplexer.cpp create mode 100644 kregexpeditor/gen_qregexpparser.cc create mode 100644 kregexpeditor/gen_qregexpparser.hh create mode 100644 kregexpeditor/hi128-app-kregexpeditor.png create mode 100644 kregexpeditor/hi16-app-kregexpeditor.png create mode 100644 kregexpeditor/hi22-app-kregexpeditor.png create mode 100644 kregexpeditor/hi32-app-kregexpeditor.png create mode 100644 kregexpeditor/hi48-app-kregexpeditor.png create mode 100644 kregexpeditor/hi64-app-kregexpeditor.png create mode 100644 kregexpeditor/infopage.cpp create mode 100644 kregexpeditor/infopage.h create mode 100644 kregexpeditor/kregexpeditor.desktop create mode 100644 kregexpeditor/kregexpeditor.svgz create mode 100644 kregexpeditor/kregexpeditorfactory.cpp create mode 100644 kregexpeditor/kregexpeditorgui.cpp create mode 100644 kregexpeditor/kregexpeditorgui.desktop create mode 100644 kregexpeditor/kregexpeditorgui.h create mode 100644 kregexpeditor/kregexpeditorprivate.cpp create mode 100644 kregexpeditor/kregexpeditorprivate.h create mode 100644 kregexpeditor/limitedcharlineedit.cpp create mode 100644 kregexpeditor/limitedcharlineedit.h create mode 100644 kregexpeditor/lookaheadregexp.cpp create mode 100644 kregexpeditor/lookaheadregexp.h create mode 100644 kregexpeditor/lookaheadwidget.cpp create mode 100644 kregexpeditor/lookaheadwidget.h create mode 100644 kregexpeditor/main.cpp create mode 100644 kregexpeditor/multicontainerwidget.cpp create mode 100644 kregexpeditor/multicontainerwidget.h create mode 100644 kregexpeditor/myfontmetrics.cpp create mode 100644 kregexpeditor/myfontmetrics.h create mode 100644 kregexpeditor/pair.h create mode 100644 kregexpeditor/picts/Makefile.am create mode 100644 kregexpeditor/picts/altn.png create mode 100644 kregexpeditor/picts/anychar.png create mode 100644 kregexpeditor/picts/autoverify.png create mode 100644 kregexpeditor/picts/begline.png create mode 100644 kregexpeditor/picts/characters.png create mode 100644 kregexpeditor/picts/compound.png create mode 100644 kregexpeditor/picts/endline.png create mode 100644 kregexpeditor/picts/error.png create mode 100644 kregexpeditor/picts/neglookahead.png create mode 100644 kregexpeditor/picts/nonwordboundary.png create mode 100644 kregexpeditor/picts/poslookahead.png create mode 100644 kregexpeditor/picts/repeat.png create mode 100644 kregexpeditor/picts/select.png create mode 100644 kregexpeditor/picts/text.png create mode 100644 kregexpeditor/picts/verify.png create mode 100644 kregexpeditor/picts/wordboundary.png create mode 100644 kregexpeditor/positionregexp.cpp create mode 100644 kregexpeditor/positionregexp.h create mode 100644 kregexpeditor/predefined/General/Makefile.am create mode 100644 kregexpeditor/predefined/General/anything.regexp create mode 100644 kregexpeditor/predefined/General/spaces.regexp create mode 100644 kregexpeditor/predefined/Makefile.am create mode 100644 kregexpeditor/predefined/README create mode 100644 kregexpeditor/qregexpparser.l create mode 100644 kregexpeditor/qregexpparser.y create mode 100755 kregexpeditor/qt-only/clean create mode 100644 kregexpeditor/qt-only/compat.cpp create mode 100644 kregexpeditor/qt-only/compat.h create mode 100755 kregexpeditor/qt-only/compile create mode 100644 kregexpeditor/qt-only/qt-only.pro create mode 100644 kregexpeditor/qt-only/win-release.bat create mode 100644 kregexpeditor/qtregexpconverter.cpp create mode 100644 kregexpeditor/qtregexpconverter.h create mode 100644 kregexpeditor/qtregexphighlighter.cpp create mode 100644 kregexpeditor/qtregexphighlighter.h create mode 100644 kregexpeditor/regexp.cpp create mode 100644 kregexpeditor/regexp.h create mode 100644 kregexpeditor/regexpbuttons.cpp create mode 100644 kregexpeditor/regexpbuttons.h create mode 100644 kregexpeditor/regexpconverter.cpp create mode 100644 kregexpeditor/regexpconverter.h create mode 100644 kregexpeditor/regexphighlighter.cpp create mode 100644 kregexpeditor/regexphighlighter.h create mode 100644 kregexpeditor/regexpwidget.cpp create mode 100644 kregexpeditor/regexpwidget.h create mode 100644 kregexpeditor/repeatregexp.cpp create mode 100644 kregexpeditor/repeatregexp.h create mode 100644 kregexpeditor/repeatwidget.cpp create mode 100644 kregexpeditor/repeatwidget.h create mode 100644 kregexpeditor/scrollededitorwindow.cpp create mode 100644 kregexpeditor/scrollededitorwindow.h create mode 100644 kregexpeditor/selectablelineedit.cpp create mode 100644 kregexpeditor/selectablelineedit.h create mode 100644 kregexpeditor/singlecontainerwidget.cpp create mode 100644 kregexpeditor/singlecontainerwidget.h create mode 100644 kregexpeditor/test-without-dl/Makefile.am create mode 100644 kregexpeditor/test-without-dl/main.cpp create mode 100644 kregexpeditor/textrangeregexp.cpp create mode 100644 kregexpeditor/textrangeregexp.h create mode 100644 kregexpeditor/textregexp.cpp create mode 100644 kregexpeditor/textregexp.h create mode 100644 kregexpeditor/textwidget.cpp create mode 100644 kregexpeditor/textwidget.h create mode 100644 kregexpeditor/triple.h create mode 100644 kregexpeditor/userdefinedregexps.cpp create mode 100644 kregexpeditor/userdefinedregexps.h create mode 100644 kregexpeditor/util.cpp create mode 100644 kregexpeditor/util.h create mode 100644 kregexpeditor/verifier.cpp create mode 100644 kregexpeditor/verifier.h create mode 100644 kregexpeditor/verifybuttons.cpp create mode 100644 kregexpeditor/verifybuttons.h create mode 100644 kregexpeditor/widgetfactory.cpp create mode 100644 kregexpeditor/widgetfactory.h create mode 100644 kregexpeditor/zerowidgets.cpp create mode 100644 kregexpeditor/zerowidgets.h create mode 100644 ksim/AUTHORS create mode 100644 ksim/BUGS create mode 100644 ksim/COPYING create mode 100644 ksim/ChangeLog create mode 100644 ksim/Makefile.am create mode 100644 ksim/README create mode 100644 ksim/TODO create mode 100644 ksim/baselist.h create mode 100644 ksim/configure.in.in create mode 100644 ksim/generalprefs.cpp create mode 100644 ksim/generalprefs.h create mode 100644 ksim/ksim.cpp create mode 100644 ksim/ksim.desktop create mode 100644 ksim/ksim.h create mode 100644 ksim/ksim_panelextensionrc create mode 100644 ksim/ksimframe.cpp create mode 100644 ksim/ksimframe.h create mode 100644 ksim/ksimpref.cpp create mode 100644 ksim/ksimpref.h create mode 100644 ksim/ksimsysinfo.cpp create mode 100644 ksim/ksimsysinfo.h create mode 100644 ksim/ksimview.cpp create mode 100644 ksim/ksimview.h create mode 100644 ksim/library/Makefile.am create mode 100644 ksim/library/chart.cpp create mode 100644 ksim/library/chart.h create mode 100644 ksim/library/common.cpp create mode 100644 ksim/library/common.h create mode 100644 ksim/library/ksimconfig.cpp create mode 100644 ksim/library/ksimconfig.h create mode 100644 ksim/library/label.cpp create mode 100644 ksim/library/label.h create mode 100644 ksim/library/led.cpp create mode 100644 ksim/library/led.h create mode 100644 ksim/library/pluginglobal.cpp create mode 100644 ksim/library/pluginglobal.h create mode 100644 ksim/library/pluginloader.cpp create mode 100644 ksim/library/pluginloader.h create mode 100644 ksim/library/pluginmodule.cpp create mode 100644 ksim/library/pluginmodule.h create mode 100644 ksim/library/progress.cpp create mode 100644 ksim/library/progress.h create mode 100644 ksim/library/themeloader.cpp create mode 100644 ksim/library/themeloader.h create mode 100644 ksim/library/themetypes.h create mode 100644 ksim/monitorprefs.cpp create mode 100644 ksim/monitorprefs.h create mode 100644 ksim/monitors/Makefile.am create mode 100644 ksim/monitors/cpu/Makefile.am create mode 100644 ksim/monitors/cpu/cpu.desktop create mode 100644 ksim/monitors/cpu/cr16-device-ksim_cpu.png create mode 100644 ksim/monitors/cpu/ksimcpu.cpp create mode 100644 ksim/monitors/cpu/ksimcpu.h create mode 100644 ksim/monitors/disk/Makefile.am create mode 100644 ksim/monitors/disk/configure.in.in create mode 100644 ksim/monitors/disk/disk.desktop create mode 100644 ksim/monitors/disk/ksimdisk.cpp create mode 100644 ksim/monitors/disk/ksimdisk.h create mode 100644 ksim/monitors/filesystem/DFree.desktop create mode 100644 ksim/monitors/filesystem/Makefile.am create mode 100644 ksim/monitors/filesystem/configure.in.in create mode 100644 ksim/monitors/filesystem/filesystemstats.cpp create mode 100644 ksim/monitors/filesystem/filesystemstats.h create mode 100644 ksim/monitors/filesystem/filesystemwidget.cpp create mode 100644 ksim/monitors/filesystem/filesystemwidget.h create mode 100644 ksim/monitors/filesystem/fsystemconfig.cpp create mode 100644 ksim/monitors/filesystem/fsystemconfig.h create mode 100644 ksim/monitors/filesystem/fsystemiface.h create mode 100644 ksim/monitors/filesystem/ksimfsystem.cpp create mode 100644 ksim/monitors/filesystem/ksimfsystem.h create mode 100644 ksim/monitors/i8k/Makefile.am create mode 100644 ksim/monitors/i8k/i8k.desktop create mode 100644 ksim/monitors/i8k/ksimi8k.cpp create mode 100644 ksim/monitors/i8k/ksimi8k.h create mode 100644 ksim/monitors/lm_sensors/Lm_sensors.desktop create mode 100644 ksim/monitors/lm_sensors/Makefile.am create mode 100644 ksim/monitors/lm_sensors/NVCtrl.c create mode 100644 ksim/monitors/lm_sensors/NVCtrl.h create mode 100644 ksim/monitors/lm_sensors/NVCtrlLib.h create mode 100644 ksim/monitors/lm_sensors/ksimsensors.cpp create mode 100644 ksim/monitors/lm_sensors/ksimsensors.h create mode 100644 ksim/monitors/lm_sensors/ksimsensorsiface.h create mode 100644 ksim/monitors/lm_sensors/nv_control.h create mode 100644 ksim/monitors/lm_sensors/sensorbase.cpp create mode 100644 ksim/monitors/lm_sensors/sensorbase.h create mode 100644 ksim/monitors/lm_sensors/sensorsconfig.cpp create mode 100644 ksim/monitors/lm_sensors/sensorsconfig.h create mode 100644 ksim/monitors/mail/Makefile.am create mode 100644 ksim/monitors/mail/ksimmail.cpp create mode 100644 ksim/monitors/mail/ksimmail.h create mode 100644 ksim/monitors/mail/mail.desktop create mode 100644 ksim/monitors/net/Makefile.am create mode 100644 ksim/monitors/net/Net.desktop create mode 100644 ksim/monitors/net/ksimnet.cpp create mode 100644 ksim/monitors/net/ksimnet.h create mode 100644 ksim/monitors/net/netconfig.cpp create mode 100644 ksim/monitors/net/netconfig.h create mode 100644 ksim/monitors/net/netdevices.h create mode 100644 ksim/monitors/net/netdialog.cpp create mode 100644 ksim/monitors/net/netdialog.h create mode 100644 ksim/monitors/snmp/Makefile.am create mode 100644 ksim/monitors/snmp/Snmp.desktop create mode 100644 ksim/monitors/snmp/browsedialog.cpp create mode 100644 ksim/monitors/snmp/browsedialog.h create mode 100644 ksim/monitors/snmp/browsedialogbase.ui create mode 100644 ksim/monitors/snmp/chartmonitor.cpp create mode 100644 ksim/monitors/snmp/chartmonitor.h create mode 100644 ksim/monitors/snmp/configpage.cpp create mode 100644 ksim/monitors/snmp/configpage.h create mode 100644 ksim/monitors/snmp/configure.in.in create mode 100644 ksim/monitors/snmp/configwidget.ui create mode 100644 ksim/monitors/snmp/hostconfig.cpp create mode 100644 ksim/monitors/snmp/hostconfig.h create mode 100644 ksim/monitors/snmp/hostdialog.cpp create mode 100644 ksim/monitors/snmp/hostdialog.h create mode 100644 ksim/monitors/snmp/hostdialogbase.ui create mode 100644 ksim/monitors/snmp/identifier.cpp create mode 100644 ksim/monitors/snmp/identifier.h create mode 100644 ksim/monitors/snmp/labelmonitor.cpp create mode 100644 ksim/monitors/snmp/labelmonitor.h create mode 100644 ksim/monitors/snmp/monitor.cpp create mode 100644 ksim/monitors/snmp/monitor.h create mode 100644 ksim/monitors/snmp/monitorconfig.cpp create mode 100644 ksim/monitors/snmp/monitorconfig.h create mode 100644 ksim/monitors/snmp/monitordialog.cpp create mode 100644 ksim/monitors/snmp/monitordialog.h create mode 100644 ksim/monitors/snmp/monitordialogbase.ui create mode 100644 ksim/monitors/snmp/pdu.cpp create mode 100644 ksim/monitors/snmp/pdu.h create mode 100644 ksim/monitors/snmp/plugin.cpp create mode 100644 ksim/monitors/snmp/plugin.h create mode 100644 ksim/monitors/snmp/probedialog.cpp create mode 100644 ksim/monitors/snmp/probedialog.h create mode 100644 ksim/monitors/snmp/proberesultdialog.cpp create mode 100644 ksim/monitors/snmp/proberesultdialog.h create mode 100644 ksim/monitors/snmp/proberesultdialogbase.ui create mode 100644 ksim/monitors/snmp/session.cpp create mode 100644 ksim/monitors/snmp/session.h create mode 100644 ksim/monitors/snmp/snmp.cpp create mode 100644 ksim/monitors/snmp/snmp.h create mode 100644 ksim/monitors/snmp/snmp_p.h create mode 100644 ksim/monitors/snmp/snmplib.cpp create mode 100644 ksim/monitors/snmp/snmplib.h create mode 100644 ksim/monitors/snmp/value.cpp create mode 100644 ksim/monitors/snmp/value.h create mode 100644 ksim/monitors/snmp/value_p.h create mode 100644 ksim/monitors/snmp/view.cpp create mode 100644 ksim/monitors/snmp/view.h create mode 100644 ksim/monitors/snmp/walker.cpp create mode 100644 ksim/monitors/snmp/walker.h create mode 100644 ksim/pics/Makefile.am create mode 100644 ksim/pics/cr16-app-ksim.png create mode 100644 ksim/pics/cr32-app-ksim.png create mode 100644 ksim/pics/cr48-app-ksim.png create mode 100644 ksim/pics/misc/Makefile.am create mode 100644 ksim/pics/misc/clock.png create mode 100644 ksim/pics/misc/uptime.png create mode 100644 ksim/systeminfo.cpp create mode 100644 ksim/systeminfo.h create mode 100644 ksim/themeprefs.cpp create mode 100644 ksim/themeprefs.h create mode 100644 ksim/themes/Makefile.am create mode 100644 ksim/themes/ksim/Makefile.am create mode 100644 ksim/themes/ksim/bg_chart.png create mode 100644 ksim/themes/ksim/bg_grid.png create mode 100644 ksim/themes/ksim/bg_meter.png create mode 100644 ksim/themes/ksim/bg_panel.png create mode 100644 ksim/themes/ksim/decal_net_leds.png create mode 100644 ksim/themes/ksim/frame_bottom.png create mode 100644 ksim/themes/ksim/frame_left.png create mode 100644 ksim/themes/ksim/frame_right.png create mode 100644 ksim/themes/ksim/frame_top.png create mode 100644 ksim/themes/ksim/gkrellmrc create mode 100644 ksim/themes/ksim/gkrellmrc_ksim create mode 100644 ksim/themes/ksim/host/Makefile.am create mode 100644 ksim/themes/ksim/host/bg_meter.png create mode 100644 ksim/themes/ksim/krell_meter.png create mode 100644 ksim/themes/ksim/krell_panel.png create mode 100644 ksim/themes/ksim/krell_slider.png create mode 100644 ksim/themes/ksim/mail/Makefile.am create mode 100644 ksim/themes/ksim/mail/decal_mail.png create mode 100644 ksim/themes/ksim/mail/krell_mail.png create mode 100644 ksim/themes/ksim/mail/krell_mail_daemon.png create mode 100644 ktimer/Makefile.am create mode 100644 ktimer/hi128-app-ktimer.png create mode 100644 ktimer/hi16-app-ktimer.png create mode 100644 ktimer/hi32-app-ktimer.png create mode 100644 ktimer/hi48-app-ktimer.png create mode 100644 ktimer/ktimer.cpp create mode 100644 ktimer/ktimer.desktop create mode 100644 ktimer/ktimer.h create mode 100644 ktimer/main.cpp create mode 100644 ktimer/prefwidget.ui create mode 100644 kwallet/Makefile.am create mode 100644 kwallet/TODO create mode 100644 kwallet/allyourbase.cpp create mode 100644 kwallet/allyourbase.h create mode 100644 kwallet/hi128-app-kwalletmanager.png create mode 100644 kwallet/hi128-app-kwalletmanager2.png create mode 100644 kwallet/hi16-app-kwalletmanager.png create mode 100644 kwallet/hi16-app-kwalletmanager2.png create mode 100644 kwallet/hi22-app-kwalletmanager.png create mode 100644 kwallet/hi32-app-kwalletmanager.png create mode 100644 kwallet/hi32-app-kwalletmanager2.png create mode 100644 kwallet/hi48-app-kwalletmanager.png create mode 100644 kwallet/hi48-app-kwalletmanager2.png create mode 100644 kwallet/hi64-app-kwalletmanager.png create mode 100644 kwallet/hi64-app-kwalletmanager2.png create mode 100644 kwallet/icons/Makefile.am create mode 100644 kwallet/icons/cr22-action-folder_closed.png create mode 100644 kwallet/icons/cr22-action-folder_open.png create mode 100644 kwallet/icons/cr22-action-wallet_closed.png create mode 100644 kwallet/icons/cr22-action-wallet_open.png create mode 100644 kwallet/kbetterthankdialogbase.ui create mode 100644 kwallet/kbetterthankdialogbase.ui.h create mode 100644 kwallet/konfigurator/Makefile.am create mode 100644 kwallet/konfigurator/konfigurator.cpp create mode 100644 kwallet/konfigurator/konfigurator.h create mode 100644 kwallet/konfigurator/kwallet_config.desktop create mode 100644 kwallet/konfigurator/kwalletconfig.desktop create mode 100644 kwallet/konfigurator/kwalletmanager_show.desktop create mode 100644 kwallet/konfigurator/walletconfigwidget.ui create mode 100644 kwallet/kwalleteditor.cpp create mode 100644 kwallet/kwalleteditor.h create mode 100644 kwallet/kwalleteditor.rc create mode 100644 kwallet/kwalletmanager-kwalletd.desktop create mode 100644 kwallet/kwalletmanager.cpp create mode 100644 kwallet/kwalletmanager.desktop create mode 100644 kwallet/kwalletmanager.h create mode 100644 kwallet/kwalletmanager.rc create mode 100644 kwallet/kwalletpopup.cpp create mode 100644 kwallet/kwalletpopup.h create mode 100644 kwallet/kwmapeditor.cpp create mode 100644 kwallet/kwmapeditor.h create mode 100644 kwallet/main.cpp create mode 100644 kwallet/walletwidget.ui create mode 100644 superkaramba/AUTHORS create mode 100644 superkaramba/COPYING create mode 100644 superkaramba/ChangeLog create mode 100644 superkaramba/Doxyfile create mode 100644 superkaramba/INSTALL create mode 100644 superkaramba/Makefile.am create mode 100644 superkaramba/NEWS create mode 100644 superkaramba/README create mode 100644 superkaramba/TODO create mode 100644 superkaramba/configure.in.bot create mode 100644 superkaramba/configure.in.in create mode 100644 superkaramba/doc/Makefile.am create mode 100644 superkaramba/doc/faq/faq.css create mode 100644 superkaramba/doc/faq/faq.dat create mode 100644 superkaramba/doc/faq/faq.html create mode 100644 superkaramba/doc/faq/faq.txt create mode 100644 superkaramba/doc/faq/faqfooter.html create mode 100644 superkaramba/doc/faq/faqfooter.txt create mode 100644 superkaramba/doc/faq/faqheader.html create mode 100644 superkaramba/doc/faq/faqheader.txt create mode 100644 superkaramba/doc/python_api/api.css create mode 100644 superkaramba/doc/python_api/api_html.rc create mode 100755 superkaramba/doc/python_api/make_api_doc.sh create mode 100644 superkaramba/examples/API create mode 100644 superkaramba/examples/README create mode 100644 superkaramba/examples/api.html create mode 100644 superkaramba/examples/autoHide/main.py create mode 100644 superkaramba/examples/autoHide/main.theme create mode 100644 superkaramba/examples/autoHide/pics/MSN-64x64.png create mode 100644 superkaramba/examples/autoHide/pics/MSN-96x96.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_House-64x64.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_House-96x96.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_Mail-64x64.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_Mail-96x96.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_Mozilla-64x64.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_Mozilla-96x96.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_Sherlock-64x64.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_Sherlock-96x96.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_Terminal-64x64.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_Terminal-96x96.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_iPhoto-64x64.png create mode 100644 superkaramba/examples/autoHide/pics/Tux_iPhoto-96x96.png create mode 100644 superkaramba/examples/autoHide/pics/bar3.png create mode 100644 superkaramba/examples/autoHide/pics/bar4.png create mode 100644 superkaramba/examples/autoHide/pics/calendar.png create mode 100644 superkaramba/examples/autoHide/pics/ctrl center-64x64.png create mode 100644 superkaramba/examples/autoHide/pics/ctrl center-96x96.png create mode 100644 superkaramba/examples/autoHide/pics/iconbarback.png create mode 100644 superkaramba/examples/autoHide/pics/label3.png create mode 100644 superkaramba/examples/autoHide/pics/label4.png create mode 100644 superkaramba/examples/autoHide/pics/osxbarback.png create mode 100644 superkaramba/examples/autoHide/pics/osxbarbackBig.png create mode 100644 superkaramba/examples/autoHide/pics/pointer.png create mode 100644 superkaramba/examples/bar/bar.py create mode 100644 superkaramba/examples/bar/bar.theme create mode 100644 superkaramba/examples/bar/hor.png create mode 100644 superkaramba/examples/bar/ver.png create mode 100644 superkaramba/examples/change_interval/interval.py create mode 100644 superkaramba/examples/change_interval/interval.theme create mode 100644 superkaramba/examples/control_management/mgmt.py create mode 100644 superkaramba/examples/control_management/mgmt.theme create mode 100644 superkaramba/examples/disableRightClickMenu/disable_menu.py create mode 100644 superkaramba/examples/disableRightClickMenu/disable_menu.theme create mode 100644 superkaramba/examples/globalMouse/README create mode 100644 superkaramba/examples/globalMouse/extension/setup.py create mode 100644 superkaramba/examples/globalMouse/extension/xcursor.c create mode 100644 superkaramba/examples/globalMouse/eyes.py create mode 100644 superkaramba/examples/globalMouse/eyes.theme create mode 100644 superkaramba/examples/globalMouse/pics/eyes.png create mode 100644 superkaramba/examples/globalMouse/pics/eyes.xcf create mode 100644 superkaramba/examples/globalMouse/pics/mask.png create mode 100644 superkaramba/examples/globalMouse/pics/pupille.png create mode 100755 superkaramba/examples/globalMouse/xcursor.so create mode 100644 superkaramba/examples/graph/graph.py create mode 100644 superkaramba/examples/graph/graph.theme create mode 100644 superkaramba/examples/image/flag.png create mode 100644 superkaramba/examples/image/flag2.png create mode 100644 superkaramba/examples/image/image.py create mode 100644 superkaramba/examples/image/image.theme create mode 100755 superkaramba/examples/image/test1.sh create mode 100755 superkaramba/examples/image/test2.sh create mode 100644 superkaramba/examples/input_api/input_api.py create mode 100644 superkaramba/examples/input_api/input_api.theme create mode 100644 superkaramba/examples/input_example/input_example.py create mode 100644 superkaramba/examples/input_example/input_example.theme create mode 100644 superkaramba/examples/mouseDrag/karmix/images/bar.png create mode 100644 superkaramba/examples/mouseDrag/karmix/images/bg.png create mode 100644 superkaramba/examples/mouseDrag/karmix/karmix.py create mode 100644 superkaramba/examples/mouseDrag/karmix/karmix.theme create mode 100644 superkaramba/examples/mouseDrop/mousedrop.py create mode 100644 superkaramba/examples/mouseDrop/mousedrop.theme create mode 100644 superkaramba/examples/openCloseTheme/1.py create mode 100644 superkaramba/examples/openCloseTheme/1.theme create mode 100644 superkaramba/examples/openCloseTheme/2.theme create mode 100644 superkaramba/examples/popupMenu/calendar.png create mode 100644 superkaramba/examples/popupMenu/popupMenu.png create mode 100644 superkaramba/examples/popupMenu/popupMenu.py create mode 100644 superkaramba/examples/popupMenu/popupMenu.theme create mode 100644 superkaramba/examples/richtext/info.png create mode 100644 superkaramba/examples/richtext/penguin_executive.png create mode 100644 superkaramba/examples/richtext/richtext.py create mode 100644 superkaramba/examples/richtext/richtext.theme create mode 100644 superkaramba/examples/richtext/rtext.py create mode 100644 superkaramba/examples/richtext/rtext.theme create mode 100644 superkaramba/examples/service_group/service_group.py create mode 100644 superkaramba/examples/service_group/service_group.theme create mode 100644 superkaramba/examples/setIncomingData/1.py create mode 100644 superkaramba/examples/setIncomingData/1.theme create mode 100644 superkaramba/examples/setIncomingData/2.py create mode 100644 superkaramba/examples/setIncomingData/2.theme create mode 100644 superkaramba/examples/taskBar/cleanbar/README create mode 100644 superkaramba/examples/taskBar/cleanbar/cleanbar.py create mode 100644 superkaramba/examples/taskBar/cleanbar/cleanbar.theme create mode 100644 superkaramba/examples/taskBar/cleanbar/pics/bar2.png create mode 100644 superkaramba/examples/taskBar/cleanbar/pics/rightend.png create mode 100644 superkaramba/examples/taskBar/cleanbar/pics/rightend_new.png create mode 100644 superkaramba/examples/taskBar/cleanbar/pics/slickbar.png create mode 100644 superkaramba/examples/taskBar/cleanbar/pics/startup.png create mode 100644 superkaramba/examples/taskBar/cleanbar/pics/task.png create mode 100644 superkaramba/examples/taskBar/cleanbar/pics/task_new.png create mode 100644 superkaramba/examples/template.py create mode 100755 superkaramba/examples/test_all.sh create mode 100644 superkaramba/examples/text/text.py create mode 100644 superkaramba/examples/text/text.theme create mode 100644 superkaramba/examples/unicode/unicode.py create mode 100644 superkaramba/examples/unicode/unicode.theme create mode 100644 superkaramba/icons/Makefile.am create mode 100644 superkaramba/icons/cr128-app-superkaramba.png create mode 100644 superkaramba/icons/cr128-mime-superkaramba_theme.png create mode 100644 superkaramba/icons/cr16-app-superkaramba.png create mode 100644 superkaramba/icons/cr16-mime-superkaramba_theme.png create mode 100644 superkaramba/icons/cr22-app-superkaramba.png create mode 100644 superkaramba/icons/cr22-mime-superkaramba_theme.png create mode 100644 superkaramba/icons/cr32-app-superkaramba.png create mode 100644 superkaramba/icons/cr32-mime-superkaramba_theme.png create mode 100644 superkaramba/icons/cr48-app-superkaramba.png create mode 100644 superkaramba/icons/cr48-mime-superkaramba_theme.png create mode 100644 superkaramba/icons/cr64-app-superkaramba.png create mode 100644 superkaramba/icons/cr64-mime-superkaramba_theme.png create mode 100644 superkaramba/icons/crsc-app-superkaramba.svgz create mode 100644 superkaramba/icons/crsc-mime-superkaramba_theme.svgz create mode 100644 superkaramba/karamba.kdevelop create mode 100644 superkaramba/karamba.kdevses create mode 100644 superkaramba/mimetypes/Makefile.am create mode 100644 superkaramba/mimetypes/x-superkaramba.desktop create mode 100644 superkaramba/src/Makefile.am create mode 100644 superkaramba/src/bar.cpp create mode 100644 superkaramba/src/bar.h create mode 100644 superkaramba/src/bar_python.cpp create mode 100644 superkaramba/src/bar_python.h create mode 100644 superkaramba/src/clickable.cpp create mode 100644 superkaramba/src/clickable.h create mode 100644 superkaramba/src/clickarea.cpp create mode 100644 superkaramba/src/clickarea.h create mode 100644 superkaramba/src/clickmap.cpp create mode 100644 superkaramba/src/clickmap.h create mode 100644 superkaramba/src/config_python.cpp create mode 100644 superkaramba/src/config_python.h create mode 100644 superkaramba/src/cpusensor.cpp create mode 100644 superkaramba/src/cpusensor.h create mode 100644 superkaramba/src/datesensor.cpp create mode 100644 superkaramba/src/datesensor.h create mode 100644 superkaramba/src/dcopinterface.h create mode 100644 superkaramba/src/disksensor.cpp create mode 100644 superkaramba/src/disksensor.h create mode 100644 superkaramba/src/graph.cpp create mode 100644 superkaramba/src/graph.h create mode 100644 superkaramba/src/graph_python.cpp create mode 100644 superkaramba/src/graph_python.h create mode 100644 superkaramba/src/imagelabel.cpp create mode 100644 superkaramba/src/imagelabel.h create mode 100644 superkaramba/src/imagelabel_python.cpp create mode 100644 superkaramba/src/imagelabel_python.h create mode 100644 superkaramba/src/input.cpp create mode 100644 superkaramba/src/input.h create mode 100644 superkaramba/src/input_python.cpp create mode 100644 superkaramba/src/input_python.h create mode 100644 superkaramba/src/karamba.cpp create mode 100644 superkaramba/src/karamba.h create mode 100644 superkaramba/src/karamba_python.cpp create mode 100644 superkaramba/src/karamba_python.h create mode 100644 superkaramba/src/karambaapp.cpp create mode 100644 superkaramba/src/karambaapp.h create mode 100644 superkaramba/src/karambainterface.cpp create mode 100644 superkaramba/src/karambainterface.h create mode 100644 superkaramba/src/karambalistboxitem.cpp create mode 100644 superkaramba/src/karambalistboxitem.h create mode 100644 superkaramba/src/karambarootpixmap.cpp create mode 100644 superkaramba/src/karambarootpixmap.h create mode 100644 superkaramba/src/karambasessionmanaged.cpp create mode 100644 superkaramba/src/karambasessionmanaged.h create mode 100644 superkaramba/src/kwidgetlistbox.cpp create mode 100644 superkaramba/src/kwidgetlistbox.h create mode 100644 superkaramba/src/lineparser.cpp create mode 100644 superkaramba/src/lineparser.h create mode 100644 superkaramba/src/main.cpp create mode 100644 superkaramba/src/memsensor.cpp create mode 100644 superkaramba/src/memsensor.h create mode 100644 superkaramba/src/menu_python.cpp create mode 100644 superkaramba/src/menu_python.h create mode 100644 superkaramba/src/meter.cpp create mode 100644 superkaramba/src/meter.h create mode 100644 superkaramba/src/meter_python.cpp create mode 100644 superkaramba/src/meter_python.h create mode 100644 superkaramba/src/misc_python.cpp create mode 100644 superkaramba/src/misc_python.h create mode 100644 superkaramba/src/networksensor.cpp create mode 100644 superkaramba/src/networksensor.h create mode 100644 superkaramba/src/noatunsensor.cpp create mode 100644 superkaramba/src/noatunsensor.h create mode 100644 superkaramba/src/programsensor.cpp create mode 100644 superkaramba/src/programsensor.h create mode 100644 superkaramba/src/richtextlabel.cpp create mode 100644 superkaramba/src/richtextlabel.h create mode 100644 superkaramba/src/richtextlabel_python.cpp create mode 100644 superkaramba/src/richtextlabel_python.h create mode 100644 superkaramba/src/rsssensor.cpp create mode 100644 superkaramba/src/rsssensor.h create mode 100644 superkaramba/src/sensor.cpp create mode 100644 superkaramba/src/sensor.h create mode 100644 superkaramba/src/sensorparams.cpp create mode 100644 superkaramba/src/sensorparams.h create mode 100644 superkaramba/src/sensorsensor.cpp create mode 100644 superkaramba/src/sensorsensor.h create mode 100644 superkaramba/src/showdesktop.cpp create mode 100644 superkaramba/src/showdesktop.h create mode 100644 superkaramba/src/sklineedit.cpp create mode 100644 superkaramba/src/sklineedit.h create mode 100644 superkaramba/src/sknewstuff.cpp create mode 100644 superkaramba/src/sknewstuff.h create mode 100644 superkaramba/src/superkaramba.desktop create mode 100644 superkaramba/src/superkaramba.kcfg create mode 100644 superkaramba/src/superkaramba.lsm create mode 100644 superkaramba/src/superkarambasettings.kcfgc create mode 100644 superkaramba/src/superkarambaui.rc create mode 100644 superkaramba/src/svcgrp_python.cpp create mode 100644 superkaramba/src/svcgrp_python.h create mode 100644 superkaramba/src/systemtray.cpp create mode 100644 superkaramba/src/systemtray.h create mode 100644 superkaramba/src/systray_python.cpp create mode 100644 superkaramba/src/systray_python.h create mode 100644 superkaramba/src/task_python.cpp create mode 100644 superkaramba/src/task_python.h create mode 100644 superkaramba/src/taskbartest.cpp create mode 100644 superkaramba/src/taskbartest.h create mode 100644 superkaramba/src/taskmanager.cpp create mode 100644 superkaramba/src/taskmanager.h create mode 100644 superkaramba/src/textfield.cpp create mode 100644 superkaramba/src/textfield.h create mode 100644 superkaramba/src/textfilesensor.cpp create mode 100644 superkaramba/src/textfilesensor.h create mode 100644 superkaramba/src/textlabel.cpp create mode 100644 superkaramba/src/textlabel.h create mode 100644 superkaramba/src/textlabel_python.cpp create mode 100644 superkaramba/src/textlabel_python.h create mode 100644 superkaramba/src/themefile.cpp create mode 100644 superkaramba/src/themefile.h create mode 100644 superkaramba/src/themelocale.cpp create mode 100644 superkaramba/src/themelocale.h create mode 100644 superkaramba/src/themes_layout.ui create mode 100644 superkaramba/src/themesdlg.cpp create mode 100644 superkaramba/src/themesdlg.h create mode 100644 superkaramba/src/themewidget.cpp create mode 100644 superkaramba/src/themewidget.h create mode 100644 superkaramba/src/themewidget_layout.ui create mode 100644 superkaramba/src/uptimesensor.cpp create mode 100644 superkaramba/src/uptimesensor.h create mode 100644 superkaramba/src/widget_python.cpp create mode 100644 superkaramba/src/widget_python.h create mode 100644 superkaramba/src/xmmssensor.cpp create mode 100644 superkaramba/src/xmmssensor.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..4c064a3 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,28 @@ +Program Person held responsible +======================================= +ark Emily Ezust +kab (discontinued) Mirko Boehm +karm Sirtaj Singh Kang +kcalc Bernd Johannes Wuebben +kcharselect Reginald Stadlbauer +kdepasswd Geert Jansen +kdessh Geert Jansen +kdf Michael Kropfberger +kedit Bernd Johannes Wuebben +kfind Carsten Pfeiffer +kfloppy Bernd Johannes Wuebben +kfontmanager Hans Petter Bieker +kgpg Jean-Baptiste Mardelle +khexedit Espen Sand +kjots Christoph Neerfeld +klaptopdaemon Paul Campbell +klipper Carsten Pfeiffer +kljettool Bernd Johannes Wuebben +klpq Bernd Johannes Wuebben +kpm Mario Weilguni +ktimemon Dirk A. Mueller +ktop Chris Schlaeger +kwrite Jochen Wilhelmy + +Look in the subdirs to get more info about the authors. +The package is maintained by Matthias Elter diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..5185fd3 --- /dev/null +++ b/COPYING @@ -0,0 +1,346 @@ +NOTE! The GPL below is copyrighted by the Free Software Foundation, but +the instance of code that it refers to (the kde programs) are copyrighted +by the authors who actually wrote it. + +--------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/COPYING-DOCS b/COPYING-DOCS new file mode 100644 index 0000000..4a0fe1c --- /dev/null +++ b/COPYING-DOCS @@ -0,0 +1,397 @@ + GNU Free Documentation License + Version 1.2, November 2002 + + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (Thus, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..f8bad0c --- /dev/null +++ b/INSTALL @@ -0,0 +1,176 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/kde/bin', `/usr/local/kde/lib', etc. You can specify an +installation prefix other than `/usr/local/kde' by giving `configure' +the option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/Mainpage.dox b/Mainpage.dox new file mode 100644 index 0000000..3334ae2 --- /dev/null +++ b/Mainpage.dox @@ -0,0 +1,11 @@ +/** @mainpage KDE Utilities +* +* The KDE Utilities SVN module collects together an enormous amount +* of small shoddy utilities of dubious value that fall under the +* 'desk utilities' category and that you would normally get for +* free in a box of cereal. These include: +* +* - kfloppy, a floppy disk formatter +* - superkaramba, a form of eyecandy +* +*/ diff --git a/Makefile.am.in b/Makefile.am.in new file mode 100644 index 0000000..f5a67f1 --- /dev/null +++ b/Makefile.am.in @@ -0,0 +1,10 @@ +## kdebase/Makefile.am +## (C) 1997 Stephan Kulow + +AUTOMAKE_OPTIONS = foreign 1.6.1 +DISTCLEANFILES = inst-apps + +MAINTAINERCLEANFILES = subdirs configure.in acinclude.m4 SUBDIRS +include admin/deps.am +include admin/Doxyfile.am + diff --git a/Makefile.cvs b/Makefile.cvs new file mode 100644 index 0000000..be59a86 --- /dev/null +++ b/Makefile.cvs @@ -0,0 +1,14 @@ +all: + @echo "This Makefile is only for the CVS repository" + @echo "This will be deleted before making the distribution" + @echo "" + @if test ! -d admin; then \ + echo "Please recheckout this module!" ;\ + echo "for cvs: use checkout once and after that update again" ;\ + echo "for cvsup: checkout kde-common from cvsup and" ;\ + echo " link kde-common/admin to ./admin" ;\ + exit 1 ;\ + fi + $(MAKE) -f admin/Makefile.common cvs + +.SILENT: diff --git a/README b/README new file mode 100644 index 0000000..9e3708e --- /dev/null +++ b/README @@ -0,0 +1,51 @@ +In this file: + +* What it is +* Common Mistakes +* Debugging +* More Info + +What it is +---------- + +* ark: manager for compressed files and archives +* kcalc: scientific calculator +* kcharselect: select special characters from any fonts and put them into + the clipboard +* charselectapplet: dito, but as a Kicker applet +* kdepasswd: like 'passwd', a graphical password changer +* kdessh: front end to ssh +* kdf: like 'df', a graphical free disk space viewer +* kedit: a simple text editor, without formatting like bold, italics etc +* kfloppy: format a floppy disks with this app +* khexedit: binary file editor +* kjots: manages several "books" with a subject and notes +* klaptopdaemon: battery and power management, including KControl plugins +* kregexpeditor: graphical regular expression editor +* ktimer: execute programs after some time + +Common Mistakes +--------------- + +If configure claims Qt cannot be found, have a look at http://www.trolltech.com +to get latest copy of Qt 3.3.x version. If you have peeked there already, +grab the CVS module qt-copy from anoncvs.kde.org, or a snapshot thereof. + +Debugging +--------- + +You can use --enable-debug with the configure script, if you want to have +debug code in your KDE apps and libs. I recommend to do this, since this +is alpha software and this makes debugging things a whole lot easier. + +More Info +--------- + +Have a look at the individual subdirectories, if you want to know, what +versions of apps are included. + +Please direct any bug reports to our bug list by visiting +http://bugs.kde.org. + +General KDE discussions should go to the KDE mailing list (kde@kde.org). + diff --git a/ark/AUTHORS b/ark/AUTHORS new file mode 100644 index 0000000..0de587e --- /dev/null +++ b/ark/AUTHORS @@ -0,0 +1,5 @@ +Rob Palmbos palm9744@kettering.edu +Francois-Xavier Duranceau duranceau@kde.org +Emily Ezust emilye@corel.com +Roberto Selbach Teixeira maragato@kde.org +Helio Chissini de Castro helio@kde.org diff --git a/ark/ChangeLog b/ark/ChangeLog new file mode 100644 index 0000000..cd5b4de --- /dev/null +++ b/ark/ChangeLog @@ -0,0 +1,277 @@ + $Id$ + +2001-10-24: Roberto Selbach Teixeira + * Renamed all .cc files to .cpp to make things more logic. + +2001-06-23: Roberto Selbach Teixeira + * Fixed a bug in tar addition with non-compressed tar archives + +2001-06-10: Roberto Selbach Teixeira + * Made extraction use KURL instead of QString. + * Made extractDlg use a KHistoryCombo. + +2001-05-31 Roberto Selbach Teixeira + * Fixed a bug that made the file list freeze. + * Fixed extractDlg size to use QLayout + +2001-05-30 Roberto Selbach Teixeira + * Began using KMimeMagic to figure file types + * Began cleaning up Ark's code a bit. + +2001-05-29 Roberto Selbach Teixeira + + * compressedfile.cc (unarchFile): move to fromLocal8Bit() to allow + non-Latin1 characters in filenames. + + * ar.cc (unarchFile): .latin1() to .local8Bit() + + * zip.cc (unarchFile): .latin1() to .local8Bit() + +2000-07-10: Emily Ezust + * Added checks for available disk space + +2000-07-05: Emily Ezust + * Added some more mimetype magic. + +2000-06-28: Emily Ezust + * Made Extract dialog prettier + +2000-06-27: Emily Ezust + * Added code to let users load rar, lha, ar and tar archives that + do not have the standard extensions. You can also "Save As" into + a file with no extension provided the original is rar, lha or ar. + Zip and zoo don't like having no extension. Tar doesn't mind but + I haven't explored that tangle yet. It's complicated with all the + compressors! + * Made shell output dialog a tiny bit prettier. + +2000-06-22: Emily Ezust + * Overhaul of Directories Preferences dialog + * For Save As, ark will add proper extension if user does not have one. + +2000-06-13: Emily Ezust + * Fixed "Save As" code so that it prevents the user from saving a + zip as a tar + * Fixed bug preventing you from opening a network file after having + opened one before in the same session. + * Added a check for utilities (it will notify you e.g. that + "The utility zip is not in your PATH. Please + install it or contact your system administrator."). + * Added support for drag/adding files or drag/opening network archives + from konqy. + +2000-06-12: Emily Ezust + * Began adding network transparency + * Added a Save As option so that people can rename arks that are + temporary files + +2000-05-23: Emily Ezust + * Odds and ends: fixed problem with selecting multiple files in Add + File; added some better option enabling in the extract dialog. + +2000-05-16: Emily Ezust + * Fixed a bug in ArArch - wasn't reading TOCs properly + +2000-05-12: Emily Ezust + * Added some code to notify the user about file(s) that were not + extracted. This happens when the user disallows overwrites and + then extracts file(s) that already exist in the destination + directory. The notification happens before the extract, so that + the user can decide whether to continue or not. + * Fixed a possible memory corruption having to do with the lists passed + via the stack to unarchFile which cease to exist because unarchFile + returns before the job is done. + +2000-05-04: Emily Ezust + * Added control/shift LMB selection rules + * Added code to allow drag/extract but it doesn't work yet. Commented + it out. Not too sure about when to start the drag anyhow... have to + extract first! + * Added an "Edit With" option to let you edit files in the archive. + It would be too complicated to let the user edit more than one + file at a time, so like view, this freezes the app until the user + quits the editor. + + It even works with files that have paths! (I think - haven't + tested thoroughly) + +2000-04-27: Emily Ezust + * Got rid of a segfault that occured whenever you closed an archive + (I was deleting something that the statusbar needed (but had not + needed before KStatusBar was adopted by QStatusBar!)) + * Added code to let users drag files to extract them. Not working + yet: when I drag to konqy, it requests a filename for + clipboard content. + +2000-04-18: Emily Ezust + * Added some code to prevent tar from adding duplicate filenames + (having duplicates really screws up deletion and particular extracts) + * More archive-specific options (for all types: update only with + newer files; tar: keep absolute paths; zip, rar: store file as + symlinks (although my version of rar doesn't seem to know how + to extract a symlink??) + +2000-04-06: Emily Ezust + * Switched to KListView + * Some work on settings and archive-specific actions + * Couldn't load LHA archives with files that were symlinks; fixed + * Added more entries to the Settings and RMB menu. Toggle menu bar will + display help in the titlebar for getting the menubar back (just as + konsole does) + * Seems I need a KFileOpenWithHandler for OpenWith now... + * Moved archive column header strings from archive classes to the base + class header file on Francois-Xavier Duranceau's suggestion. + +2000-04-03: Emily Ezust + * Struggling with the Recent Files popup (fixed next day with help of + Kurt Granroth) + * Ar had a problem with some of my files; fixed + * ArkWidget destructor was never being called; fixed + +2000-03-29: Emily Ezust + * Extra GUI tweaks + * Fixed faulty drop/add into compressed file (if you chose to create a + real archive, it didn't actually add the files, just the compressed + file). + +2000-03-23: Emily Ezust + * Began migration to the XML-GUI framework. RMB menus disabled for + the moment... + +2000-03-20: Emily Ezust + * Fixed up Ar format. + +2000-03-20: Emily Ezust + * Added Rar format. Added disabling of buttons and menu entries during + operations + +2000-03-16: Emily Ezust + * Added Zoo format + +2000-03-15: Emily Ezust + * Added the class CompressedFile to the hierarchy. This + allows ark to be used to view, create, and extract compressed files. + The user will be asked if he/she wants to create a real archive if + she/he tries to add a file to the thing when there's already + a file in there. + * Added an Open With option (RMB and Action menu) + * Made use of statusbar improvements + * Made the time and date stamp in LHA sortable + +2000-03-09: Emily Ezust + * Fixed TarArch so that it warns the user before deleting the + contents of a directory. (Delete a directory entry in tar and + tar deletes everything in it, unlike zip & lha!!) + * Finished TarArch so that extract and view work. + * Added LHA format + * Simplified the Arch API a little (got rid of useless return values) + +2000-03-06: Emily Ezust + * Fixed TarArch so that the other compressors work + * Dealt with readonly archives (if the user views an archive from + within an archive, it is extracted to the /tmp directory, so all + changes will be lost.) + +2000-03-06: Emily Ezust + * Got rid of KProcess data member in Arch - no need for it with the + new way that KProcess does its work: we are always passing it + around to the functions that need it. This way we won't get + confused when there are more than one processes happening. + * Made tar more asynchronous, redid the temp file creation & updating. + +2000-03-03: Emily Ezust + * Made zip fully asynchronous. + +2000-03-02: Emily Ezust + * add and delete now work for tar files, although I'll probably + change how temp files are created from compressed tars and + how they are used to update the original archive... + Note: ark uses KTar for display and shell process for everything + else. + * Reduced the number of calls of slotSelectionChanged + * OK, _now_ I'm done with the enable/disable stuff - I swear! + * Other miscellaneous abstractions with zip->arch code + +2000-02-24: Emily Ezust + * Got showFile interface working (see zip) + * Started using KTar in tar. Seems to display OK. + No other functionality yet for tar. + +2000-02-22: Emily Ezust + * More work on the abstract base class for archives - moved lots of + slots dealing with the KProcess from zip.cpp to arch.cpp + * Some work on tar. Doesn't work yet. + +2000-02-16: Emily Ezust + * More consistent disabling/enabling of menu items and toolbar buttons. + * Added "add directory" - might need some more tweaking in zip so it + doesn't flatten the files out. + +2000-02-15: Emily Ezust + * Added drop support. Doesn't seem to work with directories though. + * Toolbar icons stopped working briefly - renamed them to ensure no + ambiguity. + +2000-02-14: Emily Ezust + * Separated GUI and backend in zip, which will be the model + for the other formats once it's just-right. Next I'll make sure + drag and drop works. + +2000-02-09: Emily Ezust + * Finally have Add and Extract working for zip + +2000-02-07: Emily Ezust + * new locking scheme to prevent users from opening the same archive + in two different windows. Handles symlinks. But I can't figure out + why raise() alone doesn't do it - I hide and show the window + instead - blech! + * made classes more const correct + * add dialog still doesn't work. Problem with KFileView? + +2000-01-18: Emily Ezust + * KUniqueApplication stuff was enabled by waba, with KCmdLineArgs + code. Modified it to work according to Cooperating-SDI model. + * Moved windowList to ArkApplication (accessed through a static + function). ArkApplication is now modelled on the singleton pattern. + +2000-01-10: Emily Ezust + * Finished renaming ArkData to ArkSettings. + * Tried using KDialogBase for Add dialog - not working too well. + +2000-01-6: Emily Ezust + * Disabled KUniqueApplication stuff for now... was interfering with + development with crashes. Will add later. + * Asks "Are you sure?" when you try to "New" over an existing zip + * Began work on new extract dialog - old one doesn't work any longer + due to kdelibs changes. Doesn't do anything yet - just trying out + for look&feel with error-checking. + Idea of extract: highlight the ones to be extracted and then + let the right archiver grab all the highlighted files (or current). + + +1999-12-16 Emily Ezust + * created ArkApplication : public KUniqueApplication + * Code now to follow the Co-operating SDI model. + * Some problems with dcop still... exiting the last window doesn't + get you back the prompt! + +1999-12-13 Emily Ezust + * fixed up icons, continued with merge: enabling toolbar buttons + and menu items. Close enables don't work yet... + * Fixed status bar totals for selection, number and size. + +1999-12-09 Emily Ezust + * started merge with Corel Linux code. + * added toolbar icons (with two more on the way), lock files, + and fixed the sorting for numeric column data. + * added preliminary code to count number of files and total sizes + in the status bar, but it does nothing so far. + * created a new problem: action_add in zip now segfaults. + +1999-07-05 Francois-Xavier Duranceau + * added selection with regular expressions + +1999-04-11 Francois-Xavier Duranceau + + * created this file + diff --git a/ark/Makefile.am b/ark/Makefile.am new file mode 100644 index 0000000..b97b034 --- /dev/null +++ b/ark/Makefile.am @@ -0,0 +1,54 @@ +# set the include path for X, qt and KDE +AM_CPPFLAGS = -D_LARGEFILE64_SOURCE $(all_includes) + +SUBDIRS = pics + +# The binary name. Changed from kzip to ark +bin_PROGRAMS = +kdeinit_LTLIBRARIES = ark.la +lib_LTLIBRARIES = + +ark_la_SOURCES = main.cpp arkapp.cpp mainwindow.cpp +ark_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +ark_la_LIBADD = libark_common.la $(LIB_KPARTS) +ark_la_COMPILE_FIRST = settings.h + +noinst_LTLIBRARIES = libark_common.la + +libark_common_la_SOURCES = settings.kcfgc archiveformatinfo.cpp +libark_common_la_LDFLAGS = $(all_libraries) -no-undefined +libark_common_la_LIBADD = $(LIB_KFILE) + +kde_module_LTLIBRARIES = libarkpart.la +libarkpart_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries) +libarkpart_la_LIBADD = libark_common.la $(LIB_KPARTS) +libarkpart_la_COMPILE_FIRST = settings.h + +libarkpart_la_SOURCES = ark_part.cpp arkfactory.cpp zip.cpp tar.cpp \ + filelistview.cpp arch.cpp lha.cpp \ + compressedfile.cpp zoo.cpp rar.cpp \ + ar.cpp arkutils.cpp archiveformatdlg.cpp \ + arkwidget.cpp searchbar.cpp \ + addition.ui extraction.ui general.ui \ + arkviewer.cpp sevenzip.cpp extractiondialog.cpp \ + ace.cpp tarlistingthread.cpp + +METASOURCES = AUTO + +rcdir = $(kde_datadir)/ark +rc_DATA = arkui.rc ark_part.rc ark_part_readonly.rc + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/ark.pot + +KDE_ICON = ark + +xdg_apps_DATA = ark.desktop +kde_kcfg_DATA = ark.kcfg + +parts_DATA = ark_part.desktop +partsdir = $(kde_servicesdir) + +#konqservice_DATA = arkservicemenu.desktop ark_directory_service.desktop +#konqservicedir = $(kde_datadir)/konqueror/servicemenus + diff --git a/ark/README b/ark/README new file mode 100644 index 0000000..156c2bb --- /dev/null +++ b/ark/README @@ -0,0 +1,4 @@ +This is Ark version 2.3.x. + +Ark is KDE archive handling tool, part of the kdeutils package. + diff --git a/ark/TODO b/ark/TODO new file mode 100644 index 0000000..cc3d455 --- /dev/null +++ b/ark/TODO @@ -0,0 +1,11 @@ +TODO +----- + +Feature-wise: +- Rename option +- Behavior-compatibility with the Konqueror filemanager + +For KDE 4.0: +- Use KArchive to handle archives +- Add support for split files +- Add support for more archive formats (ace, iso, rpm) diff --git a/ark/ace.cpp b/ark/ace.cpp new file mode 100644 index 0000000..d9cce52 --- /dev/null +++ b/ark/ace.cpp @@ -0,0 +1,181 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2005: Henrique Pinto + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ace.h" +#include "arkwidget.h" +#include "settings.h" + +AceArch::AceArch( ArkWidget *gui, const QString &filename ) + : Arch( gui, filename ) +{ + //m_archiver_program = m_unarchiver_program = "/usr/local/bin/unace"; + m_archiver_program = m_unarchiver_program = "/home/henrique/ArkTest/teste.sh"; + verifyCompressUtilityIsAvailable( m_archiver_program ); + + m_headerString = "Date Time Packed Size RatioFile"; + + m_repairYear = 5; m_fixMonth = 6; m_fixDay = 7; m_fixTime = 8; + m_dateCol = 3; + m_numCols = 5; + + m_archCols.append( new ArchColumns( 7, QRegExp( "[0-3][0-9]" ), 2 ) ); // Day + m_archCols.append( new ArchColumns( 6, QRegExp( "[01][0-9]" ), 2 ) ); // Month + m_archCols.append( new ArchColumns( 5, QRegExp( "[0-9][0-9]" ), 4 ) ); // Year + m_archCols.append( new ArchColumns( 8, QRegExp( "[0-9:]+" ), 8 ) ); // Time + m_archCols.append( new ArchColumns( 2, QRegExp( "[0-9]+" ) ) ); // Compressed Size + m_archCols.append( new ArchColumns( 1, QRegExp( "[0-9]+" ) ) ); // Size + m_archCols.append( new ArchColumns( 9, QRegExp( "[0-9][0-9]%" ) ) ); // Ratio + m_archCols.append( new ArchColumns( 0, QRegExp( "[^\\n]+" ), 4096 ) ); // Name +} + +AceArch::~AceArch() +{ +} + +void AceArch::setHeaders() +{ + ColumnList list; + list.append( FILENAME_COLUMN ); + list.append( SIZE_COLUMN ); + list.append( PACKED_COLUMN ); + list.append( TIMESTAMP_COLUMN ); + + emit headers( list ); +} + +void AceArch::open() +{ + kdDebug(1601) << "+AceArch::open()" << endl; + setHeaders(); + + m_buffer = ""; + m_header_removed = false; + m_finished = false; + + KProcess *kp = m_currentProcess = new KProcess; + *kp << m_archiver_program << "v" << m_filename; + //kp->setUseShell( true ); + + kdDebug() << "AceArch::open(): kp->args(): " << kp->args() << endl; + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedTOC(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotOpenExited(KProcess*) ) ); + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + this, SLOT( catchMeIfYouCan(KProcess*, char*, int) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigOpen( this, false, QString::null, 0 ); + } +} + +void AceArch::create() +{ + emit sigCreate( this, true, m_filename, + Arch::Extract | Arch::View ); +} + +void AceArch::addFile( const QStringList & urls ) +{ +} + +void AceArch::addDir( const QString & dirName ) +{ +} + +void AceArch::remove( QStringList *list ) +{ +} + +void AceArch::unarchFileInternal( ) +{ + if ( m_destDir.isEmpty() || m_destDir.isNull() ) + { + kdError( 1601 ) << "There was no extract directory given." << endl; + return; + } + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + // extract (and maybe overwrite) + *kp << m_unarchiver_program << "x" << "-y"; + + if ( ArkSettings::extractOverwrite() ) + { + *kp << "-o"; + } + + *kp << m_filename; + + *kp << m_destDir ; + + // if the file list is empty, no filenames go on the command line, + // and we then extract everything in the archive. + if ( m_fileList ) + { + QStringList::Iterator it; + for ( it = m_fileList->begin(); it != m_fileList->end(); ++it ) + { + *kp << (*it); + } + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotExtractExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigExtract( false ); + } +} + +void AceArch::catchMeIfYouCan( KProcess*, char *buffer, int buflen ) +{ + QString myBuf = QString::fromLatin1( buffer, buflen ); + kdDebug(1601) << " Wololo!: " << myBuf << endl; +} + +#include "ace.moc" diff --git a/ark/ace.h b/ark/ace.h new file mode 100644 index 0000000..7aed56c --- /dev/null +++ b/ark/ace.h @@ -0,0 +1,55 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2005: Henrique Pinto + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef ARK_ACE_H +#define ARK_ACE_H + +#include "arch.h" + +class KProcess; // TODO: Remove me! + +class AceArch : public Arch +{ + Q_OBJECT + public: + AceArch( ArkWidget *, const QString & ); + virtual ~AceArch(); + + virtual void open(); + virtual void create(); + + virtual void addFile( const QStringList & ); + virtual void addDir( const QString & ); + + virtual void remove( QStringList * ); + virtual void unarchFileInternal( ); + + private slots: + void catchMeIfYouCan( KProcess*, char*, int ); + + private: + void setHeaders(); +}; + +#endif // ARK_ACE_H diff --git a/ark/addition.ui b/ark/addition.ui new file mode 100644 index 0000000..a8f51d8 --- /dev/null +++ b/ark/addition.ui @@ -0,0 +1,79 @@ + +Addition + + + Addition + + + + 0 + 0 + 365 + 268 + + + + + unnamed + + + + kcfg_replaceOnlyWithNewer + + + Replace old files only &with newer files + + + + + kcfg_forceMSDOS + + + Force &MS-DOS short filenames (Zip) + + + + + kcfg_convertLF2CRLF + + + Translate &LF to DOS CRLF (Zip) + + + + + kcfg_rarStoreSymlinks + + + &Store symlinks as links (Zip, Rar) + + + + + kcfg_rarRecurseSubdirs + + + &Recursively add subfolders (Zip, Rar) + + + + + spacer2 + + + Vertical + + + Expanding + + + + 20 + 51 + + + + + + + diff --git a/ark/ar.cpp b/ark/ar.cpp new file mode 100644 index 0000000..71f44e0 --- /dev/null +++ b/ark/ar.cpp @@ -0,0 +1,263 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 1997-1999: Rob Palmbos palm9744@kettering.edu + 2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +// C includes +#include +#include +#include +#include +#include + +// QT includes +#include + +// KDE includes +#include +#include +#include +#include + +// ark includes +#include "arkwidget.h" +#include "settings.h" +#include "ar.h" + +ArArch::ArArch( ArkWidget *_gui, const QString & _fileName ) + : Arch(_gui, _fileName ) +{ + m_archiver_program = m_unarchiver_program = "ar"; + verifyCompressUtilityIsAvailable( m_archiver_program ); + verifyUncompressUtilityIsAvailable( m_unarchiver_program ); + + // Do not set headerString - there is none for Ar + m_numCols = 5; + m_dateCol = 4; m_fixYear = 8; m_repairMonth = 5; m_fixDay = 6; m_fixTime = 7; + + m_archCols.append(new ArchColumns(1, QRegExp("[a-zA-Z-]+"), 12)); // Perms + m_archCols.append(new ArchColumns(2, QRegExp("[^\\s]+"), 128)); //User/grp + m_archCols.append(new ArchColumns(3, QRegExp("[0-9]+"))); // Size + m_archCols.append(new ArchColumns(5, QRegExp("[a-zA-Z]+"), 4)); // Month + m_archCols.append(new ArchColumns(6, QRegExp("[0-9]+"), 2)); // Day + m_archCols.append(new ArchColumns(7, QRegExp("[0-9:]+"), 6)); // Time + m_archCols.append(new ArchColumns(8, QRegExp("[0-9]+"), 5)); // Year + m_archCols.append(new ArchColumns(0, QRegExp("[^\\s][^\\n]+"), 4096));// File + + kdDebug(1601) << "ArArch constructor" << endl; +} + +void ArArch::setHeaders() +{ + ColumnList list; + list.append( FILENAME_COLUMN ); + list.append( PERMISSION_COLUMN ); + list.append( OWNER_GROUP_COLUMN ); + list.append( SIZE_COLUMN ); + list.append( TIMESTAMP_COLUMN ); + + emit headers( list ); +} + +void ArArch::open() +{ + kdDebug(1601) << "+ArArch::open" << endl; + setHeaders(); + + m_buffer = ""; + + KProcess *kp = m_currentProcess = new KProcess; + *kp << m_archiver_program << "vt" << m_filename; + connect( kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedTOC(KProcess*, char*, int))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + + connect( kp, SIGNAL(processExited(KProcess*)), this, + SLOT(slotOpenExited(KProcess*))); + + if (kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + emit sigOpen(this, false, QString::null, 0 ); + } + kdDebug(1601) << "-ArArch::open" << endl; +} + +void ArArch::create() +{ + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + *kp << m_archiver_program << "c" << m_filename; + + connect( kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + + if (kp->start(KProcess::Block) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + emit sigCreate(this, false, m_filename, + Arch::Extract | Arch::Delete | Arch::Add + | Arch::View); + } + else + emit sigCreate(this, true, m_filename, + Arch::Extract | Arch::Delete | Arch::Add + | Arch::View); +} + +void ArArch::addFile( const QStringList &urls ) +{ + kdDebug(1601) << "+ArArch::addFile" << endl; + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + *kp << m_archiver_program; + + if (ArkSettings::replaceOnlyWithNewer()) + *kp << "ru"; + else + *kp << "r"; + + *kp << m_filename; + + QStringList::ConstIterator iter; + KURL url( urls.first() ); + QDir::setCurrent( url.directory() ); + for (iter = urls.begin(); iter != urls.end(); ++iter ) + { + KURL fileURL( *iter ); + *kp << fileURL.fileName(); + } + + connect( kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + + connect( kp, SIGNAL(processExited(KProcess*)), this, + SLOT(slotAddExited(KProcess*))); + + if (kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + emit sigAdd(false); + } + + kdDebug(1601) << "-ArArch::addFile" << endl; +} + +void ArArch::unarchFileInternal() +{ + // if m_fileList is empty, we extract all. + // if m_destDir is empty, abort with error. + + kdDebug(1601) << "+ArArch::unarchFile" << endl; + QString dest; + + if (m_destDir.isEmpty() || m_destDir.isNull()) + { + kdError(1601) << "There was no extract directory given." << endl; + return; + } + else dest = m_destDir; + + // ar has no option to specify the destination directory + // so I have to change to it. + + bool ret = QDir::setCurrent(dest); + // I already checked the validity of the dir before coming here + Q_ASSERT(ret); + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program; + *kp << "vx"; + *kp << m_filename; + + // if the list is empty, no filenames go on the command line, + // and we then extract everything in the archive. + if (m_fileList) + { + for ( QStringList::Iterator it = m_fileList->begin(); + it != m_fileList->end(); ++it ) + { + *kp << (*it); + } + } + + connect( kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + + connect( kp, SIGNAL(processExited(KProcess*)), this, + SLOT(slotExtractExited(KProcess*))); + + if (kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + emit sigExtract(false); + } +} + +void ArArch::remove(QStringList *list) +{ + kdDebug(1601) << "+ArArch::remove" << endl; + + if (!list) + return; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program << "d" << m_filename; + for ( QStringList::Iterator it = list->begin(); + it != list->end(); ++it ) + { + QString str = *it; + *kp << str; + } + + connect( kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + + connect( kp, SIGNAL(processExited(KProcess*)), this, + SLOT(slotDeleteExited(KProcess*))); + + if (kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + emit sigDelete(false); + } + + kdDebug(1601) << "-ArArch::remove" << endl; +} + + +#include "ar.moc" diff --git a/ark/ar.h b/ark/ar.h new file mode 100644 index 0000000..1a5f00f --- /dev/null +++ b/ark/ar.h @@ -0,0 +1,61 @@ +// -*-C++-*- emacs magic for .h files +/* + + $Id$ + + ark -- archiver for the KDE project + + Copyright (C) + + 1997-1999: Rob Palmbos palm9744@kettering.edu + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef ARARCH_H +#define ARARCH_H + +class QString; +class QCString; +class QStringList; + +class Arch; +class ArkWidget; + +class ArArch : public Arch +{ + Q_OBJECT +public: + ArArch( ArkWidget *_gui, + const QString & _fileName ); + virtual ~ArArch() {} + + virtual void open(); + virtual void create(); + + virtual void addFile( const QStringList & ); + virtual void addDir(const QString &) {} // never gets called + + virtual void remove(QStringList *); + virtual void unarchFileInternal(); + +private: + void setHeaders(); +}; + +#endif /* ARARCH_H */ diff --git a/ark/arch.cpp b/ark/arch.cpp new file mode 100644 index 0000000..8ff6a2b --- /dev/null +++ b/ark/arch.cpp @@ -0,0 +1,403 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2002: Helio Chissini de Castro + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1997-1999: Rob Palmbos palm9744@kettering.edu + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +// C includes +#include +#include + +// QT includes +#include +#include + +// KDE includes +#include +#include +#include +#include +#include +#include +#include + +// ark includes +#include "arch.h" +#include "arkwidget.h" +#include "arkutils.h" +#include "filelistview.h" + +// the archive types +#include "tar.h" +#include "zip.h" +#include "lha.h" +#include "compressedfile.h" +#include "zoo.h" +#include "rar.h" +#include "ar.h" +#include "sevenzip.h" +#include "ace.h" + +Arch::ArchColumns::ArchColumns( int col, QRegExp reg, int length, bool opt ) + : colRef( col ), pattern( reg ), maxLength( length ), optional( opt ) +{ +} + +Arch::Arch( ArkWidget *gui, const QString &filename ) + : m_filename( filename ), m_buffer( "" ), m_gui( gui ), + m_bReadOnly( false ), m_bNotifyWhenDeleteFails( true ), + m_header_removed( false ), m_finished( false ), + m_numCols( 0 ), m_dateCol( -1 ), m_fixYear( -1 ), m_fixMonth( -1 ), + m_fixDay( -1 ), m_fixTime( -1 ), m_repairYear( -1 ), m_repairMonth( -1 ), + m_repairTime( -1 ), m_currentProcess( 0 ) +{ + m_archCols.setAutoDelete( true ); // To check: it still leaky here??? +} + +Arch::~Arch() +{ + if ( m_currentProcess ) + m_currentProcess->kill(); +} + +//Check if a compress utility exists +void Arch::verifyCompressUtilityIsAvailable( const QString &utility ) +{ + // see if the utility is in the PATH of the user. + QString cmd = KGlobal::dirs()->findExe( utility ); + m_bArchUtilityIsAvailable = !cmd.isEmpty(); +} + +//Check if a utility can uncompress files +void Arch::verifyUncompressUtilityIsAvailable( const QString &utility ) +{ + // see if the utility is in the PATH of the user. + QString cmd = KGlobal::dirs()->findExe( utility ); + m_bUnarchUtilityIsAvailable = !cmd.isEmpty(); +} + +void Arch::slotOpenExited( KProcess* _kp ) +{ + int exitStatus = 100; // arbitrary bad exit status + + if ( _kp->normalExit() ) + exitStatus = _kp->exitStatus(); + + if ( exitStatus == 1 ) + { + exitStatus = 0; // because 1 means empty archive - not an error. + // Is this a safe assumption? + } + + if ( !exitStatus ) + emit sigOpen( this, true, m_filename, + Arch::Extract | Arch::Delete | Arch::Add | Arch::View ); + else + emit sigOpen( this, false, QString::null, 0 ); + + delete _kp; + _kp = m_currentProcess = 0; +} + +void Arch::slotDeleteExited( KProcess *_kp ) +{ + bool success = ( _kp->normalExit() && ( _kp->exitStatus() == 0 ) ); + + if ( !success ) + { + QApplication::restoreOverrideCursor(); + + QString msg = i18n( "The deletion operation failed." ); + + if ( !getLastShellOutput().isNull() ) + { + QStringList list = QStringList::split( "\n", getLastShellOutput() ); + KMessageBox::errorList( m_gui, msg, list ); + clearShellOutput(); + } + else + { + KMessageBox::error( m_gui, msg ); + } + } + + emit sigDelete( success ); + delete _kp; + _kp = m_currentProcess = 0; +} + +void Arch::slotExtractExited( KProcess *_kp ) +{ + bool success = ( _kp->normalExit() && ( _kp->exitStatus() == 0 ) ); + + if( !success ) + { + if ( passwordRequired() ) + { + QString msg; + if ( !m_password.isEmpty() ) + msg = i18n("The password was incorrect. "); + if (KPasswordDialog::getPassword( m_password, msg+i18n("You must enter a password to extract the file:") ) == KPasswordDialog::Accepted ) + { + delete _kp; + _kp = m_currentProcess = 0; + clearShellOutput(); + unarchFileInternal(); // try to extract the file again with a password + return; + } + m_password = ""; + emit sigExtract( false ); + delete _kp; + _kp = m_currentProcess = 0; + return; + } + else if ( m_password.isEmpty() || _kp->exitStatus() > 1 ) + { + QApplication::restoreOverrideCursor(); + + QString msg = i18n( "The extraction operation failed." ); + + if ( !getLastShellOutput().isNull() ) + { + //getLastShellOutput() is a QString. errorList is expecting QStringLists to show in multiple lines + QStringList list = QStringList::split( "\n", getLastShellOutput() ); + KMessageBox::errorList( m_gui, msg, list ); + clearShellOutput(); + } + else + { + KMessageBox::error( m_gui, msg ); + } + } + } + m_password = ""; + delete _kp; + _kp = m_currentProcess = 0; + emit sigExtract( success ); +} + +void Arch::unarchFile( QStringList *fileList, const QString & destDir, + bool viewFriendly ) +{ + m_fileList = fileList; + m_destDir = destDir; + m_viewFriendly = viewFriendly; + unarchFileInternal(); +} + +void Arch::slotAddExited( KProcess *_kp ) +{ + bool success = ( _kp->normalExit() && ( _kp->exitStatus() == 0 ) ); + + if( !success ) + { + QApplication::restoreOverrideCursor(); + + QString msg = i18n( "The addition operation failed." ); + + if ( !getLastShellOutput().isNull() ) + { + QStringList list = QStringList::split( "\n", getLastShellOutput() ); + KMessageBox::errorList( m_gui, msg, list ); + clearShellOutput(); + } + else + { + KMessageBox::error( m_gui, msg ); + } + } + + emit sigAdd( success ); + delete _kp; + _kp = m_currentProcess = 0; +} + +void Arch::slotReceivedOutput( KProcess*, char* data, int length ) +{ + char c = data[ length ]; + data[ length ] = '\0'; + + appendShellOutputData( data ); + data[ length ] = c; +} + + +void Arch::slotReceivedTOC( KProcess*, char* data, int length ) +{ + char c = data[ length ]; + data[ length ] = '\0'; + + appendShellOutputData( data ); + + int lfChar, startChar = 0; + + while ( !m_finished ) + { + for ( lfChar = startChar; data[ lfChar ] != '\n' && lfChar < length; + lfChar++ ); + + if ( data[ lfChar ] != '\n') + break; // We are done all the complete lines + + data[ lfChar ] = '\0'; + m_buffer.append( data + startChar ); + data[ lfChar ] = '\n'; + startChar = lfChar + 1; + + if ( m_headerString.isEmpty() ) + { + processLine( m_buffer ); + } + else if ( m_buffer.find( m_headerString ) == -1 ) + { + if ( m_header_removed && !m_finished ) + { + if ( !processLine( m_buffer ) ) + { + // Have faith - maybe it wasn't a header? + m_header_removed = false; + m_error = true; + } + } + } + else if ( !m_header_removed ) + { + m_header_removed = true; + } + else + { + m_finished = true; + } + + m_buffer = ""; + } + + if ( !m_finished ) + m_buffer.append( data + startChar); // Append what's left of the buffer + + data[ length ] = c; +} + +bool Arch::processLine( const QCString &line ) +{ + QString columns[ 11 ]; + unsigned int pos = 0; + int strpos, len; + + // Go through our columns, try to pick out data, return silently on failure + for ( QPtrListIterator col( m_archCols ); col.current(); ++col ) + { + ArchColumns *curCol = *col; + + strpos = curCol->pattern.search( line, pos ); + len = curCol->pattern.matchedLength(); + + if ( ( strpos == -1 ) || ( len > curCol->maxLength ) ) + { + if ( curCol->optional ) + continue; // More? + else + { + kdDebug(1601) << "processLine failed to match critical column" << endl; + return false; + } + } + + pos = strpos + len; + + columns[curCol->colRef] = QString::fromLocal8Bit( line.mid(strpos, len) ); + } + + + if ( m_dateCol >= 0 ) + { + QString year = ( m_repairYear >= 0 ) ? + ArkUtils::fixYear( columns[ m_repairYear ].ascii()) + : columns[ m_fixYear ]; + QString month = ( m_repairMonth >= 0 ) ? + QString( "%1" ) + .arg( ArkUtils::getMonth( columns[ m_repairMonth ].ascii() ) ) + : columns[ m_fixMonth ]; + QString timestamp = QString::fromLatin1( "%1-%2-%3 %4" ) + .arg( year ) + .arg( month ) + .arg( columns[ m_fixDay ] ) + .arg( columns[ m_fixTime ] ); + + columns[ m_dateCol ] = timestamp; + } + + QStringList list; + + for ( int i = 0; i < m_numCols; ++i ) + { + list.append( columns[ i ] ); + } + + m_gui->fileList()->addItem( list ); // send the entry to the GUI + + return true; +} + + +Arch *Arch::archFactory( ArchType aType, + ArkWidget *parent, const QString &filename, + const QString &openAsMimeType ) +{ + switch( aType ) + { + case TAR_FORMAT: + return new TarArch( parent, filename, openAsMimeType ); + + case ZIP_FORMAT: + return new ZipArch( parent, filename ); + + case LHA_FORMAT: + return new LhaArch( parent, filename ); + + case COMPRESSED_FORMAT: + return new CompressedFile( parent, filename, openAsMimeType ); + + case ZOO_FORMAT: + return new ZooArch( parent, filename ); + + case RAR_FORMAT: + return new RarArch( parent, filename ); + + case AA_FORMAT: + return new ArArch( parent, filename ); + + case SEVENZIP_FORMAT: + return new SevenZipArch( parent, filename ); + + case ACE_FORMAT: + return new AceArch( parent, filename ); + + case UNKNOWN_FORMAT: + default: + return 0; + } +} +#include "arch.moc" diff --git a/ark/arch.h b/ark/arch.h new file mode 100644 index 0000000..1a38a2c --- /dev/null +++ b/ark/arch.h @@ -0,0 +1,221 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 1997-1999: Rob Palmbos palm9744@kettering.edu + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +/* The following class is the base class for all of the archive types. + * In order for it to work properly with the KProcess, you have to + * connect the ProcessExited signal appropriately before spawning + * the core operations. Then the signal that the process exited can + * be intercepted by the viewer (in ark, ArkWidget) and dealt with + * appropriately. See LhaArch or ZipArch for a good model. Don't use + * TarArch or CompressedFile as models - they're too complicated! + * + * Don't forget to set m_archiver_program and m_unarchiver_program + * and add a call to + * verifyUtilityIsAvailable(m_archiver_program, m_unarchiver_program); + * in the constructor of your class. It's OK to leave out the second argument. + * + * To add a new archive type: + * 1. Create a new header file and a source code module + * 2. Add an entry to the ArchType enum in arch.h. + * 3. Add appropriate types to buildFormatInfo() in archiveformatinfo.cpp + * and archFactory() in arch.cpp + */ + + +#ifndef ARCH_H +#define ARCH_H + +#include +#include // Some very annoying hackery in arkwidgetpart +#include +#include +#include +#include + +class QCString; +class QStringList; +class KProcess; + +class FileListView; +class ArkWidget; + +enum ArchType { UNKNOWN_FORMAT, ZIP_FORMAT, TAR_FORMAT, AA_FORMAT, + LHA_FORMAT, RAR_FORMAT, ZOO_FORMAT, COMPRESSED_FORMAT, + SEVENZIP_FORMAT, ACE_FORMAT }; + +typedef QValueList< QPair< QString, Qt::AlignmentFlags > > ColumnList; + +/** + * Pure virtual base class for archives - provides a framework as well as + * useful common functionality. + */ +class Arch : public QObject +{ + Q_OBJECT + + protected: + /** + * A struct representing column data. This makes it possible to abstract + * archive output, and save writing the same function for every archive + * type. It is also much more robust than sscanf (which was breaking). + */ + struct ArchColumns + { + int colRef; // Which column to load to in processLine + QRegExp pattern; + int maxLength; + bool optional; + + ArchColumns( int col, QRegExp reg, int length = 64, bool opt = false ); + }; + + public: + Arch( ArkWidget *_viewer, const QString & _fileName ); + virtual ~Arch(); + + virtual void open() = 0; + virtual void create() = 0; + virtual void remove( QStringList * ) = 0; + + virtual void addFile( const QStringList & ) = 0; + virtual void addDir( const QString & ) = 0; + + // unarch the files in m_fileList or all files if m_fileList is empty. + // if m_destDir is empty, abort with error. + // m_viewFriendly forces certain options like directory junking required by view/edit + virtual void unarchFileInternal() = 0; + // returns true if a password is required + virtual bool passwordRequired() { return false; } + + void unarchFile( QStringList *, const QString & _destDir, + bool viewFriendly = false ); + + QString fileName() const { return m_filename; } + + enum EditProperties{ Add = 1, Delete = 2, Extract = 4, + View = 8, Integrity = 16 }; + + // is the archive readonly? + bool isReadOnly() { return m_bReadOnly; } + void setReadOnly( bool bVal ) { m_bReadOnly = bVal; } + + bool isError() { return m_error; } + void resetError() { m_error = false; } + + // check to see if the utility exists in the PATH of the user + void verifyUtilityIsAvailable( const QString &, + const QString & = QString::null ); + + void verifyCompressUtilityIsAvailable( const QString &utility ); + + void verifyUncompressUtilityIsAvailable( const QString &utility ); + + bool archUtilityIsAvailable() { return m_bArchUtilityIsAvailable; } + + bool unarchUtilityIsAvailable() { return m_bUnarchUtilityIsAvailable; } + + QString getArchUtility() { return m_archiver_program; } + + QString getUnarchUtility() { return m_unarchiver_program; } + + void appendShellOutputData( const char * data ) { m_lastShellOutput.append( QString::fromLocal8Bit( data ) ); } + void clearShellOutput() { m_lastShellOutput.truncate( 0 ); } + const QString& getLastShellOutput() const { return m_lastShellOutput; } + + static Arch *archFactory( ArchType aType, ArkWidget *parent, + const QString &filename, + const QString &openAsMimeType = QString::null ); + + protected slots: + void slotOpenExited( KProcess* ); + void slotExtractExited( KProcess* ); + void slotDeleteExited( KProcess* ); + void slotAddExited( KProcess* ); + + void slotReceivedOutput( KProcess *, char*, int ); + + virtual bool processLine( const QCString &line ); + virtual void slotReceivedTOC( KProcess *, char *, int ); + + signals: + void sigOpen( Arch * archive, bool success, const QString &filename, int ); + void sigCreate( Arch *, bool, const QString &, int ); + void sigDelete( bool ); + void sigExtract( bool ); + void sigAdd( bool ); + void headers( const ColumnList& columns ); + + protected: // data + QString m_filename; + QString m_lastShellOutput; + QCString m_buffer; + ArkWidget *m_gui; + bool m_bReadOnly; // for readonly archives + bool m_error; + + // lets tar delete unsuccessfully before adding without confusing the user + bool m_bNotifyWhenDeleteFails; + + // set to whether if the compressing utility is in the user's PATH + bool m_bArchUtilityIsAvailable; + + // set to whether if the uncompressing utility is in the user's PATH + bool m_bUnarchUtilityIsAvailable; + + QString m_archiver_program; + QString m_unarchiver_program; + + // Archive parsing information + QCString m_headerString; + bool m_header_removed, m_finished; + QPtrList m_archCols; + int m_numCols, m_dateCol, m_fixYear, m_fixMonth, m_fixDay, m_fixTime; + int m_repairYear, m_repairMonth, m_repairTime; + KProcess *m_currentProcess; + QStringList *m_fileList; + QString m_destDir; + bool m_viewFriendly; + QCString m_password; +}; + +// Columns +// don't forget to change common_texts.cpp if you change something here +#define FILENAME_COLUMN qMakePair( i18n(" Filename "), Qt::AlignLeft ) +#define PERMISSION_COLUMN qMakePair( i18n(" Permissions "), Qt::AlignLeft ) +#define OWNER_GROUP_COLUMN qMakePair( i18n(" Owner/Group "), Qt::AlignLeft ) +#define SIZE_COLUMN qMakePair( i18n(" Size "), Qt::AlignRight ) +#define TIMESTAMP_COLUMN qMakePair( i18n(" Timestamp "), Qt::AlignRight ) +#define LINK_COLUMN qMakePair( i18n(" Link "), Qt::AlignLeft ) +#define PACKED_COLUMN qMakePair( i18n(" Size Now "), Qt::AlignRight ) +#define RATIO_COLUMN qMakePair( i18n(" Ratio "), Qt::AlignRight ) +#define CRC_COLUMN qMakePair( i18n("Cyclic Redundancy Check"," CRC "), Qt::AlignLeft ) +#define METHOD_COLUMN qMakePair( i18n(" Method "), Qt::AlignLeft ) +#define VERSION_COLUMN qMakePair( i18n(" Version "), Qt::AlignLeft ) +#define OWNER_COLUMN qMakePair( i18n(" Owner "), Qt::AlignLeft ) +#define GROUP_COLUMN qMakePair( i18n(" Group "), Qt::AlignLeft ) + +#endif /* ARCH_H */ diff --git a/ark/archiveformatdlg.cpp b/ark/archiveformatdlg.cpp new file mode 100644 index 0000000..be046fb --- /dev/null +++ b/ark/archiveformatdlg.cpp @@ -0,0 +1,71 @@ +/* + ark -- archiver for the KDE project + + Copyright (C) 2003: Georg Robbers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include "archiveformatdlg.h" +#include "archiveformatinfo.h" +#include "arch.h" + +#include + +#include +#include + +ArchiveFormatDlg::ArchiveFormatDlg( QWidget * parent, const QString & defaultType ) + :KDialogBase( parent, "archiveformatdialog", true, + i18n( "Choose Archive Format" ), + KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok), + m_combo( 0 ) +{ + QString defaultDescription = ArchiveFormatInfo::self()->descriptionForMimeType( defaultType ); + QString text; + if ( defaultDescription.isNull() ) + text = i18n( "This file appears to be of type %1,\n" + "which is not a supported archive format.\n" + "In order to proceed, please choose the format\n" + "of the file." ).arg( defaultType ); + else + text = i18n( "You are about to open a file that has a non-standard extension.\n" + "Ark has detected the format: %1\n" + "If this is not correct, please choose " + "the appropriate format." ).arg( defaultDescription ); + + QVBox * page = makeVBoxMainWidget(); + + QLabel * label; + label = new QLabel( text, page ); + + m_combo = new KComboBox( page ); + QStringList list = ArchiveFormatInfo::self()->allDescriptions(); + list.sort(); + m_combo->insertStringList( list ); + m_combo->setCurrentItem( list.findIndex( defaultDescription ) ); +} + +QString ArchiveFormatDlg::mimeType() +{ + if (m_combo && !m_combo->currentText().isEmpty()) + return ArchiveFormatInfo::self()->mimeTypeForDescription( m_combo->currentText() ); + else + return QString(); +} + +#include "archiveformatdlg.moc" + diff --git a/ark/archiveformatdlg.h b/ark/archiveformatdlg.h new file mode 100644 index 0000000..c8a2e46 --- /dev/null +++ b/ark/archiveformatdlg.h @@ -0,0 +1,39 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) 2003: Georg Robbers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +#ifndef ARCHIVEFORMATDLG_H +#define ARCHIVEFORMATDLG_H + +#include +#include + +class ArchiveFormatDlg: public KDialogBase +{ + Q_OBJECT +public: + ArchiveFormatDlg( QWidget * parent, const QString & defaultType ); + QString mimeType(); + +private: + KComboBox * m_combo; +}; +#endif // ARCHIVEFORMATDLG_H + diff --git a/ark/archiveformatinfo.cpp b/ark/archiveformatinfo.cpp new file mode 100644 index 0000000..f2ac14d --- /dev/null +++ b/ark/archiveformatinfo.cpp @@ -0,0 +1,278 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) 2003 Georg Robbers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include "arch.h" +#include "archiveformatinfo.h" +#include "settings.h" + +#include +#include +#include +#include + +#include + +ArchiveFormatInfo * ArchiveFormatInfo::m_pSelf = 0; + +ArchiveFormatInfo::ArchiveFormatInfo() + :m_lastExtensionUnknown( false ) +{ + buildFormatInfos(); +} + +ArchiveFormatInfo * ArchiveFormatInfo::self() +{ + if ( !m_pSelf ) + m_pSelf = new ArchiveFormatInfo(); + return m_pSelf; +} + +void ArchiveFormatInfo::buildFormatInfos() +{ + addFormatInfo( TAR_FORMAT, "application/x-tgz", ".tar.gz" ); + addFormatInfo( TAR_FORMAT, "application/x-tzo", ".tar.lzo" ); + addFormatInfo( TAR_FORMAT, "application/x-tarz", ".tar.z" ); + addFormatInfo( TAR_FORMAT, "application/x-tbz", ".tar.bz2" ); + addFormatInfo( TAR_FORMAT, "application/x-tbz2", ".tar.bz2" ); + // x-tar as the last one to get its comment for all the others, too + addFormatInfo( TAR_FORMAT, "application/x-tar", ".tar" ); + + addFormatInfo( LHA_FORMAT, "application/x-lha", ".lha" ); + + addFormatInfo( ZIP_FORMAT, "application/x-jar", ".jar" ); + addFormatInfo( ZIP_FORMAT, "application/x-zip", ".zip" ); + addFormatInfo( ZIP_FORMAT, "application/x-zip-compressed", ".zip" ); + + addFormatInfo( COMPRESSED_FORMAT, "application/x-gzip", ".gz" ); + addFormatInfo( COMPRESSED_FORMAT, "application/x-bzip", ".bz" ); + addFormatInfo( COMPRESSED_FORMAT, "application/x-bzip2", ".bz2" ); + addFormatInfo( COMPRESSED_FORMAT, "application/x-lzop", ".lzo" ); + addFormatInfo( COMPRESSED_FORMAT, "application/x-compress", ".Z" ); + find( COMPRESSED_FORMAT ).description = i18n( "Compressed File" ); + + addFormatInfo( ZOO_FORMAT, "application/x-zoo", ".zoo" ); + + addFormatInfo( RAR_FORMAT, "application/x-rar", ".rar" ); + addFormatInfo( RAR_FORMAT, "application/x-rar-compressed", ".rar" ); + + addFormatInfo( AA_FORMAT, "application/x-deb", ".deb" ); + addFormatInfo( AA_FORMAT, "application/x-archive",".a" ); + + addFormatInfo( SEVENZIP_FORMAT, "application/x-7z", ".7z" ); + + if ( ArkSettings::aceSupport() ) + addFormatInfo( ACE_FORMAT, "application/x-ace", ".ace" ); +} + +void ArchiveFormatInfo::addFormatInfo( ArchType type, QString mime, QString stdExt ) +{ + FormatInfo & info = find( type ); + + KDesktopFile * desktopFile = new KDesktopFile( mime + ".desktop", true, "mime" ); + if( !desktopFile ) + kdWarning( 1601 ) << "MimeType " << mime << " seems to be missing." << endl; + KMimeType mimeType( desktopFile ); + info.mimeTypes.append( mimeType.name() ); + info.extensions += mimeType.patterns(); + info.defaultExtensions += stdExt; + info.allDescriptions.append( mimeType.comment() ); + info.description = mimeType.comment(); + + delete desktopFile; +} + + +QString ArchiveFormatInfo::filter() +{ + QStringList allExtensions; + QString filter; + InfoList::Iterator it; + for ( it = m_formatInfos.begin(); it != m_formatInfos.end(); ++it ) + { + allExtensions += (*it).extensions; + filter += "\n" + (*it).extensions.join( " " ) + '|' + (*it).description; + } + return allExtensions.join( " " ) + '|' + i18n( "All Valid Archives\n" ) + + "*|" + i18n( "All Files" ) + + filter; +} + +const QStringList ArchiveFormatInfo::supportedMimeTypes( bool includeCompressed ) +{ + QStringList list; + + InfoList::Iterator end = m_formatInfos.end(); + for ( InfoList::Iterator it = m_formatInfos.begin(); it != end; ++it ) + { + if ( includeCompressed || ( *it ).type != COMPRESSED_FORMAT ) + { + list += ( *it ).mimeTypes; + } + } + + return list; +} + +QStringList ArchiveFormatInfo::allDescriptions() +{ + QStringList descriptions; + InfoList::Iterator it; + for ( it = m_formatInfos.begin(); it != m_formatInfos.end(); ++it ) + descriptions += (*it).allDescriptions; + return descriptions; +} + +ArchiveFormatInfo::FormatInfo & ArchiveFormatInfo::find( ArchType type ) +{ + InfoList::Iterator it = m_formatInfos.begin(); + for( ; it != m_formatInfos.end(); ++it ) + if( (*it).type == type ) + return (*it); + + FormatInfo info; + info.type = type; + return ( *m_formatInfos.append( info ) ); +} + +ArchType ArchiveFormatInfo::archTypeByExtension( const QString & archname ) +{ + InfoList::Iterator it = m_formatInfos.begin(); + QStringList::Iterator ext; + for( ; it != m_formatInfos.end(); ++it ) + { + ext = (*it).extensions.begin(); + for( ; ext != (*it).extensions.end(); ++ext ) + if( archname.endsWith( (*ext).remove( '*' ) ) ) + return (*it).type; + } + return UNKNOWN_FORMAT; +} + +ArchType ArchiveFormatInfo::archTypeForMimeType( const QString & mimeType ) +{ + InfoList::Iterator it = m_formatInfos.begin(); + for( ; it != m_formatInfos.end(); ++it ) + { + int index = (*it).mimeTypes.findIndex( mimeType ); + if( index != -1 ) + return (*it).type; + } + return UNKNOWN_FORMAT; +} + +ArchType ArchiveFormatInfo::archTypeForURL( const KURL & url ) +{ + m_lastExtensionUnknown = false; + + if( url.isEmpty() ) + return UNKNOWN_FORMAT; + + if( !QFile::exists( url.path() ) ) + return archTypeByExtension( url.path() ); + + QString mimeType = KMimeType::findByURL( url, 0, true, true )->name(); + kdDebug( 1601 ) << "find by url: " << mimeType << endl; + if( mimeType == KMimeType::defaultMimeType() ) + { + m_lastExtensionUnknown = true; + mimeType = KMimeType::findByFileContent( url.path() )->name(); + } + + ArchType archType = archTypeForMimeType( mimeType ); + if ( archType == UNKNOWN_FORMAT ) + m_lastExtensionUnknown = true; + + return archType; +} + + +QString ArchiveFormatInfo::findMimeType( const KURL & url ) +{ + QString mimeType = KMimeType::findByURL( url )->name(); + if ( mimeType != "application/x-bzip2" && mimeType != "application/x-gzip" ) + return mimeType; + + QIODevice * dev = KFilterDev::deviceForFile( url.path(), mimeType ); + if ( !dev ) + return mimeType; + + char buffer[ 0x200 ]; + + dev->open( IO_ReadOnly ); + Q_LONG n = dev->readBlock( buffer, 0x200 ); + delete dev; + + if ( n == 0x200 && buffer[0] != 0 && !strncmp(buffer + 257, "ustar", 5) ) + { + if (mimeType == "application/x-bzip2") + return "application/x-tbz"; + else + return "application/x-tgz"; + } + + return mimeType; +} + +QString ArchiveFormatInfo::mimeTypeForDescription( const QString & description ) +{ + InfoList::Iterator it = m_formatInfos.begin(); + int index; + for( ; it != m_formatInfos.end(); ++it ) + { + index = (*it).allDescriptions.findIndex( description ); + if ( index != -1 ) + return (* (*it).mimeTypes.at( index ) ); + } + return QString::null; +} + +QString ArchiveFormatInfo::descriptionForMimeType( const QString & mimeType ) +{ + InfoList::Iterator it = m_formatInfos.begin(); + int index; + for( ; it != m_formatInfos.end(); ++it ) + { + index = (*it).mimeTypes.findIndex( mimeType ); + if ( index != -1 ) + return (* (*it).allDescriptions.at( index ) ); + } + return QString::null; +} + +QString ArchiveFormatInfo::defaultExtension( const QString & mimeType ) +{ + InfoList::Iterator it = m_formatInfos.begin(); + int index; + for( ; it != m_formatInfos.end(); ++it ) + { + index = (*it).mimeTypes.findIndex( mimeType ); + if ( index != -1 ) + return (* (*it).defaultExtensions.at( index ) ); + } + return QString::null; +} + +bool ArchiveFormatInfo::wasUnknownExtension() +{ + return m_lastExtensionUnknown; +} + diff --git a/ark/archiveformatinfo.h b/ark/archiveformatinfo.h new file mode 100644 index 0000000..5682a11 --- /dev/null +++ b/ark/archiveformatinfo.h @@ -0,0 +1,73 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) 2003 Georg Robbers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef ARCHIVEFORMATINFO_H +#define ARCHIVEFORMATINFO_H + +#include "arch.h" +#include + +class ArchiveFormatInfo +{ +private: + ArchiveFormatInfo(); + +public: + static ArchiveFormatInfo * self(); + QString filter(); + const QStringList supportedMimeTypes( bool includeCompressed = true ); + QStringList allDescriptions(); + ArchType archTypeForMimeType( const QString & mimeType ); + ArchType archTypeByExtension( const QString & archname ); + ArchType archTypeForURL( const KURL & url ); + QString mimeTypeForDescription( const QString & description ); + QString findMimeType( const KURL & url ); + QString descriptionForMimeType( const QString & mimeType ); + QString defaultExtension( const QString & mimeType ); + bool wasUnknownExtension(); + +private: + void buildFormatInfos(); + void addFormatInfo( ArchType type, QString mime, QString stdExt ); + + struct FormatInfo + { + QStringList extensions; + QStringList mimeTypes; + QStringList allDescriptions; + QStringList defaultExtensions; + QString description; + enum ArchType type; + }; + + FormatInfo & find ( ArchType type ); + + typedef QValueList InfoList; + InfoList m_formatInfos; + + bool m_lastExtensionUnknown; + + static ArchiveFormatInfo * m_pSelf; +}; + +#endif // ARCHIVEFORMATINFO_H + diff --git a/ark/ark.desktop b/ark/ark.desktop new file mode 100644 index 0000000..d3615fe --- /dev/null +++ b/ark/ark.desktop @@ -0,0 +1,87 @@ +[Desktop Entry] +MimeType=application/x-gzip;application/x-lha;application/x-tar;application/x-tgz;application/x-tbz;application/x-tbz2;application/x-zip;application/zip;application/x-bzip;application/x-tzo;application/x-lzop;application/x-rar;application/x-zoo;application/x-tarz;application/x-archive;application/x-bzip2;application/x-jar;application/x-deb;application/x-ace;application/x-7z;application/x-arc;application/x-arj;application/x-compress;application/x-cpio;application/x-pak;application/x-zip-compressed +GenericName=Archiving Tool +GenericName[af]=Argiveer Program +GenericName[ar]=أداة أرشفة +GenericName[bg]=Работа с архиви +GenericName[br]=Ostilh merañ an Dielloù +GenericName[bs]=Alat za arhiviranje +GenericName[ca]=Eina d'arxivament +GenericName[cs]=Archivační nástroj +GenericName[cy]=Erfyn Archifo +GenericName[da]=Arkiveringsværktøj +GenericName[de]=Archivprogramm +GenericName[el]=Εργαλείο αρχειοθέτησης +GenericName[eo]=Arĥivilo +GenericName[es]=Archivador +GenericName[et]=Arhiivide haldamise rakendus +GenericName[eu]=Artxibaketa Tresna +GenericName[fa]=ابزار بایگانی +GenericName[fi]=Pakettienhallintatyökalu +GenericName[fr]=Outil de manipulation d'archives +GenericName[ga]=Uirlis Chartlannaithe +GenericName[he]=כלי לניהול ארכיונים +GenericName[hi]=अभिलेख औज़ार +GenericName[hr]=Uslužni program za arhiviranje +GenericName[hu]=Fájltömörítő +GenericName[is]=Vinna með safnskrár +GenericName[it]=Strumento di archiviazione +GenericName[ja]=アーカイバツール +GenericName[ka]=არქივებთან სამუშაო უტილიტა +GenericName[kk]=Архивтеу құралы +GenericName[km]=ឧបករណ៍​ប័ណ្ណសារ +GenericName[lt]=Archyvavimo priemonė +GenericName[lv]=Arhivēšanas Rīks +GenericName[mk]=Алатка за архивирање +GenericName[ms]=Alatan Pengarkiban +GenericName[mt]=Għodda tal-arkivji +GenericName[nb]=Arkiveringsverktøy +GenericName[nds]=Archivwarktüüch +GenericName[ne]=उपकरण सङ्ग्रह गर्दै +GenericName[nl]=Archiefgereedschap +GenericName[nn]=Arkiveringsverktøy +GenericName[pa]=ਪੁਰਾਲੇਖ ਸੰਦ +GenericName[pl]=Narzędzie do archiwizacji +GenericName[pt]=Ferramenta de Armazenamento +GenericName[pt_BR]=Ferramenta de Arquivamento +GenericName[ro]=Utilitar de arhivare +GenericName[ru]=Архиватор +GenericName[sk]=Archivačný nástroj +GenericName[sl]=Orodje za ravnanje z arhivi +GenericName[sr]=Алат за архивирање +GenericName[sr@Latn]=Alat za arhiviranje +GenericName[sv]=Arkiveringsverktyg +GenericName[ta]=காப்பக கருவி +GenericName[tg]=Асбобҳои Бойгонӣ +GenericName[th]=เครื่องมือจัดการแฟ้มบีบอัด +GenericName[tr]=Arşivleme Aracı +GenericName[uk]=Засіб роботи з архівами +GenericName[uz]=Arxivlash vositasi +GenericName[uz@cyrillic]=Архивлаш воситаси +GenericName[ven]=Tshishumiswa tsha fhethu huno vhulungelwa hone zwithu zwa kale +GenericName[vi]=Công cụ nén +GenericName[wa]=Usteye d' årtchivaedje +GenericName[xh]=Isixhobo Sokuphatha i Archive +GenericName[zh_CN]=文件压缩归档工具 +GenericName[zh_TW]=壓縮工具 +GenericName[zu]=Ithuluzi Lomqulu +Name=Ark +Name[ar]=أرك +Name[eo]=Arĥivilo +Name[hi]=आर्क +Name[ne]=आर्क +Name[nso]=Areka +Name[pa]=ਆਕ +Name[ta]=ஆர்க் +Name[th]=อาร์ค +Exec=ark -caption "%c" %i %m %U +Icon=ark +Path= +DocPath=ark/index.html +Type=Application +Terminal=false +SwallowExec= +SwallowTitle= +X-DCOP-ServiceType=Unique +X-KDE-HasTempFileOption=true +Categories=Qt;KDE;Utility;X-KDE-Utilities-File; diff --git a/ark/ark.kcfg b/ark/ark.kcfg new file mode 100644 index 0000000..1c134a4 --- /dev/null +++ b/ark/ark.kcfg @@ -0,0 +1,90 @@ + + + + + + + + + + If this option is enabled and you add filenames that already exist in an archive, only replace the old files if the added files are newer than them + false + + + + Overwrite any files that have matching names on disk with the one from the archive + false + + + + + + Save the user, group, and permission settings on files. Use with care, as this may result in files being extracted that do not belong to any valid user on your computer + false + + + + + + Force names of files in Zip archives to the DOS 8.3 format + false + + + + false + + + + Extract all the files into the extraction folder, ignoring any folder structure in the archive. + false + + + + + + true + + + + true + + + + false + + + + false + + + + + + true + + + + Enables integration with Konqueror's context menus, letting you easily archive or unarchive files. This option will only work if you have the kdeaddons package installed. + true + + + + true + + + + tar + + + + false + + + + false + + + diff --git a/ark/ark_part.cpp b/ark/ark_part.cpp new file mode 100644 index 0000000..a574217 --- /dev/null +++ b/ark/ark_part.cpp @@ -0,0 +1,533 @@ +/* + Copyright (C) + + 2001: Macadamian Technologies Inc (author: Jian Huang, jian@macadamian.com) + 2003: Georg Robbers + 2005: Henrique Pinto + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include "ark_part.h" +#include "arkfactory.h" +#include "arkwidget.h" +#include "settings.h" +#include "filelistview.h" +#include "searchbar.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +KAboutData *ArkPart::createAboutData() +{ + KAboutData *about = new KAboutData("ark", I18N_NOOP("ark"), + "1.0", + I18N_NOOP("Ark KParts Component"), + KAboutData::License_GPL, + I18N_NOOP( "(c) 1997-2003, The Various Ark Developers" )); + about->addAuthor("Robert Palmbos",0, "palm9744@kettering.edu"); + about->addAuthor("Francois-Xavier Duranceau",0, "duranceau@kde.org"); + about->addAuthor("Corel Corporation (author: Emily Ezust)",0, + "emilye@corel.com"); + about->addAuthor("Corel Corporation (author: Michael Jarrett)", 0, + "michaelj@corel.com"); + about->addAuthor("Jian Huang"); + about->addAuthor( "Roberto Teixeira", 0, "maragato@kde.org" ); + + return about; +} + + + +ArkPart::ArkPart( QWidget *parentWidget, const char * /*widgetName*/, QObject *parent, + const char *name, const QStringList &, bool readWrite ) + : KParts::ReadWritePart(parent, name) +{ + kdDebug(1601)<<"ArkPart::ArkPart"<fileList(), SLOT(selectAll()), actionCollection(), "select_all"); + + deselectAllAction = new KAction(i18n("&Unselect All"), 0, awidget->fileList(), SLOT(unselectAll()), actionCollection(), "deselect_all"); + + invertSelectionAction = new KAction(i18n("&Invert Selection"), 0, awidget->fileList(), SLOT(invertSelection()), actionCollection(), "invert_selection"); + + saveAsAction = KStdAction::saveAs(this, SLOT(file_save_as()), actionCollection()); + + //KStdAction::preferences(awidget, SLOT(showSettings()), actionCollection()); + + ( void ) new KAction( i18n( "Configure &Ark..." ), "configure" , 0, awidget, + SLOT( showSettings() ), actionCollection(), "options_configure_ark" ); + + + showSearchBar = new KToggleAction( i18n( "Show Search Bar" ), KShortcut(), actionCollection(), "options_show_search_bar" ); + showSearchBar->setCheckedState(i18n("Hide Search Bar")); + + showSearchBar->setChecked( ArkSettings::showSearchBar() ); + + connect( showSearchBar, SIGNAL( toggled( bool ) ), awidget, SLOT( slotShowSearchBarToggled( bool ) ) ); + + initialEnables(); +} + + +void ArkPart::fixEnables() +{ + bool bHaveFiles = ( awidget->getNumFilesInArchive() > 0 ); + bool bReadOnly = false; + bool bAddDirSupported = true; + QString extension; + if ( awidget->archiveType() == ZOO_FORMAT || awidget->archiveType() == AA_FORMAT + || awidget->archiveType() == COMPRESSED_FORMAT) + bAddDirSupported = false; + + if (awidget->archive()) + bReadOnly = awidget->archive()->isReadOnly(); + + saveAsAction->setEnabled(bHaveFiles); + selectAllAction->setEnabled(bHaveFiles); + deselectAllAction->setEnabled(bHaveFiles); + invertSelectionAction->setEnabled(bHaveFiles); + + deleteAction->setEnabled(bHaveFiles && awidget->numSelectedFiles() > 0 + && awidget->archive() && !bReadOnly); + addFileAction->setEnabled(awidget->isArchiveOpen() && + !bReadOnly); + addDirAction->setEnabled(awidget->isArchiveOpen() && + !bReadOnly && bAddDirSupported); + extractAction->setEnabled(bHaveFiles); + awidget->searchBar()->setEnabled(bHaveFiles); + + bool b = ( bHaveFiles + && (awidget->numSelectedFiles() == 1) + && (awidget->fileList()->currentItem()->childCount() == 0) + ); + viewAction->setEnabled( b ); + openWithAction->setEnabled( b ); + editAction->setEnabled( b && !bReadOnly ); // You can't edit files in read-only archives + emit fixActionState( bHaveFiles ); +} + +void ArkPart::initialEnables() +{ + saveAsAction->setEnabled( false ); + selectAllAction->setEnabled(false); + deselectAllAction->setEnabled(false); + invertSelectionAction->setEnabled(false); + + viewAction->setEnabled(false); + + deleteAction->setEnabled(false); + extractAction->setEnabled(false); + addFileAction->setEnabled(false); + addDirAction->setEnabled(false); + openWithAction->setEnabled(false); + editAction->setEnabled(false); + + awidget->searchBar()->setEnabled(false); +} + +void ArkPart::disableActions() +{ + saveAsAction->setEnabled(false); + selectAllAction->setEnabled(false); + deselectAllAction->setEnabled(false); + invertSelectionAction->setEnabled(false); + + viewAction->setEnabled(false); + deleteAction->setEnabled(false); + extractAction->setEnabled(false); + addFileAction->setEnabled(false); + addDirAction->setEnabled(false); + openWithAction->setEnabled(false); + editAction->setEnabled(false); + awidget->searchBar()->setEnabled(false); +} + +bool ArkPart::openURL( const KURL & url ) +{ + awidget->setRealURL( url ); + return KParts::ReadWritePart::openURL( KIO::NetAccess::mostLocalURL( url, awidget ) ); +} + +bool ArkPart::openFile() +{ + KURL url; + url.setPath( m_file ); + if( !QFile::exists( m_file ) ) + { + emit setWindowCaption( QString::null ); + emit removeRecentURL( awidget->realURL() ); + return false; + } + emit addRecentURL( awidget->realURL() ); + awidget->setModified( false ); + awidget->file_open( url ); + return true; +} + +void ArkPart::file_save_as() +{ + KURL u = awidget->getSaveAsFileName(); + if ( u.isEmpty() ) // user canceled + return; + + if ( !awidget->allowedArchiveName( u ) ) + awidget->convertTo( u ); + else if ( awidget->file_save_as( u ) ) + m_ext->slotOpenURLRequested( u ); + else + kdWarning( 1601 ) << "Save As failed." << endl; +} + +bool ArkPart::saveFile() +{ + return true; +} + +bool ArkPart::closeArchive() +{ + awidget->file_close(); + awidget->setModified( false ); + return ReadWritePart::closeURL(); +} + +bool ArkPart::closeURL() +{ + if ( !isReadWrite() || !awidget->isModified() || awidget->realURL().isLocalFile() ) + return closeArchive(); + + QString docName = awidget->realURL().prettyURL(); + + int res = KMessageBox::warningYesNoCancel( widget(), + i18n( "The archive \"%1\" has been modified.\n" + "Do you want to save it?" ).arg( docName ), + i18n( "Save Archive?" ), KStdGuiItem::save(), KStdGuiItem::discard() ); + + switch ( res ) + { + case KMessageBox::Yes : + return awidget->file_save_as( awidget->realURL() ) && closeArchive(); + + case KMessageBox::No : + return closeArchive(); + + default : // case KMessageBox::Cancel + return false; + } +} + +void ArkPart::slotFilePopup( const QPoint &pPoint ) +{ + if ( factory() ) + static_cast(factory()->container("file_popup", this))->popup(pPoint); +} + +void ArkPart::transferStarted( KIO::Job *job ) +{ + m_job = job; + + m_bar->slotSetBusy( i18n( "Downloading %1..." ).arg( m_url.prettyURL() ), + (job != 0), (job != 0) ); + + if ( job ) + { + disableActions(); + connect( job, SIGNAL( percent(KIO::Job*, unsigned long) ), + SLOT( progressInformation(KIO::Job*, unsigned long) ) ); + connect( m_bar->cancelButton(), SIGNAL( clicked() ), + SLOT( cancelTransfer() ) ); + } +} + +void ArkPart::transferCompleted() +{ + if ( m_job ) + { + disconnect( m_job, SIGNAL( percent(KIO::Job*, unsigned long) ), + this, SLOT( progressInformation(KIO::Job*, unsigned long) ) ); + m_job = 0; + } + + m_bar->slotSetReady(); +} + +void ArkPart::transferCanceled( const QString& errMsg ) +{ + m_job = 0; + if ( !errMsg.isEmpty() ) + { + KMessageBox::error( awidget, errMsg ); + } + initialEnables(); + m_bar->slotSetReady(); +} + +void ArkPart::progressInformation( KIO::Job *, unsigned long progress ) +{ + m_bar->setProgress( progress ); +} + +void ArkPart::cancelTransfer() +{ + disconnect( m_bar->cancelButton(), SIGNAL( clicked() ), + this, SLOT( cancelTransfer() ) ); + if ( m_job ) + { + m_job->kill( false ); + transferCanceled( QString() ); + } +} + +ArkBrowserExtension::ArkBrowserExtension( KParts::ReadOnlyPart * parent, const char * name ) + : KParts::BrowserExtension( parent, name ) +{ +} + +void ArkBrowserExtension::slotOpenURLRequested( const KURL & url ) +{ + emit openURLRequest( url, KParts::URLArgs() ); +} + +ArkStatusBarExtension::ArkStatusBarExtension( KParts::ReadWritePart * parent ) + : KParts::StatusBarExtension( parent ), + m_bBusy( false ), + m_pStatusLabelSelect( 0 ), + m_pStatusLabelTotal( 0 ), + m_pBusyText( 0 ), + m_cancelButton( 0 ), + m_pProgressBar( 0 ), + m_pTimer( 0 ) +{ +} + +ArkStatusBarExtension::~ArkStatusBarExtension() +{ +} + +void ArkStatusBarExtension::setupStatusBar() +{ + if ( m_pTimer // setup already done + || !statusBar() ) + { + return; + } + + m_pTimer = new QTimer( this ); + connect( m_pTimer, SIGNAL( timeout() ), this, SLOT( slotProgress() ) ); + + m_pStatusLabelTotal = new KSqueezedTextLabel( statusBar(), "StatusLabelTotal" ); + m_pStatusLabelTotal->setFrameStyle( QFrame::NoFrame ); + m_pStatusLabelTotal->setAlignment( AlignRight ); + m_pStatusLabelTotal->setText( i18n( "Total: 0 files" ) ); + + m_pStatusLabelSelect = new QLabel( statusBar(), "StatusLabelSelect" ); + m_pStatusLabelSelect->setFrameStyle( QFrame::NoFrame ); + m_pStatusLabelSelect->setAlignment( AlignLeft ); + m_pStatusLabelSelect->setText(i18n( "0 files selected" ) ); + + m_cancelButton = new KPushButton( SmallIcon( "cancel" ), QString(), statusBar(), "CancelButton" ); + + addStatusBarItem( m_pStatusLabelSelect, 3000, false ); + addStatusBarItem( m_pStatusLabelTotal, 3000, false ); +} + +void ArkStatusBarExtension::slotSetStatusBarText( const QString & text ) +{ + if ( !statusBar() ) + return; + + setupStatusBar(); + m_pStatusLabelTotal->setText( text ); +} + +void ArkStatusBarExtension::slotSetStatusBarSelectedFiles( const QString & text ) +{ + + if ( !statusBar() ) + return; + + setupStatusBar(); + m_pStatusLabelSelect->setText( text ); +} + +void ArkStatusBarExtension::slotSetBusy( const QString & text, bool showCancelButton, bool detailedProgress ) +{ + if ( m_bBusy || !statusBar() ) + return; + + setupStatusBar(); + if ( !m_pBusyText ) + { + m_pBusyText = new QLabel( statusBar() ); + + m_pBusyText->setAlignment( AlignLeft ); + m_pBusyText->setFrameStyle( QFrame::Panel | QFrame::Raised ); + } + + if ( !m_pProgressBar ) + { + m_pProgressBar = new KProgress( statusBar() ); + m_pProgressBar->setFixedHeight( m_pBusyText->fontMetrics().height() ); + } + + if ( !detailedProgress ) + { + m_pProgressBar->setTotalSteps( 0 ); + m_pProgressBar->setPercentageVisible( false ); + } + else + { + m_pProgressBar->setTotalSteps(100); + m_pProgressBar->setPercentageVisible( true ); + } + + m_pBusyText->setText( text ); + + removeStatusBarItem( m_pStatusLabelSelect ); + removeStatusBarItem( m_pStatusLabelTotal ); + + addStatusBarItem( m_pBusyText, 5, true ); + addStatusBarItem( m_pProgressBar, 1, true ); + if ( showCancelButton ) + { + addStatusBarItem( m_cancelButton, 0, true ); + } + + if ( !detailedProgress ) + { + m_pTimer->start( 200, false ); + } + m_bBusy = true; +} + +void ArkStatusBarExtension::slotSetReady() +{ + if ( !m_bBusy || !statusBar() ) + return; + + setupStatusBar(); + m_pTimer->stop(); + m_pProgressBar->setProgress( 0 ); + + removeStatusBarItem( m_pBusyText ); + removeStatusBarItem( m_pProgressBar ); + removeStatusBarItem( m_cancelButton ); + + addStatusBarItem( m_pStatusLabelSelect, 3000, false ); + addStatusBarItem( m_pStatusLabelTotal, 3000, false ); + + m_bBusy = false; +} + +void ArkStatusBarExtension::slotProgress() +{ + if ( !statusBar() ) + return; + + setupStatusBar(); + m_pProgressBar->setProgress( m_pProgressBar->progress() + 4 ); +} + +void ArkStatusBarExtension::setProgress( unsigned long progress ) +{ + if ( m_pProgressBar && ( m_pProgressBar->totalSteps() != 0 ) ) + { + m_pProgressBar->setProgress( progress ); + } +} + +#include "ark_part.moc" diff --git a/ark/ark_part.desktop b/ark/ark_part.desktop new file mode 100644 index 0000000..e167f26 --- /dev/null +++ b/ark/ark_part.desktop @@ -0,0 +1,135 @@ +[Desktop Entry] +MimeType=application/x-gzip;application/x-lha;application/x-tar;application/x-tgz;application/x-tbz;application/x-tbz2;application/x-zip;application/x-bzip;application/x-tzo;application/x-lzop;application/x-rar;application/x-zoo;application/x-tarz;application/x-archive;application/x-bzip2;application/x-jar;application/x-deb;application/x-ace;application/x-7z;application/x-arc;application/x-arj;application/x-compress;application/x-cpio;application/x-pak +Comment=Archive Handling Tool +Comment[af]=Argief Handtering Program +Comment[ar]=أداة التعامل مع الملفات المضغوطة +Comment[az]=Arxiv İşləmə Vasitəsi +Comment[bg]=Работа с архиви +Comment[br]=Ostilh merañ an dielloù +Comment[bs]=Uslužni program za arhiviranje +Comment[ca]=Eina per a treballar amb arxius +Comment[cs]=Program pro práci s archívy +Comment[cy]=Erfyn Triniaeth Archif +Comment[da]=Arkivbehandlingsværktøj +Comment[de]=Archiv-Verwaltung +Comment[el]=Εργαλείο χειρισμού αρχειοθηκών +Comment[eo]=Administrilo por arĥivoj +Comment[es]=Herramienta para archivos comprimidos +Comment[et]=Arhiivide haldamise rakendus +Comment[eu]=Artxiboak Kudeatzeko tresna +Comment[fa]=ابزار گرداندن بایگانی +Comment[fi]=Pakettienhallintatyökalu +Comment[fr]=Outil de manipulation d'archives +Comment[ga]=Uirlis Láimhseála Cartlainne +Comment[gl]=Ferramenta de Manexo de Arquivos +Comment[he]=כלי לניהול ארכיונים +Comment[hi]=अभिलेख संभाल औज़ार +Comment[hr]=Uslužni program za arhiviranje +Comment[hu]=Tömörítóprogram +Comment[id]=Program bantu menangani archive +Comment[is]=Vinna með safnskrár +Comment[it]=Gestione degli archivi +Comment[ja]=アーカイバツール +Comment[ka]=არქივებთან სამუშაო ხელსაწყო +Comment[kk]=Архивпен айналысу құралы +Comment[km]=ឧបករណ៍​គ្រប់គ្រង​ប័ណ្ណសារ +Comment[lt]=Archyvo valdymo priemonė +Comment[lv]=Arhīvu Apstrādes Rīks +Comment[mk]=Алатка за справување со архивирани датотеки +Comment[ms]=Alatan Pengendalian Arkib +Comment[mt]=Għodda biex tuża l-arkivji +Comment[nb]=Arkivbehandlingsverktøy +Comment[nds]=En Warktüüch för de Archivpleeg +Comment[ne]=ह्यान्डलिङ उपकरण सङ्ग्रह गर्नुहोस् +Comment[nl]=Hulpprogramma voor het beheer van archieven +Comment[nn]=Verktøy for arkivhandsaming +Comment[pa]=ਪੁਰਾਲੇਖ ਬਣਾਉਣ ਸੰਦ +Comment[pl]=Program obsługi archiwów +Comment[pt]=Programa de gestão de arquivos +Comment[pt_BR]=Gerenciador de arquivos empacotados +Comment[ro]=Utilitar de manipulare arhive +Comment[ru]=Программа работы с архивами +Comment[sk]=Program na prácu s archívmi +Comment[sl]=Orodje za ravnanje z arhivi +Comment[sr]=Алат за руковање архивама +Comment[sr@Latn]=Alat za rukovanje arhivama +Comment[sv]=Verktyg för att hantera filarkiv +Comment[ta]= காப்பகத்தை கையாளும் கருவி +Comment[tg]=Асбобҳои Дасткории Бойгонӣ +Comment[th]=เครื่องมือจัดการแฟ้มบีบอัดทั้งหลาย +Comment[tr]=Arşiv İşleme Aracı +Comment[uk]=Засіб роботи з архівами +Comment[uz]=Arxiv uchun vosita +Comment[uz@cyrillic]=Архив учун восита +Comment[ven]=Tshishumiswa tshau fara tsha fhethu huno vhulungwa zwa kale +Comment[vi]=Công cụ xử lí các file nén +Comment[wa]=Usteye po-z apougnî les årtchives +Comment[xh]=Isixhobo sokuphatha i Archive +Comment[zh_CN]=文件压缩归档处理工具 +Comment[zh_TW]=壓縮檔案處理工具 +Comment[zu]=Ithuluzi Lokuphatha Umqulu +Name=Archiver +Name[af]=Argifeerder +Name[ar]=الضاغط +Name[az]=Arxivci +Name[br]=Dieller +Name[bs]=Arhiver +Name[ca]=Arxivador +Name[cs]=Archivátor +Name[cy]=Archifydd +Name[da]=Arkivbehandler +Name[de]=Archivprogramm +Name[el]=Πρόγραμμα αρχειοθέτησης +Name[eo]=Arĥivilo +Name[es]=Archivador +Name[et]=Arhiveerija +Name[eu]=Artxibalaria +Name[fa]=بایگانی‌کننده +Name[fr]=Archiveur +Name[gl]=Arquivador +Name[he]=מנהל הארכיונים +Name[hi]=अभिलेखक +Name[hr]=Arhiver +Name[hu]=Ark fájltömörítő +Name[is]=Skráasafnari +Name[it]=Utilità di archiviazione +Name[ja]=アーカイバ +Name[ka]=არქივარიუსი +Name[kk]=Архивтегіш +Name[km]=កម្មវិធី​ប័ណ្ណសារ +Name[lt]=Archyvatorius +Name[lv]=Arhivators +Name[mk]=Архивер +Name[ms]=Pengarkib +Name[nb]=Arkivbehandler +Name[ne]=पुरालेखक +Name[nl]=Archiefgereedschap +Name[nn]=Arkiverar +Name[pa]=ਆਕੀਵਰ +Name[pl]=Ark +Name[pt]=Ark +Name[pt_BR]=Arquivador +Name[ro]=Arhivator +Name[ru]=Архиватор +Name[sk]=Archivátor +Name[sl]=Arhivar +Name[sr]=Архивер +Name[sr@Latn]=Arhiver +Name[sv]=Arkiverare +Name[ta]= காப்பகம் +Name[tg]=Бойгонигар +Name[th]=อาร์ไคว์ฟเออร์ +Name[tr]=Arşivci +Name[uk]=Архіватор +Name[uz]=Arxivlagich +Name[uz@cyrillic]=Архивлагич +Name[ven]=Muvhulungi nwa zwithu zwa kale +Name[vi]=Luư trữ +Name[wa]=Årtchiveu +Name[xh]=Umenzi woshicilelo lukawonke-wonke noxwebhu lweMbali +Name[zh_CN]=压缩存档工具 +Name[zu]=Umqulu +Icon=ark +Type=Service +ServiceTypes=KParts/ReadOnlyPart +X-KDE-Library=libarkpart diff --git a/ark/ark_part.h b/ark/ark_part.h new file mode 100644 index 0000000..b5b7f6f --- /dev/null +++ b/ark/ark_part.h @@ -0,0 +1,148 @@ +/* + Copyright (C) + + 2001: Macadamian Technologies Inc (author: Jian Huang, jian@macadamian.com) + 2005: Henrique Pinto + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef ARK_PART_H +#define ARK_PART_H + +#include +#include +#include +#include +#include +#include + +#include + +class KAboutData; +class KPushButton; + +class ArkWidget; + +namespace KIO +{ + class Job; +} + + +class ArkBrowserExtension: public KParts::BrowserExtension +{ + Q_OBJECT +public: + ArkBrowserExtension( KParts::ReadOnlyPart * parent, const char * name = 0L ); +public slots: + void slotOpenURLRequested( const KURL & url ); +}; + +class ArkStatusBarExtension: public KParts::StatusBarExtension +{ + Q_OBJECT +public: + ArkStatusBarExtension( KParts::ReadWritePart * parent ); + ~ArkStatusBarExtension(); + + void setProgress( unsigned long progress ); + KPushButton* cancelButton() const { return m_cancelButton; } + +public slots: + void slotSetStatusBarSelectedFiles( const QString & text ); + void slotSetStatusBarText( const QString & text ); + void slotSetBusy( const QString & text, bool showCancelButton = false, bool detailedProgress = false ); + void slotSetReady(); + void slotProgress(); + +protected: + void setupStatusBar(); + +private: + bool m_bBusy; + QLabel *m_pStatusLabelSelect; // How many files are selected + QLabel *m_pStatusLabelTotal; // How many files in archive + QLabel *m_pBusyText; + KPushButton *m_cancelButton; // Cancel an operation + KProgress *m_pProgressBar; + QTimer *m_pTimer; +}; + + +class ArkPart: public KParts::ReadWritePart +{ + Q_OBJECT +public: + ArkPart( QWidget *parentWidget, const char *widgetName, QObject *parent, + const char *name, const QStringList &, bool readWrite ); + virtual ~ArkPart(); + + static KAboutData* createAboutData(); + +public slots: + void fixEnables();//rename to slotFixEnables()... + void disableActions(); + void slotFilePopup( const QPoint & pPoint ); + void file_save_as(); + bool saveFile(); + bool openURL( const KURL & url ); + bool closeURL(); + void transferStarted( KIO::Job * ); + void transferCompleted(); + void transferCanceled( const QString& errMsg ); + void progressInformation( KIO::Job *, unsigned long ); + void cancelTransfer(); + +signals: + void fixActionState( const bool & bHaveFiles ); + void removeRecentURL( const KURL & url ); + void addRecentURL( const KURL & url ); + +protected: + virtual bool openFile(); //Opening an archive file + bool closeArchive(); + void setupActions(); + void initialEnables(); + void init(); + +private: + ArkWidget *awidget; + ArkBrowserExtension *m_ext; + ArkStatusBarExtension *m_bar; + + KAction *saveAsAction; + KAction *addFileAction; + KAction *addDirAction; + KAction *extractAction; + KAction *deleteAction; + KAction *selectAllAction; + KAction *viewAction; + KAction *helpAction; + KAction *openWithAction; + KAction *deselectAllAction; + KAction *invertSelectionAction; + KAction *editAction; + + // the following have different enable rules from the above KActions + KAction *popupViewAction; + KAction *popupOpenWithAction; + KToggleAction *showSearchBar; + + KIO::Job *m_job; +}; + +#endif // ARK_PART_H diff --git a/ark/ark_part.rc b/ark/ark_part.rc new file mode 100644 index 0000000..ff0a894 --- /dev/null +++ b/ark/ark_part.rc @@ -0,0 +1,57 @@ + + + + + + + &File + + + &Edit + + + + + + &Action + + + + + + + + + + &Settings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ark/ark_part_readonly.rc b/ark/ark_part_readonly.rc new file mode 100644 index 0000000..c124aae --- /dev/null +++ b/ark/ark_part_readonly.rc @@ -0,0 +1,42 @@ + + + + + + + &File + + + &Edit + + + + + + &Action + + + + + + &Settings + + + + + + + + + + + + + + + + + + + + diff --git a/ark/arkapp.cpp b/ark/arkapp.cpp new file mode 100644 index 0000000..c117d0b --- /dev/null +++ b/ark/arkapp.cpp @@ -0,0 +1,294 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2002-2003: Helio Chissini de Castro + 2003: Georg Robbers + 1999-2000: Corel Corporation (author: Emily Ezust emilye@corel.com) + 1999: Francois-Xavier Duranceau duranceau@kde.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include +#include +#include +#include +#include + + +#include "arkapp.h" + +ArkApplication *ArkApplication::mInstance = NULL; + +// a helper function to follow a symlink and obtain the real filename +// Used in the ArkApplication functions that use the archive filename +// to make sure an archive isn't opened twice in different windows +// Now, readlink only gives one level so this function recurses. + +static QString resolveFilename(const QString & _arkname) +{ + char *buff; + int nread; + int iter = 1; + + while ( true ) + { + buff = new char[BUFSIZ*iter]; + nread = readlink( QFile::encodeName(_arkname), buff, BUFSIZ); + if (-1 == nread) + { + if ( EINVAL == errno ) // not a symbolic link. Stopping condition. + { + delete [] buff; + return _arkname; + } + else if ( ENAMETOOLONG == errno ) + { + kdDebug(1601) << "resolveFilename: have to reallocate - name too long!" << endl; + iter++; + delete [] buff; + continue; + } + else + { + delete [] buff; + // the other errors will be taken care of already in simply + // // opening the archive (i.e., the user will be notified) + return ""; + } + } + else + { + buff[nread] = '\0'; // readlink doesn't null terminate + QString name = QFile::decodeName( buff ); + delete [] buff; + + // watch out for relative pathnames + if (name.at(0) != '/') + { + // copy the path from _arkname + int index = _arkname.findRev('/'); + name = _arkname.left(index + 1) + name; + } + kdDebug(1601) << "Now resolve " << name << endl; + + return resolveFilename( name ); + } + } +} + + +ArkApplication * ArkApplication::getInstance() +{ + if (mInstance == NULL) + { + mInstance = new ArkApplication(); + } + return mInstance; +} + +ArkApplication::ArkApplication() + : KUniqueApplication(), m_windowCount(0) +{ + m_mainwidget = new QWidget; + setMainWidget(m_mainwidget); +} + +int +ArkApplication::newInstance() +{ + + // If we are restored by session management, we don't need to open + // another window on startup. + if (restoringSession()) return 0; + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + if ( args->isSet( "extract-to" ) ) + { + if ( args->count() == 2 ) + { + MainWindow *arkWin = new MainWindow(); + + arkWin->extractTo( args->url( 0 ), args->url( 1 ), args->isSet( "guess-name" ) ); + return 0; + } + else + { + KCmdLineArgs::usage( i18n( "Wrong number of arguments specified" ) ); + return 0; + } + } + + if ( args->isSet( "add-to" ) && ( !args->isSet( "add" ) ) ) + { + if ( args->count() < 2 ) + { + KCmdLineArgs::usage( i18n( "You need to specify at least one file to be added to the archive." ) ); + return 0; + } + else + { + KURL::List URLList; + for ( int c = 0; c < args->count()-1 ; c++ ) + URLList.append( args->url( c ) ); + + MainWindow *arkWin = new MainWindow(); + + arkWin->addToArchive( URLList, args->cwd(), args->url( args->count()-1 ) ); + return 0; + } + } + + if ( args->isSet( "add" ) && args->isSet( "add-to" ) ) // HACK + { + bool oneFile = (args->count() == 2 ) ; + + QString extension = args->arg( 0 ); + KURL archiveName = args->url( 1 ); // the filename + + // if more than one file -> use directory name + if ( !oneFile ) + archiveName.setPath( archiveName.directory() ); + + archiveName.setFileName( archiveName.fileName() + extension ); + KURL::List URLList; + for ( int c = 1; c < args->count(); c++ ) + URLList.append( args->url( c ) ); + + MainWindow *arkWin = new MainWindow(); + + arkWin->addToArchive( URLList, args->cwd(), archiveName, !oneFile ); + return 0; + } + + + if ( args->isSet( "add" ) && ( !args->isSet( "add-to" ) ) ) + { + if ( args->count() < 1 ) + { + KCmdLineArgs::usage( i18n( "You need to specify at least one file to be added to the archive." ) ); + return 0; + } + else + { + KURL::List URLList; + for ( int c = 0; c < args->count() ; c++ ) + URLList.append( args->url( c ) ); + + MainWindow *arkWin = new MainWindow(); + + arkWin->addToArchive( URLList, args->cwd() ); + return 0; + } + } + + + int i = 0; + KURL url; + bool doAutoExtract = args->isSet("extract"); + bool tempFile = KCmdLineArgs::isTempFileSet(); + do + { + if (args->count() > 0) + { + url = args->url(i); + } + MainWindow *arkWin = new MainWindow(); + arkWin->show(); + if(doAutoExtract) + { + arkWin->setExtractOnly(true); + } + if (!url.isEmpty()) + { + arkWin->openURL(url, tempFile); + } + + ++i; + } while (i < args->count()); + + args->clear(); + return 0; +} + + +void +ArkApplication::addOpenArk(const KURL & _arkname, MainWindow *_ptr) +{ + QString realName; + if( _arkname.isLocalFile() ) + { + realName = resolveFilename( _arkname.path() ); // follow symlink + kdDebug(1601) << " Real name of " << _arkname.prettyURL() << " is " << realName << endl; + } + else + realName = _arkname.prettyURL(); + openArksList.append(realName); + m_windowsHash.replace(realName, _ptr); + kdDebug(1601) << "Saved ptr " << _ptr << " added open ark: " << realName << endl; +} + +void +ArkApplication::removeOpenArk(const KURL & _arkname) +{ + QString realName; + if ( _arkname.isLocalFile() ) + realName = resolveFilename( _arkname.path() ); // follow symlink + else + realName = _arkname.prettyURL(); + kdDebug(1601) << "Removing name " << _arkname.prettyURL() << endl; + openArksList.remove(realName); + m_windowsHash.remove(realName); +} + +void +ArkApplication::raiseArk(const KURL & _arkname) +{ + kdDebug( 1601 ) << "ArkApplication::raiseArk " << endl; + MainWindow *window; + QString realName; + if( _arkname.isLocalFile() ) + realName = resolveFilename(_arkname.path()); // follow symlink + else + realName = _arkname.prettyURL(); + window = m_windowsHash[realName]; + kdDebug(1601) << "ArkApplication::raiseArk " << window << endl; + // raise didn't seem to be enough. Not sure why! + // This might be annoying though. + //window->hide(); + //window->show(); + window->raise(); +} + +bool +ArkApplication::isArkOpenAlready(const KURL & _arkname) +{ + QString realName; + if ( _arkname.isLocalFile() ) + realName = resolveFilename(_arkname.path()); // follow symlink + else + realName = _arkname.prettyURL(); + return ( openArksList.findIndex(realName) != -1 ); +} + +#include "arkapp.moc" + diff --git a/ark/arkapp.h b/ark/arkapp.h new file mode 100644 index 0000000..1d1b474 --- /dev/null +++ b/ark/arkapp.h @@ -0,0 +1,93 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2002: Helio Chissini de Castro + 1999-2000: Corel Corporation (author: Emily Ezust emilye@corel.com) + 1999: Francois-Xavier Duranceau duranceau@kde.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef ARKAPP_H +#define ARKAPP_H + +#include "mainwindow.h" + +// QT includes +#include + +// KDE includes +#include + +class QString; +class QStringList; + +class EqualKey +{ + public: + bool operator()(const QString & str1, const QString & str2) const + { + return (str1 == str2); + } +}; + + +// This class follows the singleton pattern. +class ArkApplication : public KUniqueApplication +{ + Q_OBJECT + public: + virtual int newInstance(); + virtual ~ArkApplication() {} + + // keep track of windows so we know when to quit + int windowCount() { return m_windowCount; } + int addWindow() { ++m_windowCount; return m_windowCount; } + void removeWindow() { --m_windowCount;} + + // keep track of open archive names so we don't open one twice + // note that ArkWidget is not a pointer to const because raise() + // requires later a pointer to nonconst. + void addOpenArk(const KURL & _arkname, MainWindow * _ptr); + void removeOpenArk(const KURL & _arkname); + + bool isArkOpenAlready(const KURL & _arkname); + + void raiseArk(const KURL & _arkname); + + // use this function to access data from other modules. + static ArkApplication *getInstance(); + + protected: + ArkApplication(); + + private: + QWidget *m_mainwidget; // to be the parent of all ArkWidgets + int m_windowCount; + + QStringList openArksList; + + // a hash to obtain the window associated with a filename. + // given a QString key, you get an ArkWidget * pointer. + QDict m_windowsHash; + + static ArkApplication *mInstance; +}; + +#endif // ARKAPP_H diff --git a/ark/arkfactory.cpp b/ark/arkfactory.cpp new file mode 100644 index 0000000..8fcd262 --- /dev/null +++ b/ark/arkfactory.cpp @@ -0,0 +1,68 @@ +/* + ark -- archiver for the KDE project + + Copyright (C) 2003: Georg Robbers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include +#include + +#include "ark_part.h" +#include "arkfactory.h" + +KInstance* ArkFactory::s_instance = 0L; +KAboutData* ArkFactory::s_about = 0L; +int ArkFactory::instanceNumber = 0; + +K_EXPORT_COMPONENT_FACTORY( libarkpart, ArkFactory ) + +ArkFactory::~ArkFactory() +{ + delete s_instance; + delete s_about; + s_instance = 0L; +} + +KParts::Part * ArkFactory::createPartObject( QWidget *parentWidget, + const char *widgetName, QObject *parent, + const char *name, const char *classname, + const QStringList &args ) +{ + bool readWrite = false; // for e.g. Browser/View or KParts::ReadOnlyPart + if ( QCString( classname ) == "KParts::ReadWritePart" + || QCString( classname ) == "ArkPart" ) + { + readWrite = true; + } + ArkPart* obj = new ArkPart( parentWidget, widgetName, parent, name, + args, readWrite ); + //kdDebug( 1601 ) << "classname is: " << QCString( classname ) << endl; + return obj; +} + +KInstance* ArkFactory::instance() +{ + instanceNumber++; + if( !s_instance ) + { + s_about = ArkPart::createAboutData(); + s_instance = new KInstance( s_about ); + } + return s_instance; +} + diff --git a/ark/arkfactory.h b/ark/arkfactory.h new file mode 100644 index 0000000..ec3534a --- /dev/null +++ b/ark/arkfactory.h @@ -0,0 +1,43 @@ +/* + ark -- archiver for the KDE project + + Copyright (C) 2003: Georg Robbers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef ARKFACTORY_H +#define ARKFACTORY_H +#include + +class ArkFactory : public KParts::Factory +{ +public: + ArkFactory() : KParts::Factory() {} + virtual ~ArkFactory(); + virtual KParts::Part *createPartObject( + QWidget *parentWidget = 0,const char *widgetName = 0, + QObject *parent = 0, const char *name = 0, + const char *classname = "KParts::Part", + const QStringList &args = QStringList() ); + static KInstance* instance(); + private: + static KInstance* s_instance; + static KAboutData* s_about; + static int instanceNumber; +}; + +#endif diff --git a/ark/arkui.rc b/ark/arkui.rc new file mode 100644 index 0000000..335abc8 --- /dev/null +++ b/ark/arkui.rc @@ -0,0 +1,22 @@ + + + + &File + + + + + + + + + + + + + + + + + + diff --git a/ark/arkutils.cpp b/ark/arkutils.cpp new file mode 100644 index 0000000..1b4ed0a --- /dev/null +++ b/ark/arkutils.cpp @@ -0,0 +1,230 @@ +/* + + $Id$ + + ark -- archiver for the KDE project + + Copyright (C) + + 2002: Helio Chissini de Castro + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1997-1999: Rob Palmbos palm9744@kettering.edu + 2003: Hans Petter Bieker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include + +// C includes +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef _HPUX_SOURCE +#include +#endif + +// for statfs: +#ifdef BSD4_4 +#include +#elif defined(__linux__) +#include +#elif defined(__sun) +#include +#define STATFS statvfs +#elif defined(_AIX) +#include +#endif + +#ifndef STATFS +#define STATFS statfs +#endif + +// KDE includes +#include +#include +#include +#include + +// Qt includes +#include + +#include "arkutils.h" + +QString ArkUtils::getTimeStamp(const QString &_month, + const QString &_day, + const QString &_yearOrTime) +{ + // Make the date format sortable. + // Month is in _month, day is in _day. + // In _yearOrTime is either a year or a time. + // If it's March, we'll see the year for all dates up to October 1999. + // (five months' difference - e.g., if it's Apr, then get years up to Nov) + + char month[4]; + strncpy(month, _month.ascii(), 3); + month[3] = '\0'; + int nMonth = getMonth(month); + int nDay = _day.toInt(); + + kdDebug(1601) << "Month is " << nMonth << ", Day is " << nDay << endl; + + time_t t = time(0); + if (t == -1) + exit(1); + struct tm *now = localtime(&t); + int thisYear = now->tm_year + 1900; + int thisMonth = now->tm_mon + 1; + + QString year, timestamp; + + if (_yearOrTime.contains(":")) + // it has a timestamp so we have to figure out the year + { + year.sprintf("%d", ArkUtils::getYear(nMonth, thisYear, thisMonth)); + timestamp = _yearOrTime; + } + else + { + year = _yearOrTime; + if (year.right(1) == " ") + year = year.left(4); + if (year.left(1) == " ") + year = year.right(4); + + timestamp = "??:??"; + } + + QString retval; + retval.sprintf("%s-%.2d-%.2d %s", + year.utf8().data(), nMonth, nDay, + timestamp.utf8().data()); + return retval; +} + +int ArkUtils::getMonth(const char *strMonth) + // returns numeric value for three-char month string +{ + static char months[13][4] = { "", "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + int nIndex; + for (nIndex = 1; nIndex < 13; ++nIndex) + { + if (0 == strcmp(strMonth, months[nIndex])) + return nIndex; + } + return 0; +} + +// This function gets the year from an LHA or ls -l timestamp. +// Note: LHA doesn't seem to display the year if the file is more +// than 6 months into the future, so this will fail to give the correct +// year (of course it is hoped that there are not too many files lying +// around from the future). + +int ArkUtils::getYear(int theMonth, int thisYear, int thisMonth) +{ + int monthDiff = QABS(thisMonth - theMonth); + if (monthDiff > 6) + return (thisYear - 1); + else + return thisYear; +} + +QString ArkUtils::fixYear(const QString& strYear) +{ + // returns 4-digit year by guessing from two-char year string. + // Remember: this is used for file timestamps. There probably aren't any + // files that were created before 1970, so that's our cutoff. Of course, + // in 2070 we'll have some problems.... + + if ( strYear.length() != 2 ) return strYear; + + bool ok; + int y = strYear.toInt( &ok ); + + if ( ok ) + { + if ( y > 70 ) + y += 1900; + else + y += 2000; + + return QString::number( y ); + } + else + return QString::null; +} + +bool +ArkUtils::haveDirPermissions( const QString &strFile ) +{ + return ( access( QFile::encodeName( strFile ), W_OK ) == 0 ); +} + +bool +ArkUtils::diskHasSpace(const QString &dir, KIO::filesize_t size) + // check if disk has enough space to accommodate (a) new file(s) of + // the given size in the partition containing the given directory +{ + kdDebug( 1601 ) << "diskHasSpace() " << "dir: " << dir << " Size: " << size << endl; + + struct STATFS buf; + if (STATFS(QFile::encodeName(dir), &buf) == 0) + { + double nAvailable = (double)buf.f_bavail * buf.f_bsize; + if ( nAvailable < (double)size ) + { + KMessageBox::error(0, i18n("You have run out of disk space.")); + return false; + } + } + else + { + // something bad happened + kdWarning( 1601 ) << "diskHasSpace() failed" << endl; + // Q_ASSERT(0); + } + return true; +} + +KIO::filesize_t +ArkUtils::getSizes(QStringList *list) +{ + KIO::filesize_t sum = 0; + QString str; + KDE_struct_stat st; + + for ( QStringList::Iterator it = list->begin(); it != list->end(); ++it) + { + str = *it; + str = str.right(str.length()-5); + if (KDE_stat(QFile::encodeName(str), &st ) < 0) + continue; + sum += st.st_size; + } + return sum; +} diff --git a/ark/arkutils.h b/ark/arkutils.h new file mode 100644 index 0000000..4ddea65 --- /dev/null +++ b/ark/arkutils.h @@ -0,0 +1,56 @@ +// -*-C++-*- emacs magic for .h files +/* + + $Id$ + + ark -- archiver for the KDE project + + Copyright (C) + + 1997-1999: Rob Palmbos palm9744@kettering.edu + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + 2003: Hans Petter Bieker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef ARKUTILS_H +#define ARKUTILS_H + +#include + +#include + +class QStringList; + +// various functions for massaging timestamps +namespace ArkUtils +{ + int getYear(int theMonth, int thisYear, int thisMonth); + int getMonth(const char *strMonth); + QString fixYear(const QString& strYear); + + QString getTimeStamp(const QString &month, + const QString &day, + const QString &year); + bool haveDirPermissions(const QString &strFile); + bool diskHasSpace(const QString &dir, KIO::filesize_t size); + KIO::filesize_t getSizes(QStringList *list); +} + +#endif diff --git a/ark/arkviewer.cpp b/ark/arkviewer.cpp new file mode 100644 index 0000000..1ea76ac --- /dev/null +++ b/ark/arkviewer.cpp @@ -0,0 +1,103 @@ +/* + * ark: A program for modifying archives via a GUI. + * + * Copyright (C) 2004, Henrique Pinto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "arkviewer.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +ArkViewer::ArkViewer( QWidget * parent, const char * name ) + : KDialogBase( parent, name, false, QString::null, Close ), m_part( 0 ) +{ + m_widget = new QVBox( this ); + m_widget->layout()->setSpacing( 10 ); + + connect( this, SIGNAL( finished() ), this, SLOT( slotFinished() ) ); + + setMainWidget( m_widget ); +} + +ArkViewer::~ArkViewer() +{ + saveDialogSize( "ArkViewer" ); +} + +void ArkViewer::slotFinished() +{ + delete m_part; + m_part = 0; + delayedDestruct(); +} + +bool ArkViewer::view( const KURL& filename ) +{ + KMimeType::Ptr mimetype = KMimeType::findByURL( filename, 0, true ); + + setCaption( filename.fileName() ); + + QSize size = configDialogSize( "ArkViewer" ); + if (size.width() < 200) + size = QSize(560, 400); + setInitialSize( size ); + + QFrame *header = new QFrame( m_widget ); + QHBoxLayout *headerLayout = new QHBoxLayout( header ); + headerLayout->setAutoAdd( true ); + + QLabel *iconLabel = new QLabel( header ); + iconLabel->setPixmap( mimetype->pixmap( KIcon::Desktop ) ); + iconLabel->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ); + + QVBox *headerRight = new QVBox( header ); + new QLabel( QString( "%1" ) + .arg( filename.fileName() ), headerRight + ); + new QLabel( mimetype->comment(), headerRight ); + + header->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Maximum ); + + m_part = KParts::ComponentFactory::createPartInstanceFromQuery( mimetype->name(), QString::null, m_widget, 0, this ); + + if ( m_part ) + { + m_part->openURL( filename ); + show(); + return true; + } + else + { + return false; + } +} + +#include "arkviewer.moc" diff --git a/ark/arkviewer.h b/ark/arkviewer.h new file mode 100644 index 0000000..e0fda83 --- /dev/null +++ b/ark/arkviewer.h @@ -0,0 +1,47 @@ +#ifndef ARKVIEWER_H +#define ARKVIEWER_H + +/* + * ark: A program for modifying archives via a GUI. + * + * Copyright (C) 2004, Henrique Pinto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include + +class ArkViewer : public KDialogBase +{ + Q_OBJECT + + public: + ArkViewer( QWidget* parent = 0, const char * name = 0 ); + ~ArkViewer(); + + bool view( const KURL& filename ); + + protected slots: + void slotFinished(); + + private: + KParts::ReadOnlyPart *m_part; + QWidget *m_widget; +}; + +#endif // ARKVIEWER_H + diff --git a/ark/arkwidget.cpp b/ark/arkwidget.cpp new file mode 100644 index 0000000..d0fa3d4 --- /dev/null +++ b/ark/arkwidget.cpp @@ -0,0 +1,2262 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2004-2005: Henrique Pinto + 2003: Georg Robbers + 2002-2003: Helio Chissini de Castro + 2001-2002: Roberto Teixeira + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1997-1999: Rob Palmbos palm9744@kettering.edu + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include +#include + +// Qt includes +#include +#include +#include +#include +#include + +// KDE includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// settings +#include "settings.h" +#include "general.h" +#include "addition.h" +#include "extraction.h" +#include +#include + +// ark includes +#include "arkapp.h" +#include "archiveformatdlg.h" +#include "extractiondialog.h" +#include "arkwidget.h" +#include "filelistview.h" +#include "arkutils.h" +#include "archiveformatinfo.h" +#include "compressedfile.h" +#include "searchbar.h" +#include "arkviewer.h" + +static void viewInExternalViewer( ArkWidget* parent, const KURL& filename ) +{ + QString mimetype = KMimeType::findByURL( filename )->name(); + bool view = true; + + if ( KRun::isExecutable( mimetype ) ) + { + QString text = i18n( "The file you're trying to view may be an executable. Running untrusted executables may compromise your system's security.\nAre you sure you want to run that file?" ); + view = ( KMessageBox::warningContinueCancel( parent, text, QString::null, i18n("Run Nevertheless") ) == KMessageBox::Continue ); + } + + if ( view ) + KRun::runURL( filename, mimetype ); + +} + +//---------------------------------------------------------------------- +// +// Class ArkWidget starts here +// +//---------------------------------------------------------------------- + +ArkWidget::ArkWidget( QWidget *parent, const char *name ) + : QVBox(parent, name), m_bBusy( false ), m_bBusyHold( false ), + m_extractOnly( false ), m_extractRemote(false), + m_openAsMimeType(QString::null), m_pTempAddList(NULL), + m_bArchivePopupEnabled( false ), + m_convert_tmpDir( NULL ), m_convertSuccess( false ), + m_createRealArchTmpDir( NULL ), m_extractRemoteTmpDir( NULL ), + m_modified( false ), m_searchToolBar( 0 ), m_searchBar( 0 ), + arch( 0 ), m_archType( UNKNOWN_FORMAT ), m_fileListView( 0 ), + m_nSizeOfFiles( 0 ), m_nSizeOfSelectedFiles( 0 ), m_nNumFiles( 0 ), + m_nNumSelectedFiles( 0 ), m_bIsArchiveOpen( false ), + m_bIsSimpleCompressedFile( false ), + m_bDropSourceIsSelf( false ), m_extractList( 0 ) +{ + m_tmpDir = new KTempDir( locateLocal( "tmp", "ark" ) ); + + if ( m_tmpDir->status() != 0 ) + { + kdWarning( 1601 ) << "Could not create a temporary directory. status() returned " + << m_tmpDir->status() << "." << endl; + m_tmpDir = NULL; + } + + m_searchToolBar = new KToolBar( this, "searchBar" ); + m_searchToolBar->boxLayout()->setSpacing( KDialog::spacingHint() ); + + QLabel * l1 = new QLabel( i18n( "&Search:" ), m_searchToolBar, "kde toolbar widget" ); + m_searchBar = new SearchBar( m_searchToolBar, 0 ); + l1->setBuddy( m_searchBar ); + + m_searchToolBar->setStretchableWidget( m_searchBar ); + + if ( !ArkSettings::showSearchBar() ) + m_searchToolBar->hide(); + + createFileListView(); + + m_searchBar->setListView( m_fileListView ); + + // enable DnD + setAcceptDrops(true); + setFocusProxy(m_searchBar); +} + +ArkWidget::~ArkWidget() +{ + cleanArkTmpDir(); + ready(); + delete m_pTempAddList; + delete m_fileListView; + m_fileListView = 0; + delete arch; + ArkSettings::writeConfig(); +} + +void ArkWidget::cleanArkTmpDir() +{ + removeDownloadedFiles(); + if ( m_tmpDir ) + { + m_tmpDir->unlink(); + delete m_tmpDir; + m_tmpDir = NULL; + } +} + +void ArkWidget::closeArch() +{ + if ( isArchiveOpen() ) + { + delete arch; + arch = 0; + m_bIsArchiveOpen = false; + } + + if ( m_fileListView ) + { + m_fileListView->clear(); + m_fileListView->clearHeaders(); + } +} + +//////////////////////////////////////////////////////////////////// +///////////////////////// updateStatusTotals /////////////////////// +//////////////////////////////////////////////////////////////////// + +void +ArkWidget::updateStatusTotals() +{ + m_nNumFiles = m_fileListView->totalFiles(); + m_nSizeOfFiles = m_fileListView->totalSize(); + + QString strInfo = i18n( "%n file %1", "%n files %1", m_nNumFiles ) + .arg( KIO::convertSize( m_nSizeOfFiles ) ); + emit setStatusBarText(strInfo); +} + +void +ArkWidget::busy( const QString & text ) +{ + emit setBusy( text ); + + if ( m_bBusy ) + return; + + m_fileListView->setEnabled( false ); + + QApplication::setOverrideCursor( waitCursor ); + m_bBusy = true; +} + +void +ArkWidget::holdBusy() +{ + if ( !m_bBusy || m_bBusyHold ) + return; + + m_bBusyHold = true; + QApplication::restoreOverrideCursor(); +} + +void +ArkWidget::resumeBusy() +{ + if ( !m_bBusyHold ) + return; + + m_bBusyHold = false; + QApplication::setOverrideCursor( waitCursor ); +} + +void +ArkWidget::ready() +{ + if ( !m_bBusy ) + return; + + m_fileListView->setEnabled( true ); + + QApplication::restoreOverrideCursor(); + emit setReady(); + m_bBusyHold = false; + m_bBusy = false; +} + +////////////////////////////////////////////////////////////////////// +////////////////////// file_save_as ////////////////////////////////// +////////////////////////////////////////////////////////////////////// + +KURL +ArkWidget::getSaveAsFileName() +{ + QString defaultMimeType; + if ( m_openAsMimeType.isNull() ) + defaultMimeType = KMimeType::findByPath( m_strArchName )->name(); + else + defaultMimeType = m_openAsMimeType; + + KURL u; + QString suggestedName; + if ( m_realURL.isLocalFile() ) + suggestedName = m_realURL.url(); + else + suggestedName = m_realURL.fileName( false ); + + do + { + u = getCreateFilename( i18n( "Save Archive As" ), defaultMimeType, true, suggestedName ); + if ( u.isEmpty() ) + return u; + if( allowedArchiveName( u ) || ( ArchiveFormatInfo::self()->archTypeByExtension( u.path() ) != UNKNOWN_FORMAT ) ) + break; + KMessageBox::error( this, i18n( "Please save your archive in the same format as the original.\nHint: Use one of the suggested extensions." ) ); + } + while ( true ); + return u; +} + +bool +ArkWidget::file_save_as( const KURL & u ) +{ + bool success = KIO::NetAccess::upload( m_strArchName, u, this ); + if ( m_modified && success ) + m_modified = false; + return success; +} + +void +ArkWidget::convertTo( const KURL & u ) +{ + busy( i18n( "Saving..." ) ); + m_convert_tmpDir = new KTempDir( tmpDir() + "convtmp" ); + m_convert_tmpDir->setAutoDelete( true ); + connect( arch, SIGNAL( sigExtract( bool ) ), this, SLOT( convertSlotExtractDone( bool ) ) ); + m_convert_saveAsURL = u; + arch->unarchFile( 0, m_convert_tmpDir->name() ); +} + +void +ArkWidget::convertSlotExtractDone( bool ) +{ + kdDebug( 1601 ) << k_funcinfo << endl; + disconnect( arch, SIGNAL( sigExtract( bool ) ), this, SLOT( convertSlotExtractDone( bool ) ) ); + QTimer::singleShot( 0, this, SLOT( convertSlotCreate() ) ); +} + +void +ArkWidget::convertSlotCreate() +{ + file_close(); + connect( this, SIGNAL( createDone( bool ) ), this, SLOT( convertSlotCreateDone( bool ) ) ); + QString archToCreate; + if ( m_convert_saveAsURL.isLocalFile() ) + archToCreate = m_convert_saveAsURL.path(); + else + archToCreate = tmpDir() + m_convert_saveAsURL.fileName(); + + createArchive( archToCreate ); +} + + +void +ArkWidget::convertSlotCreateDone( bool success ) +{ + disconnect( this, SIGNAL( createDone( bool ) ), this, SLOT( convertSlotCreateDone( bool ) ) ); + kdDebug( 1601 ) << k_funcinfo << endl; + if ( !success ) + { + kdWarning( 1601 ) << "Error while converting. (convertSlotCreateDone)" << endl; + return; + } + QDir dir( m_convert_tmpDir->name() ); + QStringList entries = dir.entryList(); + entries.remove( ".." ); + entries.remove( "." ); + QStringList::Iterator it = entries.begin(); + for ( ; it != entries.end(); ++it ) + { + /////////////////////////////////////////////////////// + // BIG TODO: get rid of 'the assume // + // 'file:/', do some black magic // + // to find the basedir, chdir there, // + // and break the rest of the world' // + // hack. See also action_edit ... // + // addFile should be: // + // addFile( const QString & baseDir, // + // const QStringList & filesToAdd ) // + ////////////////////////////////////////////////////// + *it = QString::fromLatin1( "file:" )+ m_convert_tmpDir->name() + *it; + } + bool bOldRecVal = ArkSettings::rarRecurseSubdirs(); + connect( arch, SIGNAL( sigAdd( bool ) ), this, SLOT( convertSlotAddDone( bool ) ) ); + arch->addFile( entries ); + ArkSettings::setRarRecurseSubdirs( bOldRecVal ); +} + +void +ArkWidget::convertSlotAddDone( bool success ) +{ + disconnect( arch, SIGNAL( sigAdd( bool ) ), this, SLOT( convertSlotAddDone( bool ) ) ); + kdDebug( 1601 ) << k_funcinfo << endl; + m_convertSuccess = success; + // needed ? (TarArch, lzo) + QTimer::singleShot( 0, this, SLOT( convertFinish() ) ); +} + +void +ArkWidget::convertFinish() +{ + kdDebug( 1601 ) << k_funcinfo << endl; + delete m_convert_tmpDir; + m_convert_tmpDir = NULL; + + ready(); + if ( m_convertSuccess ) + { + if ( m_convert_saveAsURL.isLocalFile() ) + { + emit openURLRequest( m_convert_saveAsURL ); + } + else + { + KIO::NetAccess::upload( tmpDir() + + m_convert_saveAsURL.fileName(), m_convert_saveAsURL, this ); + // TODO: save bandwidth - we already have a local tmp file ... + emit openURLRequest( m_convert_saveAsURL ); + } + } + else + { + kdWarning( 1601 ) << "Error while converting (convertSlotAddDone)" << endl; + } +} + +bool +ArkWidget::allowedArchiveName( const KURL & u ) +{ + if (u.isEmpty()) + return false; + + QString archMimeType = KMimeType::findByURL( m_url )->name(); + if ( !m_openAsMimeType.isNull() ) + archMimeType = m_openAsMimeType; + QString newArchMimeType = KMimeType::findByPath( u.path() )->name(); + if ( archMimeType == newArchMimeType ) + return true; + + return false; +} + +void +ArkWidget::extractTo( const KURL & targetDirectory, const KURL & archive, bool bGuessName ) +{ + m_extractTo_targetDirectory = targetDirectory; + + if ( bGuessName ) // suggest an extract directory based on archive name + { + const QString fileName = guessName( archive ); + m_extractTo_targetDirectory.setPath( targetDirectory.path( 1 ) + fileName + '/' ); + } + + if ( !KIO::NetAccess::exists( m_extractTo_targetDirectory, false, this ) ) + { + if ( !KIO::NetAccess::mkdir( m_extractTo_targetDirectory, this ) ) + { + KMessageBox::error( 0, i18n( "Could not create the folder %1" ).arg( + targetDirectory.prettyURL() ) ); + emit request_file_quit(); + return; + } + } + + connect( this, SIGNAL( openDone( bool ) ), this, SLOT( extractToSlotOpenDone( bool ) ) ); +} + +const QString +ArkWidget::guessName( const KURL &archive ) +{ + QString fileName = archive.fileName(); + QStringList list = KMimeType::findByPath( fileName )->patterns(); + QStringList::Iterator it = list.begin(); + QString ext; + for ( ; it != list.end(); ++it ) + { + ext = (*it).remove( '*' ); + if ( fileName.endsWith( ext ) ) + { + fileName = fileName.left( fileName.findRev( ext ) ); + break; + } + } + + return fileName; +} + +void +ArkWidget::extractToSlotOpenDone( bool success ) +{ + disconnect( this, SIGNAL( openDone( bool ) ), this, SLOT( extractToSlotOpenDone( bool ) ) ); + if ( !success ) + { + KMessageBox::error( this, i18n( "An error occurred while opening the archive %1." ).arg( m_url.prettyURL() ) ); + emit request_file_quit(); + return; + } + + QString extractDir = m_extractTo_targetDirectory.path(); + // little code duplication from action_extract(): + if ( !m_extractTo_targetDirectory.isLocalFile() ) + { + m_extractRemoteTmpDir = new KTempDir( tmpDir() + "extremote" ); + m_extractRemoteTmpDir->setAutoDelete( true ); + + extractDir = m_extractRemoteTmpDir->name(); + m_extractRemote = true; + + if ( m_extractRemoteTmpDir->status() != 0 ) + { + kdWarning(1601) << "Unable to create " << extractDir << endl; + m_extractRemote = false; + emit request_file_quit(); + return; + } + } + + QStringList empty; + QStringList alreadyExisting = existingFiles( extractDir, empty ); + kdDebug( 1601 ) << "Already existing files count: " << existingFiles( extractDir, empty ).count() << endl; + bool keepGoing = true; + if ( !ArkSettings::extractOverwrite() && !alreadyExisting.isEmpty() ) + { + keepGoing = ( KMessageBox::Continue == KMessageBox::warningContinueCancelList( this, + i18n( "The following files will not be extracted\nbecause they " + "already exist:" ), alreadyExisting ) ); + } + + if ( keepGoing ) // if the user's OK with those failures, go ahead + { + // unless we have no space! + if ( ArkUtils::diskHasSpace( extractDir, m_nSizeOfFiles ) ) + { + disableAll(); + connect( arch, SIGNAL( sigExtract( bool ) ), this, SLOT( extractToSlotExtractDone( bool ) ) ); + arch->unarchFile( 0, extractDir ); + } + else + { + KMessageBox::error( this, i18n( "Not enough free disc space to extract the archive." ) ); + emit request_file_quit(); + return; + } + } + else + emit request_file_quit(); +} + +void +ArkWidget::extractToSlotExtractDone( bool success ) +{ + disconnect( arch, SIGNAL( sigExtract( bool ) ), this, SLOT( extractToSlotExtractDone( bool ) ) ); + if ( !success ) + { + kdDebug( 1601 ) << "Last Shell Output" << arch->getLastShellOutput() << endl; + KMessageBox::error( this, i18n( "An error occurred while extracting the archive." ) ); + emit request_file_quit(); + return; + } + + if ( m_extractRemote ) + { + connect( this, SIGNAL( extractRemoteMovingDone() ), this, SIGNAL( request_file_quit() ) ); + extractRemoteInitiateMoving( m_extractTo_targetDirectory ); + } + else + emit request_file_quit(); +} + +bool +ArkWidget::addToArchive( const KURL::List & filesToAdd, const KURL & archive) +{ + m_addToArchive_filesToAdd = filesToAdd; + m_addToArchive_archive = archive; + if ( !KIO::NetAccess::exists( archive, false, this ) ) + { + if ( !m_openAsMimeType.isEmpty() ) + { + QStringList extensions = KMimeType::mimeType( m_openAsMimeType )->patterns(); + QStringList::Iterator it = extensions.begin(); + QString file = archive.path(); + for ( ; it != extensions.end() && !file.endsWith( ( *it ).remove( '*' ) ); ++it ) + ; + + if ( it == extensions.end() ) + { + file += ArchiveFormatInfo::self()->defaultExtension( m_openAsMimeType ); + const_cast< KURL & >( archive ).setPath( file ); + } + } + + connect( this, SIGNAL( createDone( bool ) ), this, SLOT( addToArchiveSlotCreateDone( bool ) ) ); + + // TODO: remote Archives should be handled by createArchive + if ( archive.isLocalFile() ) + { + if ( !createArchive( archive.path() ) ) + return false; + } + else + { + if ( !createArchive( tmpDir() + archive.fileName() ) ) + return false; + } + return true; + + } + connect( this, SIGNAL( openDone( bool ) ), this, SLOT( addToArchiveSlotOpenDone( bool ) ) ); + return true; +} + +void +ArkWidget::addToArchiveSlotCreateDone( bool success ) +{ + disconnect( this, SIGNAL( createDone( bool ) ), this, SLOT( addToArchiveSlotCreateDone( bool ) ) ); + if ( !success ) + { + kdDebug( 1601 ) << "Could not create the archive" << endl; + emit request_file_quit(); + return; + } + addToArchiveSlotOpenDone( true ); +} + +void +ArkWidget::addToArchiveSlotOpenDone( bool success ) +{ + kdDebug( 1601 ) << k_funcinfo << endl; + disconnect( this, SIGNAL( openDone( bool ) ), this, SLOT( addToArchiveSlotOpenDone( bool ) ) ); + // TODO: handle dirs with addDir ( or better+easier: get rid of the need to do that entirely ) + if ( !success ) + { + emit request_file_quit(); + return; + } + + if ( m_bIsSimpleCompressedFile && (m_nNumFiles == 1)) + { + QString strFilename; + KURL url = askToCreateRealArchive(); + strFilename = url.path(); + if (!strFilename.isEmpty()) + { + connect( this, SIGNAL( createRealArchiveDone( bool ) ), this, SLOT( addToArchiveSlotAddDone( bool ) ) ); + createRealArchive( strFilename, m_addToArchive_filesToAdd.toStringList() ); + return; + } + else + { + emit request_file_quit(); + return; + } + } + +/* QStringList list = m_addToArchive_filesToAdd.toStringList(); + if ( !ArkUtils::diskHasSpace( tmpDir(), ArkUtils::getSizes( &list ) ) ) + { + KMessageBox::error( this, i18n( "Not enough free disc space to extract the archive." ) ); + emit request_file_quit(); + return; + }*/ + + disableAll(); + // if they are URLs, we have to download them, replace the URLs + // with filenames, and remember to delete the temporaries later. +/* for ( QStringList::Iterator it = list.begin(); + it != list.end(); ++it) + { + QString str = *it; + KURL url( toLocalFile( str ) ); + *it = url.prettyURL(); + } +*/ + KURL::List list = m_addToArchive_filesToAdd; + + + // Remote URLs need to be downloaded. + KURL::List::Iterator end( list.end() ); + for ( KURL::List::Iterator it = list.begin(); it != end; ++it ) + { + if (!(*it).isLocalFile()) + { + *it = toLocalFile( *it ); + } + } + + kdDebug( 1601 ) << "Adding: " << list << endl; + + connect( arch, SIGNAL( sigAdd( bool ) ), this, SLOT( addToArchiveSlotAddDone( bool ) ) ); + arch->addFile( list.toStringList() ); +} + +void +ArkWidget::addToArchiveSlotAddDone( bool success ) +{ + kdDebug( 1601 ) << k_funcinfo << endl; + disconnect( this, SLOT( addToArchiveSlotAddDone( bool ) ) ); + if ( !success ) + { + KMessageBox::error( this, i18n( "An error occurred while adding the files to the archive." ) ); + } + if ( !m_addToArchive_archive.isLocalFile() ) + KIO::NetAccess::upload( m_strArchName, m_addToArchive_archive, this ); + emit request_file_quit(); + return; +} + +void ArkWidget::setOpenAsMimeType( const QString & mimeType ) +{ + m_openAsMimeType = mimeType; +} + +void +ArkWidget::file_open(const KURL& url) +{ + if ( url.isEmpty() ) + { + kdDebug( 1601 ) << "file_open: url empty" << endl; + return; + } + + if ( isArchiveOpen() ) + file_close(); // close old arch. If we don't, our temp file is wrong! + + if ( !url.isLocalFile() ) + { + kdWarning ( 1601 ) << url.prettyURL() << " is not a local URL in ArkWidget::file_open( KURL). Aborting. " << endl; + return; + } + + + QString strFile = url.path(); + + kdDebug( 1601 ) << "File to open: " << strFile << endl; + + QFileInfo fileInfo( strFile ); + if ( !fileInfo.exists() ) + { + KMessageBox::error(this, i18n("The archive %1 does not exist.").arg(strFile)); + emit removeRecentURL( m_realURL ); + return; + } + else if ( !fileInfo.isReadable() ) + { + KMessageBox::error(this, i18n("You do not have permission to access that archive.") ); + emit removeRecentURL( m_realURL ); + return; + } + + // see if the user is just opening the same file that's already + // open (erm...) + + if (strFile == m_strArchName && m_bIsArchiveOpen) + { + kdDebug( 1601 ) << "file_open: strFile == m_strArchName" << endl; + return; + } + + // no errors if we made it this far. + + // Set the current archive filename to the filename + m_strArchName = strFile; + m_url = url; + //arch->clearShellOutput(); + + openArchive( strFile ); +} + + +// File menu ///////////////////////////////////////////////////////// + +KURL +ArkWidget::getCreateFilename(const QString & _caption, + const QString & _defaultMimeType, + bool allowCompressed, + const QString & _suggestedName ) +{ + int choice=0; + bool fileExists = true; + QString strFile; + KURL url; + + KFileDialog dlg( ":ArkSaveAsDialog", QString::null, this, "SaveAsDialog", true ); + dlg.setCaption( _caption ); + dlg.setOperationMode( KFileDialog::Saving ); + dlg.setMimeFilter( ArchiveFormatInfo::self()->supportedMimeTypes( allowCompressed ), + _defaultMimeType.isNull() ? "application/x-tgz" : _defaultMimeType ); + if ( !_suggestedName.isEmpty() ) + dlg.setSelection( _suggestedName ); + + while ( fileExists ) + // keep asking for filenames as long as the user doesn't want to + // overwrite existing ones; break if they agree to overwrite + // or if the file doesn't already exist. Return if they cancel. + // Also check for proper extensions. + { + dlg.exec(); + url = dlg.selectedURL(); + strFile = url.path(); + + if (strFile.isEmpty()) + return QString::null; + + //the user chose to save as the current archive + //or wanted to create a new one with the same name + //no need to do anything + if (strFile == m_strArchName && m_bIsArchiveOpen) + return QString::null; + + QStringList extensions = dlg.currentFilterMimeType()->patterns(); + QStringList::Iterator it = extensions.begin(); + for ( ; it != extensions.end() && !strFile.endsWith( ( *it ).remove( '*' ) ); ++it ) + ; + + if ( it == extensions.end() ) + { + strFile += ArchiveFormatInfo::self()->defaultExtension( dlg.currentFilterMimeType()->name() ); + url.setPath( strFile ); + } + + kdDebug(1601) << "Trying to create an archive named " << strFile << endl; + fileExists = QFile::exists( strFile ); + if( fileExists ) + { + choice = KMessageBox::warningYesNoCancel(0, + i18n("Archive already exists. Do you wish to overwrite it?"), + i18n("Archive Already Exists"), i18n("Overwrite"), i18n("Do Not Overwrite")); + + if ( choice == KMessageBox::Yes ) + { + QFile::remove( strFile ); + break; + } + else if ( choice == KMessageBox::Cancel ) + { + return QString::null; + } + else + { + continue; + } + } + // if we got here, the file does not already exist. + if ( !ArkUtils::haveDirPermissions( url.directory() ) ) + { + KMessageBox::error( this, + i18n( "You do not have permission" + " to write to the directory %1" ).arg(url.directory() ) ); + return QString::null; + } + } // end of while loop + + return url; +} + +void +ArkWidget::file_new() +{ + QString strFile; + KURL url = getCreateFilename(i18n("Create New Archive") ); + strFile = url.path(); + if (!strFile.isEmpty()) + { + file_close(); + createArchive( strFile ); + } +} + +void +ArkWidget::extractOnlyOpenDone() +{ + bool done = action_extract(); + + // last extract dir is still set, but this is not a problem + if( !done ) + { + emit request_file_quit(); + } + +} + +void +ArkWidget::slotExtractDone(bool success) +{ + disconnect( arch, SIGNAL( sigExtract( bool ) ), + this, SLOT( slotExtractDone(bool) ) ); + ready(); + + if(m_extractList != 0) + delete m_extractList; + m_extractList = 0; + + if( m_fileListView ) // avoid race condition, don't do updates if application is exiting + { + m_fileListView->setUpdatesEnabled(true); + fixEnables(); + } + + if ( m_extractRemote ) + { + extractRemoteInitiateMoving( m_extractURL ); + } + else if( m_extractOnly ) + { + emit request_file_quit(); + } + + if ( success && ArkSettings::openDestinationFolder() ) + { + KRun::runURL( m_extractURL, "inode/directory" ); + } + + kdDebug(1601) << "-ArkWidget::slotExtractDone" << endl; +} + +void +ArkWidget::extractRemoteInitiateMoving( const KURL & target ) +{ + KURL srcDirURL; + KURL src; + QString srcDir; + + srcDir = m_extractRemoteTmpDir->name(); + srcDirURL.setPath( srcDir ); + + QDir dir( srcDir ); + dir.setFilter( QDir::All | QDir::Hidden ); + QStringList lst( dir.entryList() ); + lst.remove( "." ); + lst.remove( ".." ); + + KURL::List srcList; + for( QStringList::ConstIterator it = lst.begin(); it != lst.end() ; ++it) + { + src = srcDirURL; + src.addPath( *it ); + srcList.append( src ); + } + + m_extractURL.adjustPath( 1 ); + + KIO::CopyJob *job = KIO::copy( srcList, target, this ); + connect( job, SIGNAL(result(KIO::Job*)), + this, SLOT(slotExtractRemoteDone(KIO::Job*)) ); + + m_extractRemote = false; +} + +void +ArkWidget::slotExtractRemoteDone(KIO::Job *job) +{ + delete m_extractRemoteTmpDir; + m_extractRemoteTmpDir = NULL; + + if ( job->error() ) + job->showErrorDialog(); + + emit extractRemoteMovingDone(); + + if ( m_extractOnly ) + emit request_file_quit(); +} + + +void +ArkWidget::disableAll() // private +{ + emit disableAllActions(); + m_fileListView->setUpdatesEnabled(true); +} + +void +ArkWidget::fixEnables() // private +{ + emit fixActions(); //connected to the part +} + +void +ArkWidget::file_close() +{ + if ( isArchiveOpen() ) + { + closeArch(); + emit setWindowCaption( QString::null ); + emit removeOpenArk( m_strArchName ); + updateStatusTotals(); + updateStatusSelection(); + fixEnables(); + } + else + { + closeArch(); + } + + m_strArchName = QString::null; + m_url = KURL(); +} + + +KURL +ArkWidget::askToCreateRealArchive() +{ + // ask user whether to create a real archive from a compressed file + // returns filename if so + KURL url; + int choice = + KMessageBox::warningYesNo(0, i18n("You are currently working with a simple compressed file.\nWould you like to make it into an archive so that it can contain multiple files?\nIf so, you must choose a name for your new archive."), i18n("Warning"),i18n("Make Into Archive"),i18n("Do Not Make")); + if (choice == KMessageBox::Yes) + { + url = getCreateFilename( i18n("Create New Archive"), + QString::null, false ); + } + else + url.setPath( QString::null ); + return url; +} + +void +ArkWidget::createRealArchive( const QString & strFilename, const QStringList & filesToAdd ) +{ + Arch * newArch = getNewArchive( strFilename ); + busy( i18n( "Creating archive..." ) ); + if ( !newArch ) + return; + if ( !filesToAdd.isEmpty() ) + m_pTempAddList = new QStringList( filesToAdd ); + m_compressedFile = static_cast< CompressedFile * >( arch )->tempFileName(); + KURL u1, u2; + u1.setPath( m_compressedFile ); + m_createRealArchTmpDir = new KTempDir( tmpDir() + "create_real_arch" ); + u2.setPath( m_createRealArchTmpDir->name() + u1.fileName() ); + KIO::NetAccess::copy( u1, u2, this ); + m_compressedFile = "file:" + u2.path(); // AGAIN THE 5 SPACES Hack :-( + connect( newArch, SIGNAL( sigCreate( Arch *, bool, const QString &, int ) ), + this, SLOT( createRealArchiveSlotCreate( Arch *, bool, + const QString &, int ) ) ); + file_close(); + newArch->create(); +} + +void +ArkWidget::createRealArchiveSlotCreate( Arch * newArch, bool success, + const QString & fileName, int nbr ) +{ + slotCreate( newArch, success, fileName, nbr ); + + if ( !success ) + return; + + QStringList listForCompressedFile; + listForCompressedFile.append(m_compressedFile); + disableAll(); + + connect( newArch, SIGNAL( sigAdd( bool ) ), this, + SLOT( createRealArchiveSlotAddDone( bool ) ) ); + + newArch->addFile(listForCompressedFile); +} + +void +ArkWidget::createRealArchiveSlotAddDone( bool success ) +{ + kdDebug( 1601 ) << "createRealArchiveSlotAddDone+, success:" << success << endl; + disconnect( arch, SIGNAL( sigAdd( bool ) ), this, + SLOT( createRealArchiveSlotAddDone( bool ) ) ); + + m_createRealArchTmpDir->unlink(); + delete m_createRealArchTmpDir; + m_createRealArchTmpDir = NULL; + + + if ( !success ) + return; + + ready(); + + if ( m_pTempAddList == NULL ) + { + // now get the files to be added + // we don't know which files to add yet + action_add(); + } + else + { + connect( arch, SIGNAL( sigAdd( bool ) ), this, + SLOT( createRealArchiveSlotAddFilesDone( bool ) ) ); + // files were dropped in + addFile( m_pTempAddList ); + } +} + +void +ArkWidget::createRealArchiveSlotAddFilesDone( bool success ) +{ + //kdDebug( 1601 ) << "createRealArchiveSlotAddFilesDone+, success:" << success << endl; + disconnect( arch, SIGNAL( sigAdd( bool ) ), this, + SLOT( createRealArchiveSlotAddFilesDone( bool ) ) ); + delete m_pTempAddList; + m_pTempAddList = NULL; + emit createRealArchiveDone( success ); +} + + + + +// Action menu ///////////////////////////////////////////////////////// + +void +ArkWidget::action_add() +{ + if (m_bIsSimpleCompressedFile && (m_nNumFiles == 1)) + { + QString strFilename; + KURL url = askToCreateRealArchive(); + strFilename = url.path(); + if (!strFilename.isEmpty()) + { + createRealArchive(strFilename); + } + return; + } + + KFileDialog fileDlg( ":ArkAddDir", QString::null, this, "adddlg", true ); + fileDlg.setMode( KFile::Mode( KFile::Files | KFile::ExistingOnly ) ); + fileDlg.setCaption(i18n("Select Files to Add")); + + if(fileDlg.exec()) + { + KURL::List addList; + addList = fileDlg.selectedURLs(); + QStringList * list = new QStringList(); + //Here we pre-calculate the end of the list + KURL::List::ConstIterator endList = addList.end(); + for (KURL::List::ConstIterator it = addList.begin(); it != endList; ++it) + list->append( KURL::decode_string( (*it).url() ) ); + + if ( list->count() > 0 ) + { + if ( m_bIsSimpleCompressedFile && list->count() > 1 ) + { + QString strFilename; + KURL url = askToCreateRealArchive(); + strFilename = url.path(); + if (!strFilename.isEmpty()) + { + createRealArchive(strFilename); + } + delete list; + return; + } + addFile( list ); + } + delete list; + } +} + +void +ArkWidget::addFile(QStringList *list) +{ + if ( !ArkUtils::diskHasSpace( tmpDir(), ArkUtils::getSizes( list ) ) ) + return; + + disableAll(); + busy( i18n( "Adding files..." ) ); + // if they are URLs, we have to download them, replace the URLs + // with filenames, and remember to delete the temporaries later. + for (QStringList::Iterator it = list->begin(); it != list->end(); ++it) + { + QString str = *it; + *it = toLocalFile(KURL(str)).prettyURL(); + + } + + connect( arch, SIGNAL( sigAdd( bool ) ), this, SLOT( slotAddDone( bool ) ) ); + arch->addFile( ( *list ) ); +} + +void +ArkWidget::action_add_dir() +{ + KURL u = KDirSelectDialog::selectDirectory( ":ArkAddDir", + false, this, + i18n("Select Folder to Add")); + + QString dir = KURL::decode_string( u.url(-1) ); + if ( !dir.isEmpty() ) + { + busy( i18n( "Adding folder..." ) ); + disableAll(); + u = toLocalFile(u); + connect( arch, SIGNAL( sigAdd( bool ) ), this, SLOT( slotAddDone( bool ) ) ); + arch->addDir( u.prettyURL() ); + } + +} + +void +ArkWidget::slotAddDone(bool _bSuccess) +{ + disconnect( arch, SIGNAL( sigAdd( bool ) ), this, SLOT( slotAddDone( bool ) ) ); + m_fileListView->setUpdatesEnabled(true); + m_fileListView->triggerUpdate(); + ready(); + + if (_bSuccess) + { + m_modified = true; + //simulate reload + KURL u; + u.setPath( arch->fileName() ); + file_close(); + file_open( u ); + emit setWindowCaption( u.path() ); + } + removeDownloadedFiles(); + fixEnables(); +} + + + +KURL +ArkWidget::toLocalFile( const KURL& url ) +{ + KURL localURL = url; + + if(!url.isLocalFile()) + { + QString strURL = url.prettyURL(); + + QString tempfile = tmpDir(); + tempfile += strURL.right(strURL.length() - strURL.findRev("/") - 1); + deleteAfterUse(tempfile); // remember for deletion + KURL tempurl; tempurl.setPath( tempfile ); + if( !KIO::NetAccess::dircopy(url, tempurl, this) ) + return KURL(); + localURL = tempfile; + } + return localURL; +} + +void +ArkWidget::deleteAfterUse( const QString& path ) +{ + mpDownloadedList.append( path ); +} + +void +ArkWidget::removeDownloadedFiles() +{ + if (!mpDownloadedList.isEmpty()) + { + // It is necessary to remove those files even if tmpDir() is getting deleted: + // not all files in mpDownloadedList are from tmpDir() - e.g. when using --tempfile + // But of course we could decide to not add files from tmpDir() into mpDownloadedList. + QStringList::ConstIterator it = mpDownloadedList.begin(); + QStringList::ConstIterator end = mpDownloadedList.end(); + for ( ; it != end ; ++it ) + QFile::remove( *it ); + mpDownloadedList.clear(); + } +} + +void +ArkWidget::action_delete() +{ + // remove selected files and create a list to send to the archive + // Warn the user if he/she/it tries to delete a directory entry in + // a tar file - it actually deletes the contents of the directory + // as well. + + if (m_fileListView->isSelectionEmpty()) + { + return; // shouldn't happen - delete should have been disabled! + } + + QStringList list = m_fileListView->selectedFilenames(); + + // ask for confirmation + if ( KMessageBox::warningContinueCancelList( this, + i18n( "Do you really want to delete the selected items?" ), + list, + QString::null, + KStdGuiItem::del(), + "confirmDelete" ) + != KMessageBox::Continue) + { + return; + } + + // Remove the entries from the list view + QListViewItemIterator it( m_fileListView ); + while ( it.current() ) + { + if ( it.current()->isSelected() ) + delete *it; + else + ++it; + } + + disableAll(); + busy( i18n( "Removing..." ) ); + connect( arch, SIGNAL( sigDelete( bool ) ), this, SLOT( slotDeleteDone( bool ) ) ); + arch->remove(&list); + kdDebug(1601) << "-ArkWidget::action_delete" << endl; +} + +void +ArkWidget::slotDeleteDone(bool _bSuccess) +{ + disconnect( arch, SIGNAL( sigDelete( bool ) ), this, SLOT( slotDeleteDone( bool ) ) ); + kdDebug(1601) << "+ArkWidget::slotDeleteDone" << endl; + m_fileListView->setUpdatesEnabled(true); + m_fileListView->triggerUpdate(); + if (_bSuccess) + { + m_modified = true; + updateStatusTotals(); + updateStatusSelection(); + } + // disable the select all and extract options if there are no files left + fixEnables(); + ready(); + kdDebug(1601) << "-ArkWidget::slotDeleteDone" << endl; + +} + + + +void +ArkWidget::slotOpenWith() +{ + connect( arch, SIGNAL( sigExtract( bool ) ), this, + SLOT( openWithSlotExtractDone( bool ) ) ); + + showCurrentFile(); +} + +void +ArkWidget::openWithSlotExtractDone( bool success ) +{ + disconnect( arch, SIGNAL( sigExtract( bool ) ), this, + SLOT( openWithSlotExtractDone( bool ) ) ); + + if ( success ) + { + KURL::List list; + list.append(m_viewURL); + KOpenWithDlg l( list, i18n("Open with:"), QString::null, (QWidget*)0L); + if ( l.exec() ) + { + KService::Ptr service = l.service(); + if ( !!service ) + { + KRun::run( *service, list ); + } + else + { + QString exec = l.text(); + exec += " %f"; + KRun::run( exec, list ); + } + } + } + + if( m_fileListView ) + { + m_fileListView->setUpdatesEnabled(true); + fixEnables(); + } +} + + +void +ArkWidget::prepareViewFiles( const QStringList & fileList ) +{ + QString destTmpDirectory; + destTmpDirectory = tmpDir(); + + // Make sure to delete previous file already there... + for(QStringList::ConstIterator it = fileList.begin(); + it != fileList.end(); ++it) + QFile::remove(destTmpDirectory + *it); + + m_viewList = new QStringList( fileList ); + arch->unarchFile( m_viewList, destTmpDirectory, true); +} + +bool +ArkWidget::reportExtractFailures( const QString & _dest, QStringList *_list ) +{ + // reports extract failures when Overwrite = False and the file + // exists already in the destination directory. + // If list is null, it means we are extracting all files. + // Otherwise the list contains the files we are to extract. + + bool redoExtraction = false; + QString strFilename; + + QStringList list = *_list; + QStringList filesExisting = existingFiles( _dest, list ); + + int numFilesToReport = filesExisting.count(); + + // now report on the contents + holdBusy(); + if (numFilesToReport != 0) + { + redoExtraction = ( KMessageBox::Cancel == KMessageBox::warningContinueCancelList( this, + i18n( "The following files will not be extracted\nbecause they " + "already exist:" ), filesExisting ) ); + } + resumeBusy(); + return redoExtraction; +} + +QStringList +ArkWidget::existingFiles( const QString & _dest, QStringList & _list ) +{ + QString strFilename, tmp; + + QString strDestDir = _dest; + + // make sure the destination directory has a / at the end. + if ( !strDestDir.endsWith( "/" ) ) + { + strDestDir += '/'; + } + + if (_list.isEmpty()) + { + _list = m_fileListView->fileNames(); + } + + QStringList existingFiles; + // now the list contains all the names we must verify. + for (QStringList::Iterator it = _list.begin(); it != _list.end(); ++it) + { + strFilename = *it; + QString strFullName = strDestDir + strFilename; + + // if the filename ends with an "/", it means it is a directory + if ( QFile::exists( strFullName ) && !strFilename.endsWith("/") ) + { + existingFiles.append( strFilename ); + } + } + return existingFiles; +} + + + + + +bool +ArkWidget::action_extract() +{ + KURL fileToExtract; + fileToExtract.setPath( arch->fileName() ); + + //before we start, make sure the archive is still there + if (!KIO::NetAccess::exists( fileToExtract.prettyURL(), true, this ) ) + { + KMessageBox::error(0, i18n("The archive to extract from no longer exists.")); + return false; + } + + //if more than one entry in the archive is root level, suggest a path prefix + QString prefix = m_fileListView->childCount() > 1 ? + QChar( '/' ) + guessName( realURL() ) + : QString(); + + // Should the extraction dialog show an option for extracting only selected files? + bool enableSelected = ( m_nNumSelectedFiles > 0 ) && + ( m_fileListView->totalFiles() > 1); + + QString base = ArkSettings::extractionHistory().isEmpty()? + QString() : ArkSettings::extractionHistory().first(); + if ( base.isEmpty() ) + { + // Perhaps the KDE Documents folder is a better choice? + base = QDir::homeDirPath(); + } + + // Default URL shown in the extraction dialog; + KURL defaultDir( base ); + + if ( m_extractOnly ) + { + defaultDir = KURL::fromPathOrURL( QDir::currentDirPath() ); + } + + ExtractionDialog *dlg = new ExtractionDialog( this, 0, enableSelected, defaultDir, prefix, m_url.fileName() ); + + bool bRedoExtract = false; + + // list of files to be extracted + m_extractList = new QStringList; + if ( dlg->exec() ) + { + //m_extractURL will always be the location the user chose to + //m_extract to, whether local or remote + m_extractURL = dlg->extractionDirectory(); + + //extractDir will either be the real, local extract dir, + //or in case of a extract to remote location, a local tmp dir + QString extractDir; + + if ( !m_extractURL.isLocalFile() ) + { + m_extractRemoteTmpDir = new KTempDir( tmpDir() + "extremote" ); + m_extractRemoteTmpDir->setAutoDelete( true ); + + extractDir = m_extractRemoteTmpDir->name(); + m_extractRemote = true; + if ( m_extractRemoteTmpDir->status() != 0 ) + { + kdWarning( 1601 ) << "Unable to create temporary directory" << extractDir << endl; + m_extractRemote = false; + delete dlg; + return false; + } + } + else + { + extractDir = m_extractURL.path(); + } + + // if overwrite is false, then we need to check for failure of + // extractions. + bool bOvwrt = ArkSettings::extractOverwrite(); + + if ( dlg->selectedOnly() == false ) + { + if (!bOvwrt) // send empty list to indicate we're extracting all + { + bRedoExtract = reportExtractFailures(extractDir, m_extractList); + } + + if (!bRedoExtract) // if the user's OK with those failures, go ahead + { + // unless we have no space! + if ( ArkUtils::diskHasSpace( extractDir, m_nSizeOfFiles ) ) + { + disableAll(); + busy( i18n( "Extracting..." ) ); + connect( arch, SIGNAL( sigExtract( bool ) ), this, SLOT( slotExtractDone(bool) ) ); + arch->unarchFile(0, extractDir); + } + } + } + else + { + KIO::filesize_t nTotalSize = 0; + // make a list to send to unarchFile + QStringList selectedFiles = m_fileListView->selectedFilenames(); + for ( QStringList::const_iterator it = selectedFiles.constBegin(); + it != selectedFiles.constEnd(); + ++it ) + { + m_extractList->append( QFile::encodeName( *it ) ); + } + + if (!bOvwrt) + { + bRedoExtract = reportExtractFailures(extractDir, m_extractList); + } + if (!bRedoExtract) + { + if (ArkUtils::diskHasSpace(extractDir, nTotalSize)) + { + disableAll(); + busy( i18n( "Extracting..." ) ); + connect( arch, SIGNAL( sigExtract( bool ) ), + this, SLOT( slotExtractDone(bool) ) ); + arch->unarchFile(m_extractList, extractDir); // extract selected files + } + } + } + + delete dlg; + } + else + { + delete dlg; + return false; + } + + // user might want to change some options or the selection... + if (bRedoExtract) + { + return action_extract(); + } + + return true; +} + +void +ArkWidget::action_edit() +{ + // begin an edit. This is like a view, but once the process exits, + // the file is put back into the archive. If the user tries to quit or + // close the archive, there will be a warning that any changes to the + // files open under "Edit" will be lost unless the archive remains open. + // [hmm, does that really make sense? I'll leave it for now.] + + busy( i18n( "Extracting..." ) ); + connect( arch, SIGNAL( sigExtract( bool ) ), this, + SLOT( editSlotExtractDone() ) ); + showCurrentFile(); +} + +void +ArkWidget::editSlotExtractDone() +{ + disconnect( arch, SIGNAL( sigExtract( bool ) ), + this, SLOT( editSlotExtractDone() ) ); + ready(); + editStart(); + + // avoid race condition, don't do updates if application is exiting + if( m_fileListView ) + { + m_fileListView->setUpdatesEnabled(true); + fixEnables(); + } +} + +void +ArkWidget::editStart() +{ + kdDebug(1601) << "Edit in progress..." << endl; + KURL::List list; + // edit will be in progress until the KProcess terminates. + KOpenWithDlg l( list, i18n("Edit with:"), + QString::null, (QWidget*)0L ); + if ( l.exec() ) + { + KProcess *kp = new KProcess; + + *kp << l.text() << m_strFileToView; + connect( kp, SIGNAL(processExited(KProcess *)), + this, SLOT(slotEditFinished(KProcess *)) ); + if ( kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false ) + { + KMessageBox::error(0, i18n("Trouble editing the file...")); + } + } +} + +void +ArkWidget::slotEditFinished(KProcess *kp) +{ + kdDebug(1601) << "+ArkWidget::slotEditFinished" << endl; + connect( arch, SIGNAL( sigAdd( bool ) ), this, SLOT( editSlotAddDone( bool ) ) ); + delete kp; + QStringList list; + // now put the file back into the archive. + list.append(m_strFileToView); + disableAll(); + + + // BUG: this puts any edited file back at the archive toplevel... + // there's only one file, and it's in the temp directory. + // If the filename has more than three /'s then we should + // change to the first level directory so that the paths + // come out right. + QStringList::Iterator it = list.begin(); + QString filename = *it; + QString path; + if (filename.contains('/') > 3) + { + kdDebug(1601) << "Filename is originally: " << filename << endl; + int i = filename.find('/', 5); + path = filename.left(1+i); + kdDebug(1601) << "Changing to dir: " << path << endl; + QDir::setCurrent(path); + filename = filename.right(filename.length()-i-1); + // HACK!! We need a relative path. If I have "file:", it + // will look like an absolute path. So five spaces here to get + // chopped off later.... + filename = " " + filename; + *it = filename; + } + + busy( i18n( "Readding edited file..." ) ); + arch->addFile( list ); + + kdDebug(1601) << "-ArkWidget::slotEditFinished" << endl; +} + +void +ArkWidget::editSlotAddDone( bool success ) +{ + ready(); + disconnect( arch, SIGNAL( sigAdd( bool ) ), this, SLOT( editSlotAddDone( bool ) ) ); + slotAddDone( success ); +} + +void +ArkWidget::action_view() +{ + connect( arch, SIGNAL( sigExtract( bool ) ), this, + SLOT( viewSlotExtractDone( bool ) ) ); + busy( i18n( "Extracting file to view" ) ); + showCurrentFile(); +} + +void +ArkWidget::viewSlotExtractDone( bool success ) +{ + if ( success ) + { + chmod( QFile::encodeName( m_strFileToView ), 0400 ); + bool view = true; + + if ( ArkSettings::useIntegratedViewer() ) + { + ArkViewer * viewer = new ArkViewer( this, "viewer" ); + + if ( !viewer->view( m_viewURL ) ) + { + QString text = i18n( "The internal viewer is not able to display this file. Would you like to view it using an external program?" ); + view = ( KMessageBox::warningYesNo( this, text, QString::null, i18n("View Externally"), i18n("Do Not View") ) == KMessageBox::Yes ); + + if ( view ) + viewInExternalViewer( this, m_viewURL ); + } + } + else + { + viewInExternalViewer( this, m_viewURL ); + } + } + + disconnect( arch, SIGNAL( sigExtract( bool ) ), this, + SLOT( viewSlotExtractDone( bool ) ) ); + + delete m_viewList; + + // avoid race condition, don't do updates if application is exiting + if( m_fileListView ) + { + m_fileListView->setUpdatesEnabled(true); + fixEnables(); + } + ready(); +} + + +void +ArkWidget::showCurrentFile() +{ + if ( !m_fileListView->currentItem() ) + return; + + QString name = m_fileListView->currentItem()->fileName(); + + QString fullname = tmpDir(); + fullname += name; + + if(fullname.contains("../")) + fullname.remove("../"); + + //Convert the QString filename to KURL to escape the bad characters + m_viewURL.setPath(fullname); + + m_strFileToView = fullname; + kdDebug(1601) << "File to be extracted: " << m_viewURL << endl; + + QStringList extractList; + extractList.append(name); + + if (ArkUtils::diskHasSpace( tmpDir(), m_fileListView->currentItem()->fileSize() ) ) + { + disableAll(); + prepareViewFiles( extractList ); + } +} + +// Popup ///////////////////////////////////////////////////////////// + +void +ArkWidget::setArchivePopupEnabled( bool b ) +{ + m_bArchivePopupEnabled = b; +} + +void +ArkWidget::doPopup( QListViewItem *pItem, const QPoint &pPoint, int nCol ) // slot +// do the right-click popup menus +{ + if ( nCol == 0 || !m_bArchivePopupEnabled ) + { + m_fileListView->setCurrentItem(pItem); + m_fileListView->setSelected(pItem, true); + emit signalFilePopup( pPoint ); + } + else // clicked anywhere else but the name column + { + emit signalArchivePopup( pPoint ); + } +} + + +void +ArkWidget::viewFile( QListViewItem* item ) // slot +// show contents when double click +{ + // Preview, if it is a file + if ( item->childCount() == 0) + emit action_view(); + else // Change opened state if it is a dir + item->setOpen( !item->isOpen() ); +} + + +// Service functions ///////////////////////////////////////////////// + +void +ArkWidget::slotSelectionChanged() +{ + updateStatusSelection(); +} + + +//////////////////////////////////////////////////////////////////// +//////////////////// updateStatusSelection ///////////////////////// +//////////////////////////////////////////////////////////////////// + +void +ArkWidget::updateStatusSelection() +{ + m_nNumSelectedFiles = m_fileListView->selectedFilesCount(); + m_nSizeOfSelectedFiles = m_fileListView->selectedSize(); + + QString strInfo; + if (m_nNumSelectedFiles == 0) + { + strInfo = i18n("0 files selected"); + } + else if (m_nNumSelectedFiles != 1) + { + strInfo = i18n("%1 files selected %2") + .arg(KGlobal::locale()->formatNumber(m_nNumSelectedFiles, 0)) + .arg(KIO::convertSize(m_nSizeOfSelectedFiles)); + } + else + { + strInfo = i18n("1 file selected %2") + .arg(KIO::convertSize(m_nSizeOfSelectedFiles)); + } + + emit setStatusBarSelectedFiles(strInfo); + fixEnables(); +} + + +// Drag & Drop //////////////////////////////////////////////////////// + +void +ArkWidget::dragMoveEvent(QDragMoveEvent *e) +{ + if (KURLDrag::canDecode(e) && !m_bDropSourceIsSelf) + { + e->accept(); + } +} + + +void +ArkWidget::dropEvent(QDropEvent* e) +{ + kdDebug( 1601 ) << "+ArkWidget::dropEvent" << endl; + + KURL::List list; + + if ( KURLDrag::decode( e, list ) ) + { + QStringList urlList = list.toStringList(); + dropAction( urlList ); + } + + kdDebug(1601) << "-dropEvent" << endl; +} + +////////////////////////////////////////////////////////////////////// +///////////////////////// dropAction ///////////////////////////////// +////////////////////////////////////////////////////////////////////// + +void +ArkWidget::dropAction( QStringList & list ) +{ + // Called by dropEvent + + // The possibilities treated are as follows: + // drop a regular file into a window with + // * an open archive - add it. + // * no open archive - ask user to open an archive for adding file or cancel + // drop an archive into a window with + // * an open archive - ask user to add to open archive or to open it freshly + // * no open archive - open it + // drop many files (can be a mix of archives and regular) into a window with + // * an open archive - add them. + // * no open archive - ask user to open an archive for adding files or cancel + + // and don't forget about gzip files. + + QString str; + QStringList urls; // to be sent to addFile + + str = list.first(); + + if ( 1 == list.count() && + ( UNKNOWN_FORMAT != ArchiveFormatInfo::self()->archTypeByExtension( str ) ) ) + { + // if there's one thing being dropped and it's an archive + if (isArchiveOpen()) + { + // ask them if they want to add the dragged archive to the current + // one or open it as the new current archive + int nRet = KMessageBox::warningYesNoCancel(this, + i18n("Do you wish to add this to the current archive or open it as a new archive?"), + QString::null, + i18n("&Add"), i18n("&Open")); + if (KMessageBox::Yes == nRet) // add it + { + if (m_bIsSimpleCompressedFile && (m_nNumFiles == 1)) + { + QString strFilename; + KURL url = askToCreateRealArchive(); + strFilename = url.path(); + if (!strFilename.isEmpty()) + { + createRealArchive( strFilename, list ); + } + return; + } + + addFile( &list ); + return; + } + else if (KMessageBox::Cancel == nRet) // cancel + { + return; + } + } + + // if I made it here, there's either no archive currently open + // or they selected "Open". + KURL url = str; + + emit openURLRequest( url ); + } + else + { + if (isArchiveOpen()) + { + if (m_bIsSimpleCompressedFile && (m_nNumFiles == 1)) + { + QString strFilename; + KURL url = askToCreateRealArchive(); + strFilename = url.path(); + if (!strFilename.isEmpty()) + { + createRealArchive( strFilename, list ); + } + return; + } + // add the files to the open archive + addFile( &list ); + } + else + { + // no archive is open, so we ask if the user wants to open one + // for this/these file/files. + + QString str; + str = (list.count() > 1) + ? i18n("There is no archive currently open. Do you wish to create one now for these files?") + : i18n("There is no archive currently open. Do you wish to create one now for this file?"); + int nRet = KMessageBox::warningYesNo(this, str, QString::null, i18n("Create Archive"), i18n("Do Not Create")); + if (nRet == KMessageBox::Yes) // yes + { + file_new(); + if (isArchiveOpen()) // they still could have canceled! + { + addFile( &list ); + } + } + // else // basically a cancel on the drop. + } + } +} + +void +ArkWidget::startDrag( const QStringList & fileList ) +{ + mDragFiles = fileList; + connect( arch, SIGNAL( sigExtract( bool ) ), this, SLOT( startDragSlotExtractDone( bool ) ) ); + prepareViewFiles( fileList ); +} + +void +ArkWidget::startDragSlotExtractDone( bool ) +{ + disconnect( arch, SIGNAL( sigExtract( bool ) ), + this, SLOT( startDragSlotExtractDone( bool ) ) ); + + KURL::List list; + + for (QStringList::Iterator it = mDragFiles.begin(); it != mDragFiles.end(); ++it) + { + KURL url; + url.setPath( tmpDir() + *it ); + list.append( url ); + } + + KURLDrag *drg = new KURLDrag(list, m_fileListView->viewport(), "Ark Archive Drag" ); + m_bDropSourceIsSelf = true; + drg->dragCopy(); + m_bDropSourceIsSelf = false; +} + + +void +ArkWidget::arkWarning(const QString& msg) +{ + KMessageBox::information(this, msg); +} + +void +ArkWidget::createFileListView() +{ + kdDebug(1601) << "ArkWidget::createFileListView" << endl; + if ( !m_fileListView ) + { + m_fileListView = new FileListView(this); + + connect( m_fileListView, SIGNAL( selectionChanged() ), + this, SLOT( slotSelectionChanged() ) ); + connect( m_fileListView, SIGNAL( rightButtonPressed(QListViewItem *, const QPoint &, int) ), + this, SLOT(doPopup(QListViewItem *, const QPoint &, int))); + connect( m_fileListView, SIGNAL( startDragRequest( const QStringList & ) ), + this, SLOT( startDrag( const QStringList & ) ) ); + connect( m_fileListView, SIGNAL( executed(QListViewItem *, const QPoint &, int ) ), + this, SLOT( viewFile(QListViewItem*) ) ); + connect( m_fileListView, SIGNAL( returnPressed(QListViewItem * ) ), + this, SLOT( viewFile(QListViewItem*) ) ); + } + m_fileListView->clear(); +} + + +Arch * ArkWidget::getNewArchive( const QString & _fileName, const QString& _mimetype ) +{ + Arch * newArch = 0; + + QString type = _mimetype.isNull()? KMimeType::findByURL( KURL::fromPathOrURL(_fileName) )->name() : _mimetype; + ArchType archtype = ArchiveFormatInfo::self()->archTypeForMimeType(type); + kdDebug( 1601 ) << "archtype is recognised as: " << archtype << endl; + if(0 == (newArch = Arch::archFactory(archtype, this, + _fileName, _mimetype))) + { + KMessageBox::error(this, i18n("Unknown archive format or corrupted archive") ); + emit request_file_quit(); + return NULL; + } + + if (!newArch->archUtilityIsAvailable()) + { + KMessageBox::error(this, i18n("The utility %1 is not in your PATH.\nPlease install it or contact your system administrator.").arg(newArch->getArchUtility())); + return NULL; + } + + connect( newArch, SIGNAL(headers(const ColumnList&)), + m_fileListView, SLOT(setHeaders(const ColumnList&))); + + m_archType = archtype; + m_fileListView->setUpdatesEnabled(true); + return newArch; +} + +////////////////////////////////////////////////////////////////////// +////////////////////// createArchive ///////////////////////////////// +////////////////////////////////////////////////////////////////////// + + +bool +ArkWidget::createArchive( const QString & _filename ) +{ + Arch * newArch = getNewArchive( _filename ); + if ( !newArch ) + return false; + + busy( i18n( "Creating archive..." ) ); + connect( newArch, SIGNAL(sigCreate(Arch *, bool, const QString &, int) ), + this, SLOT(slotCreate(Arch *, bool, const QString &, int) ) ); + + newArch->create(); + return true; +} + +void +ArkWidget::slotCreate(Arch * _newarch, bool _success, const QString & _filename, int) +{ + kdDebug( 1601 ) << k_funcinfo << endl; + disconnect( _newarch, SIGNAL( sigCreate( Arch *, bool, const QString &, int ) ), + this, SLOT(slotCreate(Arch *, bool, const QString &, int) ) ); + ready(); + if ( _success ) + { + //file_close(); already called in ArkWidget::file_new() + m_strArchName = _filename; + // for the hack in compressedfile; needed when creating a compressedfile + // then directly adding a file + KURL u; + u.setPath( _filename ); + setRealURL( u ); + + emit setWindowCaption( _filename ); + emit addRecentURL( u ); + createFileListView(); + m_fileListView->show(); + m_bIsArchiveOpen = true; + arch = _newarch; + m_bIsSimpleCompressedFile = + (m_archType == COMPRESSED_FORMAT); + fixEnables(); + } + else + { + KMessageBox::error(this, i18n("An error occurred while trying to create the archive.") ); + } + emit createDone( _success ); +} + +////////////////////////////////////////////////////////////////////// +//////////////////////// openArchive ///////////////////////////////// +////////////////////////////////////////////////////////////////////// + +void +ArkWidget::openArchive( const QString & _filename ) +{ + Arch *newArch = 0; + ArchType archtype; + ArchiveFormatInfo * info = ArchiveFormatInfo::self(); + if ( m_openAsMimeType.isNull() ) + { + archtype = info->archTypeForURL( m_url ); + if ( info->wasUnknownExtension() ) + { + ArchiveFormatDlg * dlg = new ArchiveFormatDlg( this, info->findMimeType( m_url ) ); + if ( !dlg->exec() == QDialog::Accepted ) + { + emit setWindowCaption( QString::null ); + emit removeRecentURL( m_realURL ); + delete dlg; + file_close(); + return; + } + m_openAsMimeType = dlg->mimeType(); + archtype = info->archTypeForMimeType( m_openAsMimeType ); + delete dlg; + } + } + else + { + archtype = info->archTypeForMimeType( m_openAsMimeType ); + } + + kdDebug( 1601 ) << "m_openAsMimeType is: " << m_openAsMimeType << endl; + if( 0 == ( newArch = Arch::archFactory( archtype, this, + _filename, m_openAsMimeType) ) ) + { + emit setWindowCaption( QString::null ); + emit removeRecentURL( m_realURL ); + KMessageBox::error( this, i18n("Unknown archive format or corrupted archive") ); + return; + } + + if (!newArch->unarchUtilityIsAvailable()) + { + KMessageBox::error(this, i18n("The utility %1 is not in your PATH.\nPlease install it or contact your system administrator.").arg(newArch->getUnarchUtility())); + return; + } + + m_archType = archtype; + + connect( newArch, SIGNAL(sigOpen(Arch *, bool, const QString &, int)), + this, SLOT(slotOpen(Arch *, bool, const QString &,int)) ); + connect( newArch, SIGNAL(headers(const ColumnList&)), + m_fileListView, SLOT(setHeaders(const ColumnList&))); + + disableAll(); + + busy( i18n( "Opening the archive..." ) ); + m_fileListView->setUpdatesEnabled( false ); + arch = newArch; + newArch->open(); + emit addRecentURL( m_url ); +} + +void +ArkWidget::slotOpen( Arch * /* _newarch */, bool _success, const QString & _filename, int ) +{ + ready(); + m_fileListView->setUpdatesEnabled(true); + m_fileListView->triggerUpdate(); + + m_fileListView->show(); + + if ( _success ) + { + QFileInfo fi( _filename ); + QString path = fi.dirPath( true ); + + if ( !fi.isWritable() ) + { + arch->setReadOnly(true); + KMessageBox::information(this, i18n("This archive is read-only. If you want to save it under a new name, go to the File menu and select Save As."), i18n("Information"), "ReadOnlyArchive"); + } + updateStatusTotals(); + m_bIsArchiveOpen = true; + m_bIsSimpleCompressedFile = ( m_archType == COMPRESSED_FORMAT ); + + if ( m_extractOnly ) + { + extractOnlyOpenDone(); + return; + } + m_fileListView->adjustColumns(); + emit addOpenArk( _filename ); + } + else + { + emit removeRecentURL( m_realURL ); + emit setWindowCaption( QString::null ); + KMessageBox::error( this, i18n( "An error occurred while trying to open the archive %1" ).arg( _filename ) ); + + if ( m_extractOnly ) + emit request_file_quit(); + } + + fixEnables(); + emit openDone( _success ); +} + + +void ArkWidget::slotShowSearchBarToggled( bool b ) +{ + if ( b ) + { + m_searchToolBar->show(); + ArkSettings::setShowSearchBar( true ); + } + else + { + m_searchToolBar->hide(); + ArkSettings::setShowSearchBar( false ); + } +} + +/** + * Show Settings dialog. + */ +void ArkWidget::showSettings(){ + if(KConfigDialog::showDialog("settings")) + return; + + KConfigDialog *dialog = new KConfigDialog(this, "settings", ArkSettings::self()); + + General* genPage = new General(0, "General"); + dialog->addPage(genPage, i18n("General"), "ark", i18n("General Settings")); + dialog->addPage(new Addition(0, "Addition"), i18n("Addition"), "ark_addfile", i18n("File Addition Settings")); + dialog->addPage(new Extraction(0, "Extraction"), i18n("Extraction"), "ark_extract", i18n("Extraction Settings")); + + KTrader::OfferList offers; + + offers = KTrader::self()->query( "KonqPopupMenu/Plugin", "Library == 'libarkplugin'" ); + + if ( offers.isEmpty() ) + genPage->kcfg_KonquerorIntegration->setEnabled( false ); + else + genPage->konqIntegrationLabel->setText( QString::null ); + + dialog->show(); +} + +#include "arkwidget.moc" diff --git a/ark/arkwidget.h b/ark/arkwidget.h new file mode 100644 index 0000000..d64bbd0 --- /dev/null +++ b/ark/arkwidget.h @@ -0,0 +1,318 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2003: Georg Robbers + 2002: Helio Chissini de Castro + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1997-1999: Rob Palmbos palm9744@kettering.edu + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef ARKWIDGET_H +#define ARKWIDGET_H + +#include +#include + +#include +#include "arch.h" + +class QPoint; +class QString; +class QStringList; +class QLabel; +class QListViewItem; +class QDragMoveEvent; +class QDropEvent; + +class KPopupMenu; +class KProcess; +class KURL; +class KRun; +class KTempFile; +class KTempDir; +class KToolBar; + +class FileListView; +class SearchBar; + + +class ArkWidget : public QVBox +{ + Q_OBJECT +public: + ArkWidget( QWidget *parent=0, const char *name=0 ); + virtual ~ArkWidget(); + + bool isArchiveOpen() const { return m_bIsArchiveOpen; } + int getNumFilesInArchive() const { return m_nNumFiles; } + + int getArkInstanceId() const { return m_arkInstanceId; } + void setArkInstanceId( int aid ) { m_arkInstanceId = aid; } + + void cleanArkTmpDir(); + virtual QString getArchName() const { return m_strArchName; } + + const KURL& realURL() const { return m_realURL; } + void setRealURL( const KURL& url ) { m_realURL = url; } + + QString tmpDir() const { return m_tmpDir ? m_tmpDir->name() : QString::null; } + + FileListView * fileList() const { return m_fileListView; } + SearchBar * searchBar() const { return m_searchBar; } + Arch * archive() const { return arch; } + ArchType archiveType() const { return m_archType; } + int numSelectedFiles() const { return m_nNumSelectedFiles; } + + /** + * Miscellaneous tasks involved in closing an archive. + */ + void closeArch(); + + virtual void setExtractOnly(bool extOnly) { m_extractOnly = extOnly; } + virtual void deleteAfterUse( const QString& path ); + bool allowedArchiveName( const KURL & u ); + bool file_save_as( const KURL & u ); + virtual KURL getSaveAsFileName(); + virtual void setOpenAsMimeType( const QString & mimeType ); + QString & openAsMimeType(){ return m_openAsMimeType; } + void prepareViewFiles( const QStringList & fileList ); + virtual void setArchivePopupEnabled( bool b ); + + virtual void extractTo( const KURL & targetDirectory, const KURL & archive, bool bGuessName ); + virtual bool addToArchive( const KURL::List & filesToAdd, const KURL & archive = KURL() ); + void convertTo( const KURL & u ); + + bool isModified() { return m_modified; } + void setModified( bool b ) { m_modified = b; } + +public slots: + void file_open( const KURL& url); + virtual void file_close(); + virtual void file_new(); + void slotShowSearchBarToggled( bool b ); + void showSettings(); + +protected slots: + void action_add(); + void action_add_dir(); + void action_view(); + void action_delete(); + bool action_extract(); + void slotOpenWith(); + void action_edit(); + + void doPopup(QListViewItem *, const QPoint &, int); // right-click menus + void viewFile(QListViewItem*); // doubleClick view files + + void slotSelectionChanged(); + void slotOpen(Arch *, bool, const QString &, int); + void slotCreate(Arch *, bool, const QString &, int); + void slotDeleteDone(bool); + void slotExtractDone(bool); + void slotExtractRemoteDone(KIO::Job *job); + void slotAddDone(bool); + void slotEditFinished(KProcess *); +signals: + void openURLRequest( const KURL & url ); + void request_file_quit(); + void setBusy( const QString & ); + void setReady(); + void fixActions(); + void disableAllActions(); + void signalFilePopup( const QPoint & pPoint ); + void signalArchivePopup( const QPoint & pPoint ); + void setStatusBarText( const QString & text ); + void setStatusBarSelectedFiles( const QString & text ); + void removeRecentURL( const KURL & url ); + void addRecentURL( const KURL & url ); + void setWindowCaption( const QString &caption ); + void removeOpenArk( const KURL & ); + void addOpenArk( const KURL & ); + void createDone( bool ); + void openDone( bool ); + void createRealArchiveDone( bool ); + void extractRemoteMovingDone(); + +protected: + + // DND + void dragMoveEvent(QDragMoveEvent *e); + void dropEvent(QDropEvent* event); + void dropAction(QStringList & list); + +private: // methods + // disabling/enabling of buttons and menu items + void fixEnables(); + + // disable all (temporarily, during operations) + void disableAll(); + void updateStatusSelection(); + void updateStatusTotals(); + void addFile(QStringList *list); + void removeDownloadedFiles(); + + // make sure that str is a local file/dir + KURL toLocalFile(const KURL& url); + + // ask user whether to create a real archive from a compressed file + // returns filename if so. Otherwise, empty. + KURL askToCreateRealArchive(); + Arch * getNewArchive( const QString & _fileName, const QString& _mimetype = QString() ); + void createRealArchive( const QString &strFilename, + const QStringList & filesToAdd = QStringList() ); + KURL getCreateFilename( const QString & _caption, + const QString & _defaultMimeType = QString::null, + bool allowCompressed = true, + const QString & _suggestedName = QString::null ); + + bool reportExtractFailures(const QString & _dest, QStringList *_list); + QStringList existingFiles( const QString & _dest, QStringList & _list ); + + void extractOnlyOpenDone(); + void extractRemoteInitiateMoving( const KURL & target ); + void editStart(); + + void busy( const QString & text ); + void holdBusy(); + void resumeBusy(); + void ready(); + + //suggests an extract directory based on archive name + const QString guessName( const KURL & archive ); + +private slots: + void startDrag( const QStringList & fileList ); + void startDragSlotExtractDone( bool ); + void editSlotExtractDone(); + void editSlotAddDone( bool success ); + void viewSlotExtractDone( bool success ); + void openWithSlotExtractDone( bool success ); + + void createRealArchiveSlotCreate( Arch * newArch, bool success, + const QString & fileName, int nbr ); + void createRealArchiveSlotAddDone( bool success ); + void createRealArchiveSlotAddFilesDone( bool success ); + + void convertSlotExtractDone( bool success ); + void convertSlotCreate(); + void convertSlotCreateDone( bool success ); + void convertSlotAddDone( bool success ); + void convertFinish(); + + void extractToSlotOpenDone( bool success ); + void extractToSlotExtractDone( bool success ); + + void addToArchiveSlotOpenDone( bool success ); + void addToArchiveSlotCreateDone( bool success ); + void addToArchiveSlotAddDone( bool success ); + +protected: + void arkWarning(const QString& msg); + void arkError(const QString& msg); + + void newCaption(const QString& filename); + void createFileListView(); + + bool createArchive(const QString & name); + void openArchive(const QString & name); + + void showCurrentFile(); + +private: // data + + bool m_bBusy; + bool m_bBusyHold; + + // for use in the edit methods: the url. + QString m_strFileToView; + + // the compressed file to be added into the new archive + QString m_compressedFile; + + // Set to true if we are doing an "Extract to Folder" + bool m_extractOnly; + + // Set to true if we are extracting to a remote location + bool m_extractRemote; + + // URL to extract to. + KURL m_extractURL; + + // URL to view + KURL m_viewURL; + + // the mimetype the user wants to open this archive as + QString m_openAsMimeType; + + // if they're dragging in files, this is the temporary list for when + // we have to create an archive: + QStringList *m_pTempAddList; + + KRun *m_pKRunPtr; + + QStringList mpDownloadedList; + + bool m_bArchivePopupEnabled; + + KTempDir * m_convert_tmpDir; + KURL m_convert_saveAsURL; + bool m_convertSuccess; + + KURL m_extractTo_targetDirectory; + + KURL::List m_addToArchive_filesToAdd; + KURL m_addToArchive_archive; + + KTempDir * m_createRealArchTmpDir; + KTempDir * m_extractRemoteTmpDir; + + bool m_modified; + + KToolBar * m_searchToolBar; + SearchBar * m_searchBar; + + Arch * arch; + QString m_strArchName; + KURL m_realURL; + KURL m_url; + ArchType m_archType; + FileListView * m_fileListView; + + KIO::filesize_t m_nSizeOfFiles; + KIO::filesize_t m_nSizeOfSelectedFiles; + unsigned int m_nNumFiles; + int m_nNumSelectedFiles; + int m_arkInstanceId; + + bool m_bIsArchiveOpen; + bool m_bIsSimpleCompressedFile; + bool m_bDropSourceIsSelf; + + QStringList mDragFiles; + QStringList *m_extractList; + QStringList *m_viewList; + KTempDir *m_tmpDir; +}; + +#endif /* ARKWIDGET_H*/ + diff --git a/ark/common_texts.cpp b/ark/common_texts.cpp new file mode 100644 index 0000000..cc64b82 --- /dev/null +++ b/ark/common_texts.cpp @@ -0,0 +1,35 @@ +i18n(" Filename ") +i18n(" Permissions ") +i18n(" Owner/Group ") +i18n(" Size ") +i18n(" Timestamp ") +i18n(" Link ") +i18n(" Size Now ") +i18n(" Ratio ") +i18n("acronym for Cyclic Redundancy Check"," CRC ") +i18n(" Method ") +i18n(" Version ") +i18n(" Owner ") +i18n(" Group ") +i18n("(used as part of a sentence)","start-up folder") +i18n("folder for opening files (used as part of a sentence)","open folder") +i18n("folder for extracting files (used as part of a sentence)","extract folder") +i18n("folder for adding files (used as part of a sentence)","add folder") + +i18n("Settings") +i18n("&Adding") +i18n("&Extracting") +i18n("&Folders") +i18n("Add Settings") +i18n("Extract Settings") +i18n("Replace &old files only with newer files") +i18n("Keep entries &generic (Lha)") +i18n("Force &MS-DOS short filenames (Zip)") +i18n("Translate LF to DOS &CRLF (Zip)") +i18n("&Recursively add subfolders (Zip, Rar)") +i18n("&Store symlinks as links (Zip, Rar)") +i18n("O&verwrite files (Zip, Tar, Zoo, Rar)") +i18n("&Preserve permissions (Tar)") +i18n("&Ignore folder names (Zip)") +i18n("Convert filenames to &lowercase (Zip, Rar)") +i18n("Convert filenames to &uppercase (Rar)") diff --git a/ark/compressedfile.cpp b/ark/compressedfile.cpp new file mode 100644 index 0000000..9ebe283 --- /dev/null +++ b/ark/compressedfile.cpp @@ -0,0 +1,376 @@ +/* + ark: A program for modifying archives via a GUI. + + Copyright (C) + + 2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + 2003: Georg Robbers + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +// C includes +#include +#include +#include + +// Qt includes +#include + +// KDE includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ark includes +#include "arkwidget.h" +#include "filelistview.h" +#include "compressedfile.h" + +// encapsulates the idea of a compressed file + +CompressedFile::CompressedFile( ArkWidget *_gui, const QString & _fileName, const QString & _openAsMimeType ) + : Arch( _gui, _fileName ) +{ + m_tempDirectory = NULL; + m_openAsMimeType = _openAsMimeType; + kdDebug(1601) << "CompressedFile constructor" << endl; + m_tempDirectory = new KTempDir( _gui->tmpDir() + + QString::fromLatin1( "compressed_file_temp" ) ); + m_tempDirectory->setAutoDelete( true ); + m_tmpdir = m_tempDirectory->name(); + initData(); + verifyCompressUtilityIsAvailable( m_archiver_program ); + verifyUncompressUtilityIsAvailable( m_unarchiver_program ); + + if (!QFile::exists(_fileName)) + { + KMessageBox::information(0, + i18n("You are creating a simple compressed archive which contains only one input file.\n" + "When uncompressed, the file name will be based on the name of the archive file.\n" + "If you add more files you will be prompted to convert it to a real archive."), + i18n("Simple Compressed Archive"), "CreatingCompressedArchive"); + } +} + +CompressedFile::~CompressedFile() +{ + if ( m_tempDirectory ) + delete m_tempDirectory; +} + +void CompressedFile::setHeaders() +{ + ColumnList list; + list.append(FILENAME_COLUMN); + list.append(PERMISSION_COLUMN); + list.append(OWNER_COLUMN); + list.append(GROUP_COLUMN); + list.append(SIZE_COLUMN); + + emit headers(list); +} + +void CompressedFile::initData() +{ + m_unarchiver_program = QString::null; + m_archiver_program = QString::null; + + QString mimeType; + if ( !m_openAsMimeType.isNull() ) + mimeType = m_openAsMimeType; + else + mimeType = KMimeType::findByPath( m_filename )->name(); + + if ( mimeType == "application/x-gzip" ) + { + m_unarchiver_program = "gunzip"; + m_archiver_program = "gzip"; + m_defaultExtensions << ".gz" << "-gz" << ".z" << "-z" << "_z" << ".Z"; + } + if ( mimeType == "application/x-bzip" ) + { + m_unarchiver_program = "bunzip"; + m_archiver_program = "bzip"; + m_defaultExtensions << ".bz"; + } + if ( mimeType == "application/x-bzip2" ) + { + m_unarchiver_program = "bunzip2"; + m_archiver_program = "bzip2"; + m_defaultExtensions << ".bz2" << ".bz"; + } + if ( mimeType == "application/x-lzop" ) + { m_unarchiver_program = "lzop"; + m_archiver_program = "lzop"; + m_defaultExtensions << ".lzo"; + } + if ( mimeType == "application/x-compress" ) + { + m_unarchiver_program = KGlobal::dirs()->findExe( "uncompress" ).isNull()? "gunzip" : "uncompress"; + m_archiver_program = "compress"; + m_defaultExtensions = ".Z"; + } + +} + +QString CompressedFile::extension() +{ + QStringList::Iterator it = m_defaultExtensions.begin(); + for( ; it != m_defaultExtensions.end(); ++it ) + if( m_filename.endsWith( *it ) ) + return QString::null; + return m_defaultExtensions.first(); +} + +void CompressedFile::open() +{ + kdDebug(1601) << "+CompressedFile::open" << endl; + setHeaders(); + + // We copy the file into the temporary directory, uncompress it, + // and when the uncompression is done, list it + // (that code is in the slot slotOpenDone) + + m_tmpfile = m_gui->realURL().fileName(); + if ( m_tmpfile.isEmpty() ) + m_tmpfile = m_filename; + m_tmpfile += extension(); + m_tmpfile = m_tmpdir + m_tmpfile; + + KURL src, target; + src.setPath( m_filename ); + target.setPath( m_tmpfile ); + + KIO::NetAccess::copy( src, target, m_gui ); + kdDebug(1601) << "Temp file name is " << target << endl; + + if ( !KIO::NetAccess::exists( target, true, NULL ) ) + return; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + *kp << m_unarchiver_program << "-f" ; + if ( m_unarchiver_program == "lzop") + { + *kp << "-d"; + // lzop hack, see comment in tar.cpp createTmp() + kp->setUsePty( KProcess::Stdin, false ); + } + // gunzip 1.3 seems not to like original names with directories in them + // testcase: https://listman.redhat.com/pipermail/valhalla-list/2006-October.txt.gz + /*if ( m_unarchiver_program == "gunzip" ) + *kp << "-N"; + */ + *kp << m_tmpfile; + + kdDebug(1601) << "Command is " << m_unarchiver_program << " " << m_tmpfile<< endl; + + connect( kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + connect( kp, SIGNAL(processExited(KProcess*)), this, + SLOT(slotUncompressDone(KProcess*))); + + if (kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + emit sigOpen(this, false, QString::null, 0 ); + } + + kdDebug(1601) << "-CompressedFile::open" << endl; +} + +void CompressedFile::slotUncompressDone(KProcess *_kp) +{ + bool bSuccess = false; + kdDebug(1601) << "normalExit = " << _kp->normalExit() << endl; + if( _kp->normalExit() ) + kdDebug(1601) << "exitStatus = " << _kp->exitStatus() << endl; + + if( _kp->normalExit() && (_kp->exitStatus()==0) ) + { + bSuccess = true; + } + + delete _kp; + _kp = m_currentProcess = 0; + + if ( !bSuccess ) + { + emit sigOpen( this, false, QString::null, 0 ); + return; + } + + QDir dir( m_tmpdir ); + QStringList lst( dir.entryList() ); + lst.remove( ".." ); + lst.remove( "." ); + KURL url; + url.setPath( m_tmpdir + lst.first() ); + m_tmpfile = url.path(); + KIO::UDSEntry udsInfo; + KIO::NetAccess::stat( url, udsInfo, m_gui ); + KFileItem fileItem( udsInfo, url ); + QStringList list; + list << fileItem.name(); + list << fileItem.permissionsString(); + list << fileItem.user(); + list << fileItem.group(); + list << KIO::number( fileItem.size() ); + m_gui->fileList()->addItem(list); // send to GUI + + emit sigOpen( this, bSuccess, m_filename, + Arch::Extract | Arch::Delete | Arch::Add | Arch::View ); +} + +void CompressedFile::create() +{ + emit sigCreate(this, true, m_filename, + Arch::Extract | Arch::Delete | Arch::Add + | Arch::View); +} + +void CompressedFile::addFile( const QStringList &urls ) +{ + // only used for adding ONE file to an EMPTY gzip file, i.e., one that + // has just been created + + kdDebug(1601) << "+CompressedFile::addFile" << endl; + + Q_ASSERT(m_gui->getNumFilesInArchive() == 0); + Q_ASSERT(urls.count() == 1); + + KURL url = KURL::fromPathOrURL(urls.first()); + Q_ASSERT(url.isLocalFile()); + + QString file; + file = url.path(); + + KProcess proc; + proc << "cp" << file << m_tmpdir; + proc.start(KProcess::Block); + + m_tmpfile = file.right(file.length() + - file.findRev("/")-1); + m_tmpfile = m_tmpdir + '/' + m_tmpfile; + + kdDebug(1601) << "Temp file name is " << m_tmpfile << endl; + + kdDebug(1601) << "File is " << file << endl; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + // lzop hack, see comment in tar.cpp createTmp() + if ( m_archiver_program == "lzop") + kp->setUsePty( KProcess::Stdin, false ); + + QString compressor = m_archiver_program; + + *kp << compressor << "-c" << file; + + connect( kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotAddInProgress(KProcess*, char*, int))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + connect( kp, SIGNAL(processExited(KProcess*)), this, + SLOT(slotAddDone(KProcess*))); + + int f_desc = KDE_open(QFile::encodeName(m_filename), O_CREAT | O_TRUNC | O_WRONLY, 0666); + if (f_desc != -1) + fd = fdopen( f_desc, "w" ); + else + fd = NULL; + + if (kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + } + + kdDebug(1601) << "-CompressedFile::addFile" << endl; +} + +void CompressedFile::slotAddInProgress(KProcess*, char* _buffer, int _bufflen) +{ + // we're trying to capture the output of a command like this + // gzip -c myfile + // and feed the output to the compressed file + int size; + size = fwrite(_buffer, 1, _bufflen, fd); + if (size != _bufflen) + { + KMessageBox::error(0, i18n("Trouble writing to the archive...")); + exit(99); + } +} + +void CompressedFile::slotAddDone(KProcess *_kp) +{ + fclose(fd); + slotAddExited(_kp); +} + +void CompressedFile::unarchFileInternal() +{ + if (m_destDir != m_tmpdir) + { + QString dest; + if (m_destDir.isEmpty() || m_destDir.isNull()) + { + kdError(1601) << "There was no extract directory given." << endl; + return; + } + else + dest=m_destDir; + + KProcess proc; + proc << "cp" << m_tmpfile << dest; + proc.start(KProcess::Block); + } + emit sigExtract(true); +} + +void CompressedFile::remove(QStringList *) +{ + kdDebug(1601) << "+CompressedFile::remove" << endl; + QFile::remove(m_tmpfile); + + // do not delete but truncate the compressed file in case someone + // does a reload and finds it no longer exists! + truncate(QFile::encodeName(m_filename), 0); + + m_tmpfile = ""; + emit sigDelete(true); + kdDebug(1601) << "-CompressedFile::remove" << endl; +} + + + +#include "compressedfile.moc" + diff --git a/ark/compressedfile.h b/ark/compressedfile.h new file mode 100644 index 0000000..ceaee6c --- /dev/null +++ b/ark/compressedfile.h @@ -0,0 +1,86 @@ +/* + + ark: A program for modifying archives via a GUI. + + Copyright (C) + + 2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +#ifndef COMPRESSED_FILE_H +#define COMPRESSED_FILE_H + +class QString; +class QCString; +class QStringList; +class KProcess; +class KTempDir; + +class Arch; +class ArkWidget; + +// This isn't *really* an archive, but having this class in the program +// allows people to manage gzipped files if they want. If someone tries to +// add a file, the gz-file must be empty (hozat? it could be empty by having +// just been created). Otherwise, the user will be asked to create a REAL +// archive, and then the added file(s) and the original file will be +// transferred to the new archive. +// +class CompressedFile : public Arch +{ + Q_OBJECT +public: + CompressedFile( ArkWidget *_gui, const QString & _fileName, const QString &_openAsMimeType ); + virtual ~CompressedFile(); + + virtual void open(); + virtual void create(); + + virtual void addFile( const QStringList& ); + virtual void addDir(const QString &) { } + + virtual void remove(QStringList *); + virtual void unarchFileInternal(); + + QString tempFileName(){ return m_tmpfile; } + +private slots: + void slotUncompressDone(KProcess *); + void slotAddInProgress(KProcess*, char*, int); + void slotAddDone(KProcess*); + +private: + void initExtract( bool, bool, bool ); + void setHeaders(); + void initData(); + QString extension(); + + QString m_openAsMimeType; + KTempDir * m_tempDirectory; + QString m_tmpdir; + QString m_tmpfile; + QStringList m_defaultExtensions; + + // for use with addFile + FILE *fd; + +}; + + + +#endif // COMPRESSED_FILE_H diff --git a/ark/configure.in.in b/ark/configure.in.in new file mode 100644 index 0000000..e0e280a --- /dev/null +++ b/ark/configure.in.in @@ -0,0 +1,11 @@ +AC_CHECK_KDEMAXPATHLEN + +KDE_CHECK_FUNC_EXT(statfs, [ +#include +], [ + char buffer[200]; + struct statfs b; + statfs(buffer, &b); +], [ + int statfs(const char *path, struct statfs *buffer) +], [STATFS]) diff --git a/ark/extraction.ui b/ark/extraction.ui new file mode 100644 index 0000000..692692f --- /dev/null +++ b/ark/extraction.ui @@ -0,0 +1,79 @@ + +Extraction + + + Extraction + + + + 0 + 0 + 436 + 289 + + + + + unnamed + + + + kcfg_extractOverwrite + + + O&verwrite files (Zip, Tar, Zoo, Rar) + + + + + kcfg_preservePerms + + + &Preserve permissions (Tar) + + + + + kcfg_extractJunkPaths + + + &Ignore folder names (Zip) + + + + + kcfg_rarToLower + + + Convert file names to &lowercase (Zip, Rar) + + + + + kcfg_rarToUpper + + + Convert file names to &uppercase (Rar) + + + + + spacer3 + + + Vertical + + + Expanding + + + + 20 + 20 + + + + + + + diff --git a/ark/extractiondialog.cpp b/ark/extractiondialog.cpp new file mode 100644 index 0000000..7892efb --- /dev/null +++ b/ark/extractiondialog.cpp @@ -0,0 +1,195 @@ +/* + * ark -- archiver for the KDE project + * + * Copyright (C) + * + * 2005: Henrique Pinto + * 2002: Helio Chissini de Castro + * 2001: Roberto Selbach Teixeira + * 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + * 1999-2000: Corel Corporation (author: Emily Ezust emilye@corel.com) + * 1999: Francois-Xavier Duranceau duranceau@kde.org + * 1997-1999: Rob Palmbos palm9744@kettering.edu + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "extractiondialog.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "arkutils.h" +#include "settings.h" + +ExtractionDialog::ExtractionDialog( QWidget *parent, const char *name, + bool enableSelected, + const KURL& defaultExtractionDir, + const QString &prefix, + const QString &archiveName ) + : KDialogBase( parent, name, true, i18n( "Extract" ), Ok | Cancel, Ok ), + m_selectedButton( 0 ), m_allButton( 0 ), + m_selectedOnly( enableSelected ), m_extractionDirectory( defaultExtractionDir ), + m_defaultExtractionDir( defaultExtractionDir.prettyURL() ), m_prefix( prefix ) +{ + if ( !archiveName.isNull() ) + { + setCaption( i18n( "Extract Files From %1" ).arg( archiveName ) ); + } + + QVBox *vbox = makeVBoxMainWidget(); + + QHBox *header = new QHBox( vbox ); + header->layout()->setSpacing( 10 ); + + QLabel *icon = new QLabel( header ); + icon->setPixmap( DesktopIcon( "ark_extract" ) ); + icon->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ); + + if ( enableSelected ) + { + QVBox *whichFiles = new QVBox( header ); + whichFiles->layout()->setSpacing( 6 ); + new QLabel( QString( "%1" ) + .arg( i18n( "Extract:" ) ), whichFiles ); + QHButtonGroup *filesGroup = new QHButtonGroup( whichFiles ); + m_selectedButton = new QRadioButton( i18n( "Selected files only" ), filesGroup ); + m_allButton = new QRadioButton( i18n( "All files" ), filesGroup ); + + m_selectedButton->setChecked( true ); + } + else + { + new QLabel( QString( "%1" ) + .arg( i18n( "Extract all files" ) ), header ); + } + + QHBox *destDirBox = new QHBox( vbox ); + + QLabel *destFolderLabel = new QLabel( i18n( "Destination folder: " ), destDirBox ); + destFolderLabel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ); + + KHistoryCombo *combobox = new KHistoryCombo( true, destDirBox ); + combobox->setPixmapProvider( new KURLPixmapProvider ); + combobox->setHistoryItems( ArkSettings::extractionHistory() ); + destFolderLabel->setBuddy( combobox ); + + KURLCompletion *comp = new KURLCompletion(); + comp->setReplaceHome( true ); + comp->setCompletionMode( KGlobalSettings::CompletionAuto ); + combobox->setCompletionObject( comp ); + combobox->setMaxCount( 20 ); + combobox->setInsertionPolicy( QComboBox::AtTop ); + + m_urlRequester = new KURLRequester( combobox, destDirBox ); + m_urlRequester->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + m_urlRequester->setMode( KFile::Directory ); + + if (!defaultExtractionDir.prettyURL().isEmpty() ) + { + m_urlRequester->setKURL( defaultExtractionDir.prettyURL() + prefix ); + } + + m_viewFolderAfterExtraction = new QCheckBox( i18n( "Open destination folder after extraction" ), vbox ); + m_viewFolderAfterExtraction->setChecked( ArkSettings::openDestinationFolder() ); + + connect( combobox, SIGNAL( returnPressed( const QString& ) ), combobox, SLOT( addToHistory( const QString& ) ) ); + connect( combobox->lineEdit(), SIGNAL( textChanged( const QString& ) ), + this, SLOT( extractDirChanged( const QString & ) ) ); +} + +ExtractionDialog::~ExtractionDialog() +{ + ArkSettings::setExtractionHistory( ( static_cast( m_urlRequester->comboBox() ) )->historyItems() ); +} + +void ExtractionDialog::accept() +{ + + KURLCompletion uc; + uc.setReplaceHome( true ); + KURL p( uc.replacedPath( m_urlRequester->comboBox()->currentText() ) ); + + //if p isn't local KIO and friends will complain later on + if ( p.isLocalFile() ) + { + QFileInfo fi( p.path() ); + if ( !fi.isDir() && !fi.exists() ) + { + QString ltext = i18n( "Create folder %1?").arg(p.path()); + int createDir = KMessageBox::questionYesNo( this, ltext, i18n( "Missing Folder" ) , i18n("Create Folder"), i18n("Do Not Create")); + if( createDir == 4 ) + { + return; + } + // create directory using filename, make sure it has trailing slash + p.adjustPath(1); + if( !KStandardDirs::makeDir( p.path() ) ) + { + KMessageBox::error( this, i18n( "The folder could not be created. Please check permissions." ) ); + return; + } + } + if ( !ArkUtils::haveDirPermissions( p.path() ) ) + { + KMessageBox::error( this, i18n( "You do not have write permission to this folder. Please provide another folder." ) ); + return; + } + } + + m_extractionDirectory = p; + m_selectedOnly = m_selectedButton == 0? false : m_selectedButton->isChecked(); + + // Determine what exactly should be added to the extraction combo list + QString historyURL = p.prettyURL(); + if ( historyURL == KURL( m_defaultExtractionDir + m_prefix ).prettyURL() ) + { + historyURL = m_defaultExtractionDir; + } + + KHistoryCombo *combo = static_cast( m_urlRequester->comboBox() ); + // If the item was already in the list, delete it from the list and readd it at the top + combo->removeFromHistory( historyURL ); + combo->addToHistory( historyURL ); + + ArkSettings::setOpenDestinationFolder( m_viewFolderAfterExtraction->isChecked() ); + + KDialogBase::accept(); +} + +void ExtractionDialog::extractDirChanged(const QString &text ) +{ + enableButtonOK(!text.isEmpty()); +} + +#include "extractiondialog.moc" +// kate: space-indent off; tab-width 4; diff --git a/ark/extractiondialog.h b/ark/extractiondialog.h new file mode 100644 index 0000000..822c085 --- /dev/null +++ b/ark/extractiondialog.h @@ -0,0 +1,97 @@ +/* + * ark -- archiver for the KDE project + * + * Copyright (C) + * + * 1997-1999: Rob Palmbos palm9744@kettering.edu + * 1999: Francois-Xavier Duranceau duranceau@kde.org + * 1999-2000: Corel Corporation (author: Emily Ezust emilye@corel.com) + * 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + * 2001: Roberto Selbach Teixeira (maragato@conectiva.com) + * 2005: Henrique Pinto ( henrique.pinto@kdemail.net ) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef EXTRACTIONDIALOG_H +#define EXTRACTIONDIALOG_H + +#include + +#include +#include + +class QRadioButton; + +class KURLRequester; + +class ExtractionDialog : public KDialogBase +{ + Q_OBJECT + public: + /** + * Constructor. + */ + ExtractionDialog( QWidget *parent = 0, const char *name = 0, + bool enableSelected = true, + const KURL &defaultExtractionDir = KURL(), + const QString &prefix = QString(), + const QString &archiveName = QString::null ); + + /** + * Destructor. + */ + ~ExtractionDialog(); + + + + /** + * Returns true if the user wants to extract only the selected files + */ + bool selectedOnly() const { return m_selectedOnly; } + + /** + * Returns the directory the files should be extracted to. + */ + KURL extractionDirectory() const { return m_extractionDirectory; } + + /** + * Returns true if the user wants the extraction folder to be opened after extraction + */ + bool viewFolderAfterExtraction() const { return m_viewFolderAfterExtraction->isChecked(); } + + + + public slots: + void accept(); + void extractDirChanged( const QString & ); + + + + private: + QRadioButton *m_selectedButton; + QRadioButton *m_allButton; + QCheckBox *m_viewFolderAfterExtraction; + bool m_selectedOnly; + KURL m_extractionDirectory; + KURLRequester *m_urlRequester; + QString m_defaultExtractionDir; + QString m_prefix; +}; + +#endif // EXTRACTIONDIALOG_H +// kate: space-indent off; tab-width 4; + diff --git a/ark/filelistview.cpp b/ark/filelistview.cpp new file mode 100644 index 0000000..3668d11 --- /dev/null +++ b/ark/filelistview.cpp @@ -0,0 +1,587 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2005: Henrique Pinto + 2003: Georg Robbers + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 1999: Francois-Xavier Duranceau duranceau@kde.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +// Qt includes +#include +#include +#include + +// KDE includes +#include +#include +#include +#include +#include + +#include "filelistview.h" +#include "arch.h" + +///////////////////////////////////////////////////////////////////// +// FileLVI implementation +///////////////////////////////////////////////////////////////////// + +FileLVI::FileLVI( KListView* lv ) + : KListViewItem( lv ), m_fileSize( 0 ), m_packedFileSize( 0 ), + m_ratio( 0 ), m_timeStamp( QDateTime() ), m_entryName( QString() ) +{ + +} + +FileLVI::FileLVI( KListViewItem* lvi ) + : KListViewItem( lvi ), m_fileSize( 0 ), m_packedFileSize( 0 ), + m_ratio( 0 ), m_timeStamp( QDateTime() ), m_entryName( QString() ) +{ +} + +QString FileLVI::key( int column, bool ascending ) const +{ + if ( column == 0 ) + return fileName(); + else + return QListViewItem::key( column, ascending ); +} + +int FileLVI::compare( QListViewItem * i, int column, bool ascending ) const +{ + FileLVI * item = static_cast< FileLVI * >( i ); + + if ( ( this->childCount() > 0 ) && ( item->childCount() == 0 ) ) + return -1; + + if ( ( this->childCount() == 0 ) && ( item->childCount() > 0 ) ) + return 1; + + if ( column == 0 ) + return KListViewItem::compare( i, column, ascending ); + + columnName colName = ( static_cast< FileListView * > ( listView() ) )->nameOfColumn( column ); + switch ( colName ) + { + case sizeCol: + { + return ( m_fileSize < item->fileSize() ? -1 : + ( m_fileSize > item->fileSize() ? 1 : 0 ) + ); + break; + } + + case ratioStrCol: + { + return ( m_ratio < item->ratio() ? -1 : + ( m_ratio > item->ratio() ? 1 : 0 ) + ); + break; + } + + case packedStrCol: + { + return ( m_packedFileSize < item->packedFileSize() ? -1 : + ( m_packedFileSize > item->packedFileSize() ? 1 : 0 ) + ); + break; + } + + case timeStampStrCol: + { + return ( m_timeStamp < item->timeStamp() ? -1 : + ( m_timeStamp > item->timeStamp() ? 1 : 0 ) + ); + break; + } + + default: + return KListViewItem::compare( i, column, ascending ); + } +} + +void FileLVI::setText( int column, const QString &text ) +{ + columnName colName = ( static_cast< FileListView * > ( listView() ) )->nameOfColumn( column ); + if ( column == 0 ) + { + QString name = text; + if ( name.endsWith( "/" ) ) + name = name.left( name.length() - 1 ); + if ( name.startsWith( "/" ) ) + name = name.mid( 1 ); + int pos = name.findRev( '/' ); + if ( pos != -1 ) + name = name.right( name.length() - pos - 1 ); + QListViewItem::setText( column, name ); + m_entryName = text; + } + else if ( colName == sizeCol ) + { + m_fileSize = text.toULongLong(); + QListViewItem::setText( column, KIO::convertSize( m_fileSize ) ); + } + else if ( colName == packedStrCol ) + { + m_packedFileSize = text.toULongLong(); + QListViewItem::setText( column, KIO::convertSize( m_packedFileSize ) ); + } + else if ( colName == ratioStrCol ) + { + int l = text.length() - 1; + if ( l>0 && text[l] == '%' ) + m_ratio = text.left(l).toDouble(); + else + m_ratio = text.toDouble(); + QListViewItem::setText( column, i18n( "Packed Ratio", "%1 %" ) + .arg(KGlobal::locale()->formatNumber( m_ratio, 1 ) ) + ); + } + else if ( colName == timeStampStrCol ) + { + if ( text.isEmpty() ) + QListViewItem::setText(column, text); + else + { + m_timeStamp = QDateTime::fromString( text, ISODate ); + QListViewItem::setText( column, KGlobal::locale()->formatDateTime( m_timeStamp ) ); + } + } + else + QListViewItem::setText(column, text); +} + +static FileLVI* folderLVI( KListViewItem *parent, const QString& name ) +{ + FileLVI *folder = new FileLVI( parent ); + + folder->setText( 0, name ); + + folder->setPixmap( 0, KMimeType::mimeType( "inode/directory" )->pixmap( KIcon::Small ) ); + + return folder; +} + +static FileLVI* folderLVI( KListView *parent, const QString& name ) +{ + FileLVI *folder = new FileLVI( parent ); + folder->setText( 0, name ); + folder->setPixmap( 0, KMimeType::mimeType( "inode/directory" )->pixmap( KIcon::Small ) ); + return folder; +} + +///////////////////////////////////////////////////////////////////// +// FileListView implementation +///////////////////////////////////////////////////////////////////// + + +FileListView::FileListView(QWidget *parent, const char* name) + : KListView(parent, name) +{ + QWhatsThis::add( this, + i18n( "This area is for displaying information about the files contained within an archive." ) + ); + + setMultiSelection( true ); + setSelectionModeExt( FileManager ); + setItemsMovable( false ); + setRootIsDecorated( true ); + setShowSortIndicator( true ); + setItemMargin( 3 ); + header()->hide(); // Don't show the header until there is something to be shown in it + + m_pressed = false; +} + +int FileListView::addColumn ( const QString & label, int width ) +{ + int index = KListView::addColumn( label, width ); + if ( label == SIZE_COLUMN.first ) + { + m_columnMap[ index ] = sizeCol; + } + else if ( label == PACKED_COLUMN.first ) + { + m_columnMap[ index ] = packedStrCol; + } + else if ( label == RATIO_COLUMN.first ) + { + m_columnMap[ index ] = ratioStrCol; + } + else if ( label == TIMESTAMP_COLUMN.first ) + { + m_columnMap[ index ] = timeStampStrCol; + } + else + { + m_columnMap[ index ] = otherCol; + } + return index; +} + +void FileListView::removeColumn( int index ) +{ + for ( unsigned int i = index; i < m_columnMap.count() - 2; i++ ) + { + m_columnMap.replace( i, m_columnMap[ i + 1 ] ); + } + + m_columnMap.remove( m_columnMap[ m_columnMap.count() - 1 ] ); + KListView::removeColumn( index ); +} + +columnName FileListView::nameOfColumn( int index ) +{ + return m_columnMap[ index ]; +} + +QStringList FileListView::selectedFilenames() +{ + QStringList files; + + FileLVI *item = static_cast( firstChild() ); + + while ( item ) + { + if ( item->isSelected() ) + { + // If the item has children, add each child and the item + if ( item->childCount() > 0 ) + { + files += item->fileName(); + files += childrenOf( item ); + + /* If we got here, then the logic for "going to the next item" + * is a bit different: as we already dealt with all the children, + * the "next item" is the next sibling of the current item, not + * its first child. If the current item has no siblings, then + * the next item is the next sibling of its parent, and so on. + */ + FileLVI *nitem = static_cast( item->nextSibling() ); + while ( !nitem && item->parent() ) + { + item = static_cast( item->parent() ); + if ( item->parent() ) + nitem = static_cast( item->parent()->nextSibling() ); + } + item = nitem; + continue; + } + else + { + // If the item has no children, just add it to the list + files += item->fileName(); + } + } + // Go to the next item + item = static_cast( item->itemBelow() ); + } + + return files; +} + +QStringList FileListView::fileNames() +{ + QStringList files; + + QListViewItemIterator it( this ); + while ( it.current() ) + { + FileLVI *item = static_cast( it.current() ); + files += item->fileName(); + ++it; + } + + return files; +} + +bool FileListView::isSelectionEmpty() +{ + FileLVI * flvi = (FileLVI*)firstChild(); + + while (flvi) + { + if( flvi->isSelected() ) + return false; + else + flvi = (FileLVI*)flvi->itemBelow(); + } + return true; +} + +void +FileListView::contentsMousePressEvent(QMouseEvent *e) +{ + if( e->button()==QMouseEvent::LeftButton ) + { + m_pressed = true; + m_presspos = e->pos(); + } + + KListView::contentsMousePressEvent(e); +} + +void +FileListView::contentsMouseReleaseEvent(QMouseEvent *e) +{ + m_pressed = false; + KListView::contentsMouseReleaseEvent(e); +} + +void +FileListView::contentsMouseMoveEvent(QMouseEvent *e) +{ + if(!m_pressed) + { + KListView::contentsMouseMoveEvent(e); + } + else if( ( m_presspos - e->pos() ).manhattanLength() > KGlobalSettings::dndEventDelay() ) + { + m_pressed = false; // Prevent triggering again + if(isSelectionEmpty()) + { + return; + } + QStringList dragFiles = selectedFilenames(); + emit startDragRequest( dragFiles ); + KListView::contentsMouseMoveEvent(e); + } +} + +FileLVI* +FileListView::item(const QString& filename) const +{ + FileLVI * flvi = (FileLVI*) firstChild(); + + while (flvi) + { + QString curFilename = flvi->fileName(); + if (curFilename == filename) + return flvi; + flvi = (FileLVI*) flvi->nextSibling(); + } + + return 0; +} + +void FileListView::addItem( const QStringList & entries ) +{ + FileLVI *flvi, *parent = findParent( entries[0] ); + if ( parent ) + flvi = new FileLVI( parent ); + else + flvi = new FileLVI( this ); + + + int i = 0; + + for (QStringList::ConstIterator it = entries.begin(); it != entries.end(); ++it) + { + flvi->setText(i, *it); + ++i; + } + + KMimeType::Ptr mimeType = KMimeType::findByPath( entries.first(), 0, true ); + flvi->setPixmap( 0, mimeType->pixmap( KIcon::Small ) ); +} + +void FileListView::selectAll() +{ + QListView::selectAll( true ); +} + +void FileListView::unselectAll() +{ + QListView::selectAll( false ); +} + +void FileListView::setHeaders( const ColumnList& columns ) +{ + clearHeaders(); + + for ( ColumnList::const_iterator it = columns.constBegin(); + it != columns.constEnd(); + ++it ) + { + QPair< QString, Qt::AlignmentFlags > pair = *it; + int colnum = addColumn( pair.first ); + setColumnAlignment( colnum, pair.second ); + } + + setResizeMode( QListView::LastColumn ); + + header()->show(); +} + +void FileListView::clearHeaders() +{ + header()->hide(); + while ( columns() > 0 ) + { + removeColumn( 0 ); + } +} + +int FileListView::totalFiles() +{ + int numFiles = 0; + + QListViewItemIterator it( this ); + while ( it.current() ) + { + if ( it.current()->childCount() == 0 ) + ++numFiles; + ++it; + } + + return numFiles; +} + +int FileListView::selectedFilesCount() +{ + int numFiles = 0; + + QListViewItemIterator it( this, QListViewItemIterator::Selected ); + while ( it.current() ) + { + ++numFiles; + ++it; + } + + return numFiles; +} + +KIO::filesize_t FileListView::totalSize() +{ + KIO::filesize_t size = 0; + + QListViewItemIterator it(this); + while ( it.current() ) + { + FileLVI *item = static_cast( it.current() ); + size += item->fileSize(); + ++it; + } + + return size; +} + +KIO::filesize_t FileListView::selectedSize() +{ + KIO::filesize_t size = 0; + + QListViewItemIterator it( this, QListViewItemIterator::Selected ); + while ( it.current() ) + { + FileLVI *item = static_cast( it.current() ); + size += item->fileSize(); + ++it; + } + + return size; +} + +FileLVI* FileListView::findParent( const QString& fullname ) +{ + QString name = fullname; + + if ( name.endsWith( "/" ) ) + name = name.left( name.length() -1 ); + if ( name.startsWith( "/" ) ) + name = name.mid( 1 ); + // Checks if this entry needs a parent + if ( !name.contains( '/' ) ) + return static_cast< FileLVI* >( 0 ); + + // Get a list of ancestors + QString parentFullname = name.left( name.findRev( '/' ) ); + QStringList ancestorList = QStringList::split( '/', parentFullname ); + + // Checks if the listview contains the first item in the list of ancestors + QListViewItem *item = firstChild(); + while ( item ) + { + if ( item->text( 0 ) == ancestorList[0] ) + break; + item = item->nextSibling(); + } + + // If the list view does not contain the item, create it + if ( !item ) + { + item = folderLVI( this, ancestorList[0] ); + } + + // We've already dealt with the first item, remove it + ancestorList.pop_front(); + + while ( ancestorList.count() > 0 ) + { + QString name = ancestorList[0]; + + FileLVI *parent = static_cast< FileLVI*>( item ); + item = parent->firstChild(); + while ( item ) + { + if ( item->text(0) == name ) + break; + item = item->nextSibling(); + } + + if ( !item ) + { + item = folderLVI( parent, name ); + } + + ancestorList.pop_front(); + } + + item->setOpen( true ); + return static_cast< FileLVI* >( item ); +} + +QStringList FileListView::childrenOf( FileLVI* parent ) +{ + Q_ASSERT( parent ); + QStringList children; + + FileLVI *item = static_cast( parent->firstChild() ); + + while ( item ) + { + if ( item->childCount() == 0 ) + { + children += item->fileName(); + } + else + { + children += item->fileName(); + children += childrenOf( item ); + } + item = static_cast( item->nextSibling() ); + } + + return children; +} + +#include "filelistview.moc" +// kate: space-indent off; tab-width 4; diff --git a/ark/filelistview.h b/ark/filelistview.h new file mode 100644 index 0000000..8ea0d48 --- /dev/null +++ b/ark/filelistview.h @@ -0,0 +1,163 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + 2003: Georg Robbers + 2005: Henrique Pinto + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +#ifndef FILELISTVIEW_H +#define FILELISTVIEW_H + +#include +#include +#include + +#include +#include + +class QString; +class QStringList; +class QRect; +class QPainter; +class QColorGroup; +class QMouseEvent; +class QPoint; + +enum columnName { sizeCol = 1 , packedStrCol, ratioStrCol, timeStampStrCol, otherCol }; + +class FileLVI : public KListViewItem +{ + public: + FileLVI( KListView* lv ); + FileLVI( KListViewItem* lvi ); + + QString fileName() const { return m_entryName; } + KIO::filesize_t fileSize() const { return m_fileSize; } + KIO::filesize_t packedFileSize() const { return m_packedFileSize; } + double ratio() const { return m_ratio; } + QDateTime timeStamp() const { return m_timeStamp; } + + int compare ( QListViewItem * i, int col, bool ascending ) const; + virtual QString key( int column, bool ) const; + virtual void setText( int column, const QString &text ); + + private: + KIO::filesize_t m_fileSize; + KIO::filesize_t m_packedFileSize; + double m_ratio; + QDateTime m_timeStamp; + QString m_entryName; +}; + +typedef QValueList< QPair< QString, Qt::AlignmentFlags > > ColumnList; + +class FileListView: public KListView +{ + Q_OBJECT + public: + FileListView( QWidget *parent = 0, const char* name = 0 ); + + FileLVI *currentItem() {return ((FileLVI *) KListView::currentItem());} + + /** + * Returns the full names of the selected files. + */ + QStringList selectedFilenames(); + + /** + * Return the full names of all files. + */ + QStringList fileNames(); + + /** + * Returns true if no file is selected + */ + bool isSelectionEmpty(); + + virtual int addColumn( const QString & label, int width = -1 ); + virtual void removeColumn( int index ); + columnName nameOfColumn( int index ); + + /** + * Returns the file item, or 0 if not found. + * @param filename The filename in question to reference in the archive + * @return The requested file's FileLVI + */ + FileLVI* item(const QString& filename) const; + + /** + * Adds a file and stats to the file listing + * @param entries A stringlist of the entries for each column of the list. + */ + void addItem( const QStringList & entries ); + + /** + * Returns the number of files in the archive. + */ + int totalFiles(); + + /** + * Returns the number of selected files. + */ + int selectedFilesCount(); + + /** + * Return the sum of the sizes of all files in the archive. + */ + KIO::filesize_t totalSize(); + + /** + * Return the sum of the sizes of the selected files. + */ + KIO::filesize_t selectedSize(); + + /** + * Adjust the size of all columns to fit their content. + */ + void adjustColumns() { for ( int i = 0; i < columns(); ++i ) adjustColumn( i ); } + + public slots: + void selectAll(); + void unselectAll(); + void setHeaders( const ColumnList& columns ); + void clearHeaders(); + + signals: + void startDragRequest( const QStringList & fileList ); + + protected: + virtual void contentsMouseReleaseEvent( QMouseEvent *e ); + virtual void contentsMousePressEvent( QMouseEvent *e ); + virtual void contentsMouseMoveEvent( QMouseEvent *e ); + + private: + FileLVI* findParent( const QString& fullname ); + QStringList childrenOf( FileLVI* parent ); + + QMap m_columnMap; + bool m_pressed; + QPoint m_presspos; // this will save the click pos to correctly recognize drag events +}; + +#endif +// kate: space-indent off; tab-width 4; diff --git a/ark/general.ui b/ark/general.ui new file mode 100644 index 0000000..d822b4c --- /dev/null +++ b/ark/general.ui @@ -0,0 +1,93 @@ + +General + + + General + + + + 0 + 0 + 323 + 251 + + + + General + + + + unnamed + + + + kcfg_UseIntegratedViewer + + + &Use integrated viewer + + + + + kcfg_KonquerorIntegration + + + &Enable Konqueror integration + + + + + layout1 + + + + unnamed + + + + spacer2 + + + Horizontal + + + Fixed + + + + 15 + 31 + + + + + + konqIntegrationLabel + + + <font size="-1"><i>Konqueror integration is only available if you install the Konqueror integration plugin from the kdeaddons package.</i></font> + + + + + + + spacer1 + + + Vertical + + + Expanding + + + + 20 + 90 + + + + + + + diff --git a/ark/hi128-app-ark.png b/ark/hi128-app-ark.png new file mode 100644 index 0000000..874d332 Binary files /dev/null and b/ark/hi128-app-ark.png differ diff --git a/ark/hi16-app-ark.png b/ark/hi16-app-ark.png new file mode 100644 index 0000000..07391b6 Binary files /dev/null and b/ark/hi16-app-ark.png differ diff --git a/ark/hi22-app-ark.png b/ark/hi22-app-ark.png new file mode 100644 index 0000000..859b325 Binary files /dev/null and b/ark/hi22-app-ark.png differ diff --git a/ark/hi32-app-ark.png b/ark/hi32-app-ark.png new file mode 100644 index 0000000..2b00cc4 Binary files /dev/null and b/ark/hi32-app-ark.png differ diff --git a/ark/hi48-app-ark.png b/ark/hi48-app-ark.png new file mode 100644 index 0000000..89f9723 Binary files /dev/null and b/ark/hi48-app-ark.png differ diff --git a/ark/hi64-app-ark.png b/ark/hi64-app-ark.png new file mode 100644 index 0000000..7f3809b Binary files /dev/null and b/ark/hi64-app-ark.png differ diff --git a/ark/hisc-app-ark.svgz b/ark/hisc-app-ark.svgz new file mode 100644 index 0000000..ec03594 Binary files /dev/null and b/ark/hisc-app-ark.svgz differ diff --git a/ark/lha.cpp b/ark/lha.cpp new file mode 100644 index 0000000..f890139 --- /dev/null +++ b/ark/lha.cpp @@ -0,0 +1,302 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 1997-1999: Rob Palmbos palm9744@kettering.edu + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include + +// C includes +#include +#include +#include +#include +#include + +// QT includes +#include +#include + +// KDE includes +#include +#include +#include +#include + +// ark includes +#include "arkwidget.h" +#include "settings.h" +#include "arch.h" +#include "lha.h" +#include "arkutils.h" +#include "filelistview.h" + +LhaArch::LhaArch( ArkWidget *_gui, const QString & _fileName ) + : Arch( _gui, _fileName ) +{ + m_archiver_program = "lha"; + verifyCompressUtilityIsAvailable( m_archiver_program ); + + m_headerString = "----"; +} + +bool LhaArch::processLine( const QCString &line ) +{ + const char *_line = ( const char * ) line; + char columns[13][80]; + char filename[4096]; + + if ( line.contains( "[generic]" ) ) + { + sscanf( _line, + " %79[]\\[generic] %79[0-9] %79[0-9] %79[0-9.%*] %10[-a-z0-9 ] %3[A-Za-z]%1[ ]%2[0-9 ]%1[ ]%5[ 0-9:]%1[ ]%4095[^\n]", + columns[0], columns[2], columns[3], columns[4], columns[5], + columns[6], columns[10], columns[7], columns[11], columns[8], + columns[9], filename ); + strcpy( columns[1], " " ); + } + else if ( line.contains( "[MS-DOS]" ) ) + { + sscanf( _line, + " %79[]\\[MS-DOS] %79[0-9] %79[0-9] %79[0-9.%*] %10[-a-z0-9 ] %3[A-Za-z]%1[ ]%2[0-9 ]%1[ ]%5[ 0-9:]%1[ ]%4095[^\n]", + columns[0], columns[2], columns[3], columns[4], columns[5], + columns[6], columns[10], columns[7], columns[11], columns[8], + columns[9], filename ); + strcpy( columns[1], " " ); + } + else + { + sscanf( _line, + " %79[-drlwxst] %79[0-9/] %79[0-9] %79[0-9] %79[0-9.%*] %10[-a-z0-9 ] %3[A-Za-z]%1[ ]%2[0-9 ]%1[ ]%5[ 0-9:]%1[ ]%4095[^\n]", + columns[0], columns[1], columns[2], columns[3], + columns[4], columns[5], columns[6], columns[10], columns[7], + columns[11], columns[8], columns[9], filename ); + } + + // make the time stamp sortable + QString massagedTimeStamp = ArkUtils::getTimeStamp( columns[6], columns[7], + columns[8] ); + strlcpy( columns[6], massagedTimeStamp.ascii(), sizeof( columns[6] ) ); + + // see if there was a link in filename + QString file = filename; + QString name, link; + bool bLink = false; + int pos = file.find( " -> " ); + if ( pos != -1 ) + { + bLink = true; + name = file.left(pos); + link = file.right(file.length()-pos-4); + } + else + { + name = file; + } + + QStringList list; + list.append( name ); + + for ( int i = 0; i < 7; i++ ) + { + list.append( QString::fromLocal8Bit( columns[i] ) ); + } + + if ( bLink ) + list.append( link ); + else + list.append( "" ); + + m_gui->fileList()->addItem( list ); // send to GUI + + return true; +} + +void LhaArch::open() +{ + setHeaders(); + + m_buffer = ""; + m_header_removed = false; + m_finished = false; + + + KProcess *kp = m_currentProcess = new KProcess; + *kp << m_archiver_program << "v" << m_filename; + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedTOC(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotOpenExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigOpen( this, false, QString::null, 0 ); + } +} + +void LhaArch::setHeaders() +{ + ColumnList list; + list.append( FILENAME_COLUMN); + list.append( PERMISSION_COLUMN); + list.append( OWNER_GROUP_COLUMN); + list.append( PACKED_COLUMN); + list.append( SIZE_COLUMN); + list.append( RATIO_COLUMN); + list.append( CRC_COLUMN); + list.append( TIMESTAMP_COLUMN); + list.append( LINK_COLUMN); + emit headers( list ); +} + + +void LhaArch::create() +{ + emit sigCreate( this, true, m_filename, + Arch::Extract | Arch::Delete | Arch::Add | Arch::View ); +} + +void LhaArch::addDir( const QString & dirName ) +{ + if ( !dirName.isEmpty() ) + { + QStringList list; + list.append( dirName ); + addFile( list ); + } +} + +void LhaArch::addFile( const QStringList &urls ) +{ + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + *kp << m_archiver_program; + + QString strOptions; + if ( ArkSettings::replaceOnlyWithNewer() ) + strOptions = "u"; + else + strOptions = "a"; + + *kp << strOptions << m_filename; + + KURL url( urls.first() ); + QDir::setCurrent( url.directory() ); + + QStringList::ConstIterator iter; + for ( iter = urls.begin(); iter != urls.end(); ++iter ) + { + KURL fileURL( *iter ); + *kp << fileURL.fileName(); + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotAddExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigAdd( false ); + } +} + +void LhaArch::unarchFileInternal() +{ + // if _fileList is empty, we extract all. + // if _destDir is empty, abort with error. + + if ( m_destDir.isEmpty() || m_destDir.isNull() ) + { + kdError( 1601 ) << "There was no extract directory given." << endl; + return; + } + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program << "xfw=" + m_destDir << m_filename; + + // if the list is empty, no filenames go on the command line, + // and we then extract everything in the archive. + if ( m_fileList ) + { + QStringList::Iterator it; + for ( it = m_fileList->begin(); it != m_fileList->end(); ++it ) + { + *kp << ( *it ); + } + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotExtractExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigExtract( false ); + } +} + +void LhaArch::remove( QStringList *list ) +{ + if ( !list ) + return; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program << "df" << m_filename; + + QStringList::Iterator it; + for ( it = list->begin(); it != list->end(); ++it ) + { + *kp << ( *it ); + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotDeleteExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigDelete( false ); + } +} + +#include "lha.moc" diff --git a/ark/lha.h b/ark/lha.h new file mode 100644 index 0000000..98041fb --- /dev/null +++ b/ark/lha.h @@ -0,0 +1,61 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 1997-1999: Rob Palmbos palm9744@kettering.edu + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +#ifndef LHA_H +#define LHA_H + +#include "arch.h" + +class QString; +class QCString; +class QStringList; + +class ArkWidget; + +class LhaArch : public Arch +{ + Q_OBJECT + public: + LhaArch( ArkWidget *, const QString & ); + virtual ~LhaArch() { } + + virtual void open(); + virtual void create(); + + virtual void addFile( const QStringList & ); + virtual void addDir( const QString & ); + + virtual void remove( QStringList * ); + virtual void unarchFileInternal(); + + protected slots: + virtual bool processLine( const QCString &line ); + + private: + void setHeaders(); +}; + +#endif // LHA_H diff --git a/ark/main.cpp b/ark/main.cpp new file mode 100644 index 0000000..a2156b4 --- /dev/null +++ b/ark/main.cpp @@ -0,0 +1,128 @@ +/* + +ark: A program for modifying archives via a GUI. + +Copyright (C) +2002-2003: Helio Chissini de Castro +2003: Georg Robbers +2001: Roberto Selbach Teixeira +1999-2000: Corel Corporation (author: Emily Ezust emilye@corel.com) +1999 Francois-Xavier Duranceau +1997-1999 Robert Palmbos + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +// +// Note: This is a KUniqueApplication. +// To debug add --nofork to the command line. +// Be aware that newInstance() will not be called in this case, but you +// can run ark from a console, and that will invoke it in the debugger. +// + +// C includes +#include + +// KDE includes +#include +#include +#include +#include +#include +// ark includes +#include "arkapp.h" + +static KCmdLineOptions option[] = +{ + { "extract", I18N_NOOP( "Open extract dialog, quit when finished" ), 0 }, + { "extract-to", I18N_NOOP( "Extract 'archive' to 'folder'. Quit when finished.\n" + "'folder' will be created if it does not exist."), 0 }, + { "add", I18N_NOOP( "Ask for the name of the archive to add 'files' to. Quit when finished." ), 0 }, + { "add-to", I18N_NOOP( "Add 'files' to 'archive'. Quit when finished.\n'archive' " + "will be created if it does not exist." ), 0 }, + { "guess-name", I18N_NOOP( "Used with '--extract-to'. When specified, 'archive'\n" + "will be extracted to a subfolder of 'folder'\n" + "whose name will be the name of 'archive' without the filename extension."), 0 }, + { "+[folder]", I18N_NOOP( "Folder to extract to" ), 0 }, + { "+[files]", I18N_NOOP( "Files to be added" ), 0 }, + { "+[archive]", I18N_NOOP( "Open 'archive'" ), 0 }, + KCmdLineLastOption +}; + +extern "C" KDE_EXPORT int kdemain( int argc, char *argv[] ) +{ + KAboutData aboutData( "ark", I18N_NOOP( "Ark" ), + "2.6.4", I18N_NOOP( "KDE Archiving tool" ), + KAboutData::License_GPL, + I18N_NOOP( "(c) 1997-2006, The Various Ark Developers" ) + ); + + aboutData.addAuthor( "Henrique Pinto", + I18N_NOOP( "Maintainer" ), + "henrique.pinto@kdemail.net" ); + aboutData.addAuthor( "Charis Kouzinopoulos", + 0, + "kouzinopoulos@gmail.com" ); + aboutData.addAuthor( "Helio Chissini de Castro", + I18N_NOOP( "Former maintainer" ), + "helio@kde.org" ); + aboutData.addAuthor( "Georg Robbers", + 0, + "Georg.Robbers@urz.uni-hd.de" ); + aboutData.addAuthor( "Roberto Selbach Teixeira", + 0, + "maragato@kde.org" ); + aboutData.addAuthor( "Francois-Xavier Duranceau", + 0, + "duranceau@kde.org" ); + aboutData.addAuthor( "Emily Ezust (Corel Corporation)", + 0, + "emilye@corel.com" ); + aboutData.addAuthor( "Michael Jarrett (Corel Corporation)", + 0, + "michaelj@corel.com" ); + aboutData.addAuthor( "Robert Palmbos", + 0, + "palm9744@kettering.edu" ); + + aboutData.addCredit( "Bryce Corkins", + I18N_NOOP( "Icons" ), + "dbryce@attglobal.net" ); + aboutData.addCredit( "Liam Smit", + I18N_NOOP( "Ideas, help with the icons" ), + "smitty@absamail.co.za" ); + + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( option ); + KCmdLineArgs::addTempFileOption(); + + if ( !ArkApplication::start() ) + { + // Already running! + kdDebug( 1601 ) << "Already running" << endl; + exit( 0 ); + } + + if ( ArkApplication::getInstance()->isRestored() ) + { + kdDebug( 1601 ) << "In main: Restore..." << endl; + RESTORE( MainWindow ); + } + + return ArkApplication::getInstance()->exec(); +} + +// kate: space-indent off; tab-width 4; diff --git a/ark/mainwindow.cpp b/ark/mainwindow.cpp new file mode 100644 index 0000000..b62422c --- /dev/null +++ b/ark/mainwindow.cpp @@ -0,0 +1,481 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) 2002-2003: Georg Robbers + Copyright (C) 2003: Helio Chissini de Castro + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +// QT includes +#include + +// KDE includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ark includes +#include "arkapp.h" +#include "settings.h" +#include "archiveformatinfo.h" +#include "arkwidget.h" + +MainWindow::MainWindow( QWidget * /*parent*/, const char *name ) + : KParts::MainWindow(), progressDialog( 0 ) +{ + setXMLFile( "arkui.rc" ); + m_part = KParts::ComponentFactory::createPartInstanceFromLibrary( "libarkpart", this, name, this, "ArkPart"); + if (m_part ) + { + //Since most of the functionality is still in ArkWidget: + m_widget = static_cast< ArkWidget* >( m_part->widget() ); + + setStandardToolBarMenuEnabled( true ); + setupActions(); + + connect( m_part->widget(), SIGNAL( request_file_quit() ), this, SLOT( file_quit() ) ); + connect( KParts::BrowserExtension::childObject( m_part ), SIGNAL( openURLRequestDelayed + ( const KURL &, const KParts::URLArgs & ) ), + m_part, SLOT( openURL( const KURL & ) ) ); + + m_widget->setArchivePopupEnabled( true ); + connect( m_part->widget(), SIGNAL( signalArchivePopup( const QPoint & ) ), this, + SLOT( slotArchivePopup( const QPoint & ) ) ); + + connect( m_part, SIGNAL( removeRecentURL( const KURL & ) ), this, + SLOT( slotRemoveRecentURL( const KURL & ) ) ); + connect( m_part, SIGNAL( addRecentURL( const KURL & ) ), this, + SLOT( slotAddRecentURL( const KURL & ) ) ); + connect( m_part, SIGNAL( fixActionState( const bool & ) ), this, + SLOT( slotFixActionState( const bool & ) ) ); + connect( m_widget, SIGNAL( disableAllActions() ), this, + SLOT( slotDisableActions() ) ); + + ArkApplication::getInstance()->addWindow(); + connect( m_widget, SIGNAL( removeOpenArk( const KURL &) ), this, + SLOT( slotRemoveOpenArk( const KURL & ) ) ); + connect( m_widget, SIGNAL( addOpenArk( const KURL & ) ), this, + SLOT( slotAddOpenArk( const KURL & ) ) ); + + setCentralWidget( m_part->widget() ); + createGUI( m_part ); + + if ( !initialGeometrySet() ) + { + resize( 640, 300 ); + } + setAutoSaveSettings( "MainWindow" ); + } + else + kdFatal( 1601 ) << "libark could not found. Aborting. " << endl; + +} + + + +MainWindow::~MainWindow() +{ + ArkApplication::getInstance()->removeWindow(); + delete m_part; + delete progressDialog; + progressDialog = 0; +} + +void +MainWindow::setupActions() +{ + newWindowAction = new KAction(i18n("New &Window"), "window_new", KShortcut(), this, + SLOT(file_newWindow()), actionCollection(), "new_window"); + + newArchAction = KStdAction::openNew(this, SLOT(file_new()), actionCollection()); + openAction = KStdAction::open(this, SLOT(file_open()), actionCollection()); + + reloadAction = new KAction(i18n("Re&load"), "reload", KStdAccel::shortcut( KStdAccel::Reload ), this, + SLOT(file_reload()), actionCollection(), "reload_arch"); + closeAction = KStdAction::close(this, SLOT(file_close()), actionCollection(), "file_close"); + + recent = KStdAction::openRecent(this, SLOT(openURL(const KURL&)), actionCollection()); + recent->loadEntries(kapp->config()); + + createStandardStatusBarAction(); + + KStdAction::quit(this, SLOT(window_close()), actionCollection()); + KStdAction::configureToolbars(this, SLOT(editToolbars()), actionCollection()); + KStdAction::keyBindings(this, SLOT( slotConfigureKeyBindings()), actionCollection()); + + openAction->setEnabled( true ); + recent->setEnabled( true ); + closeAction->setEnabled( false ); + reloadAction->setEnabled( false ); +} + +void +MainWindow::slotDisableActions() +{ + openAction->setEnabled(false); + newArchAction->setEnabled(false); + closeAction->setEnabled(false); + reloadAction->setEnabled(false); +} + +void +MainWindow::slotFixActionState( const bool & bHaveFiles ) +{ + openAction->setEnabled(true); + newArchAction->setEnabled(true); + closeAction->setEnabled(bHaveFiles); + reloadAction->setEnabled(bHaveFiles); +} + +void +MainWindow::file_newWindow() +{ + MainWindow *kw = new MainWindow; + kw->resize( 640, 300 ); + kw->show(); +} + +void +MainWindow::file_new() +{ + m_widget->file_new(); +} + +void +MainWindow::file_reload() +{ + KURL url( m_part->url() ); + file_close(); + m_part->openURL( url ); +} + +void +MainWindow::editToolbars() +{ + saveMainWindowSettings( KGlobal::config(), QString::fromLatin1("MainWindow") ); + KEditToolbar dlg( factory(), this ); + connect(&dlg, SIGNAL( newToolbarConfig() ), this, SLOT( slotNewToolbarConfig() )); + dlg.exec(); +} + +void +MainWindow::slotNewToolbarConfig() +{ + createGUI( m_part ); + applyMainWindowSettings( KGlobal::config(), QString::fromLatin1("MainWindow") ); +} + +void +MainWindow::slotConfigureKeyBindings() +{ + KKeyDialog dlg( true, this ); + + dlg.insert( actionCollection() ); + dlg.insert( m_part->actionCollection() ); + + dlg.configure(); +} + +void +MainWindow::slotArchivePopup( const QPoint &pPoint) +{ + static_cast(factory()->container("archive_popup", this))->popup(pPoint); +} + +// see if the ark is already open in another window +bool +MainWindow::arkAlreadyOpen( const KURL & url ) +{ + if (ArkApplication::getInstance()->isArkOpenAlready(url)) + { + if ( m_part->url() == url ) return true; + // raise the window containing the already open archive + ArkApplication::getInstance()->raiseArk(url); + + // close this window + window_close(); + + // notify the user what's going on + KMessageBox::information(0, i18n("The archive %1 is already open and has been raised.\nNote: if the filename does not match, it only means that one of the two is a symbolic link.").arg(url.prettyURL())); + return true; + } + return false; +} + + +void +MainWindow::openURL( const KURL & url, bool tempFile ) +{ + if( !arkAlreadyOpen( url ) ) + { + if ( tempFile && url.isLocalFile() ) + m_widget->deleteAfterUse( url.path() ); + m_part->openURL( url ); + } +} + +KURL +MainWindow::getOpenURL( bool addOnly, const QString & caption, + const QString & startDir, const QString & suggestedName ) +{ + kdDebug( 1601 ) << "startDir is: " << startDir << endl; + QWidget * forceFormatWidget = new QWidget( this ); + QHBoxLayout * l = new QHBoxLayout( forceFormatWidget ); + + QLabel * label = new QLabel( forceFormatWidget ); + label->setText( i18n( "Open &as:" ) ); + label->adjustSize(); + + KComboBox * combo = new KComboBox( forceFormatWidget ); + + QStringList list; + list = ArchiveFormatInfo::self()->allDescriptions(); + list.sort(); + list.prepend( i18n( "Autodetect (default)" ) ); + combo->insertStringList( list ); + + QString filter = ArchiveFormatInfo::self()->filter(); + if ( !suggestedName.isEmpty() ) + { + filter = QString::null; + combo->setCurrentItem( list.findIndex( ArchiveFormatInfo::self()->descriptionForMimeType( + KMimeType::findByPath( suggestedName, 0, true )->name() ) ) ); + } + + label->setBuddy( combo ); + + l->addWidget( label ); + l->addWidget( combo, 1 ); + + QString dir; + if ( addOnly ) + dir = startDir; + else + dir = ":ArkOpenDir"; + + KFileDialog dlg( dir, filter, this, "filedialog", true, forceFormatWidget ); + dlg.setOperationMode( addOnly ? KFileDialog::Saving + : KFileDialog::Opening ); + + dlg.setCaption( addOnly ? caption : i18n("Open") ); + dlg.setMode( addOnly ? ( KFile::File | KFile::ExistingOnly ) + : KFile::File ); + dlg.setSelection( suggestedName ); + + dlg.exec(); + + KURL url; + url = dlg.selectedURL(); + + if ( combo->currentItem() !=0 ) // i.e. != "Autodetect" + m_widget->setOpenAsMimeType( + ArchiveFormatInfo::self()->mimeTypeForDescription( combo->currentText() ) ); + else + m_widget->setOpenAsMimeType( QString::null ); + + return url; +} + +void +MainWindow::file_open() +{ + KURL url = getOpenURL(); + if( !arkAlreadyOpen( url ) ) + m_part->openURL( url ); +} + +void +MainWindow::file_close() +{ + m_part->closeURL(); +} + +void +MainWindow::window_close() +{ + file_close(); + slotSaveProperties(); + //kdDebug(1601) << "-ArkWidget::window_close" << endl; + close(); +} + +bool +MainWindow::queryClose() +{ + window_close(); + return true; +} + +void +MainWindow::file_quit() +{ + window_close(); +} + +void +MainWindow::slotSaveProperties() +{ + recent->saveEntries(kapp->config()); +} + +void +MainWindow::saveProperties( KConfig* config ) +{ + //TODO: make it work for URLS + config->writePathEntry( "SMOpenedFile",m_widget->getArchName() ); + config->sync(); +} + + +void +MainWindow::readProperties( KConfig* config ) +{ + QString file = config->readPathEntry("SMOpenedFile"); + kdDebug(1601) << "ArkWidget::readProperties( KConfig* config ) file=" << file << endl; + if ( !file.isEmpty() ) + openURL( KURL::fromPathOrURL( file ) ); +} + +void +MainWindow::slotAddRecentURL( const KURL & url ) +{ + recent->addURL( url ); + recent->saveEntries(kapp->config()); +} + +void +MainWindow::slotRemoveRecentURL( const KURL & url ) +{ + recent->removeURL( url ); + recent->saveEntries(kapp->config()); +} + +void +MainWindow::slotAddOpenArk( const KURL & _arkname ) +{ + ArkApplication::getInstance()->addOpenArk( _arkname, this ); +} + +void +MainWindow::slotRemoveOpenArk( const KURL & _arkname ) +{ + ArkApplication::getInstance()->removeOpenArk( _arkname ); +} + +void +MainWindow::setExtractOnly ( bool b ) +{ + m_widget->setExtractOnly( b ); +} + +void +MainWindow::extractTo( const KURL & targetDirectory, const KURL & archive, bool guessName ) +{ + startProgressDialog( i18n( "Extracting..." ) ); + m_widget->extractTo( targetDirectory, archive, guessName ); + m_part->openURL( archive ); +} + +void +MainWindow::addToArchive( const KURL::List & filesToAdd, const QString & /*cwd*/, + const KURL & archive, bool askForName ) +{ + KURL archiveFile; + if ( askForName || archive.isEmpty() ) + { + // user definded actions in servicemus are being started by konq + // from konqis working directory, not from the one being shown when + // the popupmenu was requested; work around that so the user + // sees a list of the archives in the diretory he is looking at. + // makes it show the 'wrong' dir when being called from the commandline + // like: /dira> ark -add /dirb/file, but well... + KURL cwdURL; + cwdURL.setPath( filesToAdd.first().path() ); + QString dir = cwdURL.directory( false ); + + archiveFile = getOpenURL( true, i18n( "Select Archive to Add Files To" ), + dir /*cwd*/, archive.fileName() ); + } + else + archiveFile = archive; + + if ( archiveFile.isEmpty() ) + { + kdDebug( 1601 ) << "no archive selected." << endl; + file_quit(); + return; + } + + startProgressDialog( i18n( "Compressing..." ) ); + + bool exists = KIO::NetAccess::exists( archiveFile, false, m_widget ); + kdDebug( 1601 ) << archiveFile << endl; + + if ( !m_widget->addToArchive( filesToAdd, archiveFile ) ) + file_quit(); + if ( exists ) + m_part->openURL( archiveFile ); +} + +void +MainWindow::startProgressDialog( const QString & text ) +{ + if ( !progressDialog ) + progressDialog = new KProgressDialog( this, "progress_dialog", QString::null, text, false ); + else + progressDialog->setLabel( text ); + +// progressDialog->setWFlags( Qt::WType_TopLevel ); + + progressDialog->setAllowCancel( true ); + progressDialog->setPlainCaption( i18n( "Please Wait" ) ); + + progressDialog->progressBar()->setTotalSteps( 0 ); + progressDialog->progressBar()->setPercentageVisible( false ); + +// progressDialog->setInitialSize( QSize(200,100), true ); + progressDialog->setMinimumDuration( 500 ); + progressDialog->show(); + KDialog::centerOnScreen( progressDialog ); + connect( progressDialog, SIGNAL( cancelClicked() ), this, SLOT( window_close() ) ); + + timer = new QTimer( this ); + connect( timer, SIGNAL( timeout() ), this, SLOT( slotProgress() ) ); + + timer->start( 200, false ); +} + +void +MainWindow::slotProgress() +{ + progressDialog->progressBar()->setProgress( progressDialog->progressBar()->progress() + 4 ); +} + + +#include "mainwindow.moc" + diff --git a/ark/mainwindow.h b/ark/mainwindow.h new file mode 100644 index 0000000..2d25ed0 --- /dev/null +++ b/ark/mainwindow.h @@ -0,0 +1,112 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) 2002-2003: Georg Robbers + Copyright (C) 2003: Helio Chissini de Castro + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef ARKMAINWINDOW_H +#define ARKMAINWINDOW_H + +// QT includes +#include +#include +#include + +// KDE includes +#include +#include +#include +#include + +class ArkWidget; + +class +MainWindow: public KParts::MainWindow +{ + Q_OBJECT +public: + MainWindow( QWidget *parent=0, const char *name=0 ); + virtual ~MainWindow(); + + void setExtractOnly ( bool b ); + void extractTo( const KURL & targetDirectory, const KURL & archive, bool guessName ); + void addToArchive( const KURL::List & filesToAdd, const QString & cwd = QString::null, + const KURL & archive = KURL(), bool askForName = false ); + +public slots: + void file_newWindow(); + void file_new(); + void openURL( const KURL & url, bool tempFile = false ); + void file_open(); + void file_reload(); + void editToolbars(); + void window_close(); + void file_quit(); + void file_close(); + void slotNewToolbarConfig(); + void slotConfigureKeyBindings(); + virtual void saveProperties( KConfig* config ); + virtual void readProperties( KConfig* config ); + void slotSaveProperties(); + void slotArchivePopup( const QPoint &pPoint); + void slotRemoveRecentURL( const KURL &url ); + void slotAddRecentURL( const KURL &url ); + void slotFixActionState( const bool & bHaveFiles ); + void slotDisableActions(); + void slotAddOpenArk( const KURL & _arkname ); + void slotRemoveOpenArk( const KURL & _arkname ); + +protected: + virtual bool queryClose(); // SM + +private: // methods + // disabling/enabling of buttons and menu items + void setupActions(); + void setupMenuBar(); + + void newCaption(const QString & filename); + bool arkAlreadyOpen( const KURL & url ); + + KURL getOpenURL( bool addOnly = false , const QString & caption = QString::null, + const QString & startDir = QString::null, + const QString & suggestedName = QString::null ); + + void startProgressDialog( const QString & text ); + +private slots: + void slotProgress(); + +private: // data + KParts::ReadWritePart *m_part; + ArkWidget *m_widget; //the parts widget + + KAction *newWindowAction; + KAction *newArchAction; + KAction *openAction; + KAction *closeAction; + KAction *reloadAction; + KRecentFilesAction *recent; + + //progress dialog for konqs service menus / commmand line + KProgressDialog *progressDialog; + QTimer *timer; +}; + +#endif /* ARKMAINWINDOW_H*/ diff --git a/ark/pics/Makefile.am b/ark/pics/Makefile.am new file mode 100644 index 0000000..fc447c5 --- /dev/null +++ b/ark/pics/Makefile.am @@ -0,0 +1,2 @@ +icondir = $(kde_datadir)/ark/icons +icon_ICON = AUTO diff --git a/ark/pics/cr22-action-ark_adddir.png b/ark/pics/cr22-action-ark_adddir.png new file mode 100644 index 0000000..e92bd63 Binary files /dev/null and b/ark/pics/cr22-action-ark_adddir.png differ diff --git a/ark/pics/cr22-action-ark_addfile.png b/ark/pics/cr22-action-ark_addfile.png new file mode 100644 index 0000000..8108fff Binary files /dev/null and b/ark/pics/cr22-action-ark_addfile.png differ diff --git a/ark/pics/cr22-action-ark_delete.png b/ark/pics/cr22-action-ark_delete.png new file mode 100644 index 0000000..4d60b28 Binary files /dev/null and b/ark/pics/cr22-action-ark_delete.png differ diff --git a/ark/pics/cr22-action-ark_extract.png b/ark/pics/cr22-action-ark_extract.png new file mode 100644 index 0000000..d82746d Binary files /dev/null and b/ark/pics/cr22-action-ark_extract.png differ diff --git a/ark/pics/cr22-action-ark_selectall.png b/ark/pics/cr22-action-ark_selectall.png new file mode 100644 index 0000000..677b116 Binary files /dev/null and b/ark/pics/cr22-action-ark_selectall.png differ diff --git a/ark/pics/cr22-action-ark_view.png b/ark/pics/cr22-action-ark_view.png new file mode 100644 index 0000000..77d8470 Binary files /dev/null and b/ark/pics/cr22-action-ark_view.png differ diff --git a/ark/pics/cr32-action-ark_adddir.png b/ark/pics/cr32-action-ark_adddir.png new file mode 100644 index 0000000..022438d Binary files /dev/null and b/ark/pics/cr32-action-ark_adddir.png differ diff --git a/ark/pics/cr32-action-ark_addfile.png b/ark/pics/cr32-action-ark_addfile.png new file mode 100644 index 0000000..a447f8c Binary files /dev/null and b/ark/pics/cr32-action-ark_addfile.png differ diff --git a/ark/pics/cr32-action-ark_delete.png b/ark/pics/cr32-action-ark_delete.png new file mode 100644 index 0000000..7b9e6fe Binary files /dev/null and b/ark/pics/cr32-action-ark_delete.png differ diff --git a/ark/pics/cr32-action-ark_extract.png b/ark/pics/cr32-action-ark_extract.png new file mode 100644 index 0000000..38913ec Binary files /dev/null and b/ark/pics/cr32-action-ark_extract.png differ diff --git a/ark/pics/cr32-action-ark_view.png b/ark/pics/cr32-action-ark_view.png new file mode 100644 index 0000000..f1bd613 Binary files /dev/null and b/ark/pics/cr32-action-ark_view.png differ diff --git a/ark/rar.cpp b/ark/rar.cpp new file mode 100644 index 0000000..592ffe2 --- /dev/null +++ b/ark/rar.cpp @@ -0,0 +1,306 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2003: Helio Chissini de Castro + 2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +// Std includes +#include +#include +#include +#include + +// QT includes +#include +#include + +// KDE includes +#include +#include +#include +#include +#include +#include + +// ark includes +#include +#include "arkwidget.h" +#include "arch.h" +#include "settings.h" +#include "rar.h" +#include "arkutils.h" +#include "filelistview.h" + +RarArch::RarArch( ArkWidget *_gui, const QString & _fileName ) + : Arch( _gui, _fileName ) +{ + // Check if rar is available + bool have_rar = !KGlobal::dirs()->findExe( "rar" ).isNull(); + + if ( have_rar ) + { + // If it is, then use it as archiver and unarchiver + m_archiver_program = m_unarchiver_program = "rar"; + verifyCompressUtilityIsAvailable( m_archiver_program ); + verifyUncompressUtilityIsAvailable( m_unarchiver_program ); + } + else + { + // If rar is not available, try to use unrar to open the archive read-only + m_unarchiver_program = "unrar"; + verifyUncompressUtilityIsAvailable( m_unarchiver_program ); + setReadOnly( true ); + } + + + + m_headerString = "-------------------------------------------------------------------------------"; + + m_isFirstLine = true; +} + +bool RarArch::processLine( const QCString &line ) +{ + if ( m_isFirstLine ) + { + m_entryFilename = QString::fromLocal8Bit( line ); + m_entryFilename.remove( 0, 1 ); + m_isFirstLine = false; + return true; + } + + QStringList list; + + QStringList l2 = QStringList::split( ' ', line ); + + list << m_entryFilename; // filename + list << l2[ 0 ]; // size + list << l2[ 1 ]; // packed + list << l2[ 2 ]; // ratio + + QStringList date = QStringList::split( '-', l2[ 3 ] ); + list << ArkUtils::fixYear( date[ 2 ].latin1() ) + '-' + date[ 1 ] + '-' + date [ 0 ] + ' ' + l2[4]; // date + list << l2[ 5 ]; // attributes + list << l2[ 6 ]; // crc + list << l2[ 7 ]; // method + list << l2[ 8 ]; // Version + + m_gui->fileList()->addItem( list ); // send to GUI + + m_isFirstLine = true; + return true; +} + +void RarArch::open() +{ + setHeaders(); + + m_buffer = ""; + m_header_removed = false; + m_finished = false; + + KProcess *kp = m_currentProcess = new KProcess; + *kp << m_unarchiver_program << "v" << "-c-" << m_filename; + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedTOC(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotOpenExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigOpen( this, false, QString::null, 0 ); + } +} + +void RarArch::setHeaders() +{ + ColumnList list; + list.append( FILENAME_COLUMN ); + list.append( SIZE_COLUMN ); + list.append( PACKED_COLUMN ); + list.append( RATIO_COLUMN ); + list.append( TIMESTAMP_COLUMN ); + list.append( PERMISSION_COLUMN ); + list.append( CRC_COLUMN ); + list.append( METHOD_COLUMN ); + list.append( VERSION_COLUMN ); + + emit headers( list ); +} + +void RarArch::create() +{ + emit sigCreate( this, true, m_filename, + Arch::Extract | Arch::Delete | Arch::Add | Arch::View ); +} + +void RarArch::addDir( const QString & _dirName ) +{ + if ( !_dirName.isEmpty() ) + { + QStringList list; + list.append( _dirName ); + addFile( list ); + } +} + +void RarArch::addFile( const QStringList & urls ) +{ + KProcess *kp = m_currentProcess = new KProcess; + + kp->clearArguments(); + *kp << m_archiver_program; + + if ( ArkSettings::replaceOnlyWithNewer() ) + *kp << "u"; + else + *kp << "a"; + + if ( ArkSettings::rarStoreSymlinks() ) + *kp << "-ol"; + if ( ArkSettings::rarRecurseSubdirs() ) + *kp << "-r"; + + *kp << m_filename; + + KURL dir( urls.first() ); + QDir::setCurrent( dir.directory() ); + + QStringList::ConstIterator iter; + for ( iter = urls.begin(); iter != urls.end(); ++iter ) + { + KURL url( *iter ); + *kp << url.fileName(); + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotAddExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigAdd( false ); + } +} + +void RarArch::unarchFileInternal() +{ + if ( m_destDir.isEmpty() || m_destDir.isNull() ) + { + kdError( 1601 ) << "There was no extract directory given." << endl; + return; + } + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + // extract (and maybe overwrite) + *kp << m_unarchiver_program << "x"; + + if ( !m_password.isEmpty() ) + *kp << "-p" + m_password; + else + *kp << "-p-"; + + if ( !ArkSettings::extractOverwrite() ) + { + *kp << "-o+"; + } + else + { + *kp << "-o-"; + } + + *kp << m_filename; + + // if the file list is empty, no filenames go on the command line, + // and we then extract everything in the archive. + if ( m_fileList ) + { + QStringList::Iterator it; + for ( it = m_fileList->begin(); it != m_fileList->end(); ++it ) + { + *kp << (*it); + } + } + + *kp << m_destDir ; + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotExtractExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigExtract( false ); + } +} + +bool RarArch::passwordRequired() +{ + return m_lastShellOutput.findRev("password incorrect ?)")+1; +} + +void RarArch::remove( QStringList *list ) +{ + if ( !list ) + return; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program << "d" << m_filename; + + QStringList::Iterator it; + for ( it = list->begin(); it != list->end(); ++it ) + { + QString str = *it; + *kp << str; + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotDeleteExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigDelete( false ); + } +} + +#include "rar.moc" diff --git a/ark/rar.h b/ark/rar.h new file mode 100644 index 0000000..d8a4ab4 --- /dev/null +++ b/ark/rar.h @@ -0,0 +1,68 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +#ifndef RAR_H +#define RAR_H + +#include "arch.h" + +class QString; +class QCString; +class QStringList; + +class ArkWidget; + +class RarArch : public Arch +{ + Q_OBJECT + public: + RarArch( ArkWidget *_gui, const QString & _fileName ); + virtual ~RarArch() {} + + virtual void open(); + virtual void create(); + + virtual void addFile( const QStringList & ); + virtual void addDir( const QString & ); + + virtual void remove( QStringList * ); + virtual void unarchFileInternal(); + virtual bool passwordRequired(); + + protected slots: + virtual bool processLine( const QCString & ); + + private: + void setHeaders(); + + /* + * The output of the rar command uses more than one + * line for each entry, the first containing the filename + * for the entry, the second containing additional information. + * Therefore, the variables below are needed. + */ + bool m_isFirstLine; + QString m_entryFilename; +}; + +#endif // RAR_H diff --git a/ark/searchbar.cpp b/ark/searchbar.cpp new file mode 100644 index 0000000..015a3bf --- /dev/null +++ b/ark/searchbar.cpp @@ -0,0 +1,49 @@ +/* + * ark: A program for modifying archives via a GUI. + * + * Copyright (C) 2004, Henrique Pinto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "searchbar.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +SearchBar::SearchBar( QWidget* parent, KActionCollection* aC, const char * name ) + : KListViewSearchLine( parent, 0, name ) +{ + KAction *resetSearch = new KAction( i18n( "Reset Search" ), QApplication::reverseLayout() ? "clear_left" : "locationbar_erase", 0, this, SLOT( clear() ), aC, "reset_search" ); + + resetSearch->plug( parent ); + resetSearch->setWhatsThis( i18n( "Reset Search\n" + "Resets the search bar, so that all archive entries are shown again." ) ); +} + +SearchBar::~SearchBar() +{ +} + +#include "searchbar.moc" diff --git a/ark/searchbar.h b/ark/searchbar.h new file mode 100644 index 0000000..95857ae --- /dev/null +++ b/ark/searchbar.h @@ -0,0 +1,40 @@ +#ifndef SEARCHBAR_H +#define SEARCHBAR_H +/* + * ark: A program for modifying archives via a GUI. + * + * Copyright (C) 2004, Henrique Pinto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include + +class KListView; +class KComboBox; +class KActionCollection; + +class SearchBar: public KListViewSearchLine +{ + Q_OBJECT + public: + SearchBar( QWidget* parent, KActionCollection* aC, const char * name = 0 ); + ~SearchBar(); +}; + +#endif // SEARCHBAR_H diff --git a/ark/settings.kcfgc b/ark/settings.kcfgc new file mode 100644 index 0000000..a8bc919 --- /dev/null +++ b/ark/settings.kcfgc @@ -0,0 +1,5 @@ +File=ark.kcfg +ClassName=ArkSettings +Singleton=true +Mutators=true +SetUserTexts=true diff --git a/ark/sevenzip.cpp b/ark/sevenzip.cpp new file mode 100644 index 0000000..30747a3 --- /dev/null +++ b/ark/sevenzip.cpp @@ -0,0 +1,367 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2004: Henrique Pinto + 2003: Helio Chissini de Castro + 2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "sevenzip.h" +#include "arkwidget.h" +#include "settings.h" +#include "arkutils.h" +#include "filelistview.h" + +SevenZipArch::SevenZipArch( ArkWidget *gui, const QString &filename ) + : Arch( gui, filename ), m_nameColumnPos( -1 ) +{ + // Check if 7z is available + bool have_7z = !KGlobal::dirs()->findExe( "7z" ).isNull(); + // Check if 7za is available + bool have_7za = !KGlobal::dirs()->findExe( "7za" ).isNull(); + + if ( have_7z ) + m_archiver_program = m_unarchiver_program = "7z"; // Use 7z + else if ( have_7za ) + m_archiver_program = m_unarchiver_program = "7za"; // Try 7za + else + m_archiver_program = m_unarchiver_program = "7zr"; + + verifyCompressUtilityIsAvailable( m_archiver_program ); + verifyUncompressUtilityIsAvailable( m_unarchiver_program ); + + m_headerString = "------------------"; + + m_repairYear = 5; m_fixMonth = 6; m_fixDay = 7; m_fixTime = 8; + m_dateCol = 3; + m_numCols = 5; + + m_archCols.append( new ArchColumns( 5, QRegExp( "[0-2][0-9][0-9][0-9]" ), 4 ) ); // Year + m_archCols.append( new ArchColumns( 6, QRegExp( "[01][0-9]" ), 2 ) ); // Month + m_archCols.append( new ArchColumns( 7, QRegExp( "[0-3][0-9]" ), 2 ) ); // Day + m_archCols.append( new ArchColumns( 8, QRegExp( "[0-9:]+" ), 8 ) ); // Time + m_archCols.append( new ArchColumns( 4, QRegExp( "[^\\s]+" ) ) ); // Attributes + m_archCols.append( new ArchColumns( 1, QRegExp( "[0-9]+" ) ) ); // Size + m_archCols.append( new ArchColumns( 2, QRegExp( "[0-9]+" ), 64, true ) ); // Compressed Size +} + +SevenZipArch::~SevenZipArch() +{ +} + +void SevenZipArch::setHeaders() +{ + ColumnList columns; + columns.append( FILENAME_COLUMN ); + columns.append( SIZE_COLUMN ); + columns.append( PACKED_COLUMN ); + columns.append( TIMESTAMP_COLUMN ); + columns.append( PERMISSION_COLUMN ); + + emit headers( columns ); +} + +void SevenZipArch::open() +{ + setHeaders(); + + m_buffer = ""; + m_header_removed = false; + m_finished = false; + + KProcess *kp = m_currentProcess = new KProcess; + *kp << m_archiver_program << "l" << m_filename; + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedTOC(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotOpenExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigOpen( this, false, QString::null, 0 ); + } +} + +void SevenZipArch::create() +{ + emit sigCreate( this, true, m_filename, + Arch::Extract | Arch::Delete | Arch::Add | Arch::View ); +} + +void SevenZipArch::addFile( const QStringList & urls ) +{ + KProcess *kp = m_currentProcess = new KProcess; + + kp->clearArguments(); + *kp << m_archiver_program << "a" ; + + KURL url( urls.first() ); + QDir::setCurrent( url.directory() ); + + *kp << m_filename; + + QStringList::ConstIterator iter; + for ( iter = urls.begin(); iter != urls.end(); ++iter ) + { + KURL url( *iter ); + *kp << url.fileName(); + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotAddExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigAdd( false ); + } +} + +void SevenZipArch::addDir( const QString & dirName ) +{ + if ( !dirName.isEmpty() ) + { + QStringList list; + list.append( dirName ); + addFile( list ); + } +} + +void SevenZipArch::remove( QStringList *list ) +{ + if ( !list ) + return; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program << "d" << m_filename; + + QStringList::Iterator it; + for ( it = list->begin(); it != list->end(); ++it ) + { + *kp << *it; + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotDeleteExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigDelete( false ); + } +} + +void SevenZipArch::unarchFileInternal( ) +{ + if ( m_destDir.isEmpty() || m_destDir.isNull() ) + { + kdError( 1601 ) << "There was no extract directory given." << endl; + return; + } + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + // extract (and maybe overwrite) + *kp << m_unarchiver_program << "x"; + + if ( ArkSettings::extractOverwrite() ) + { + //*kp << "-ao"; + } + + *kp << m_filename; + + // if the file list is empty, no filenames go on the command line, + // and we then extract everything in the archive. + if ( m_fileList ) + { + QStringList::Iterator it; + for ( it = m_fileList->begin(); it != m_fileList->end(); ++it ) + { + *kp << (*it); + } + } + + *kp << "-o" + m_destDir ; + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotExtractExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigExtract( false ); + } +} + +bool SevenZipArch::processLine( const QCString& _line ) +{ + QCString line( _line ); + QString columns[ 11 ]; + unsigned int pos = 0; + int strpos, len; + + columns[ 0 ] = line.right( line.length() - m_nameColumnPos +1); + line.truncate( m_nameColumnPos ); + + // Go through our columns, try to pick out data, return silently on failure + for ( QPtrListIterator col( m_archCols ); col.current(); ++col ) + { + ArchColumns *curCol = *col; + + strpos = curCol->pattern.search( line, pos ); + len = curCol->pattern.matchedLength(); + + if ( ( strpos == -1 ) || ( len > curCol->maxLength ) ) + { + if ( curCol->optional ) + continue; // More? + else + { + kdDebug(1601) << "processLine failed to match critical column" << endl; + return false; + } + } + + pos = strpos + len; + + columns[ curCol->colRef ] = line.mid( strpos, len ); + } + + + if ( m_dateCol >= 0 ) + { + QString year = ( m_repairYear >= 0 ) ? + ArkUtils::fixYear( columns[ m_repairYear ].ascii()) + : columns[ m_fixYear ]; + QString month = ( m_repairMonth >= 0 ) ? + QString( "%1" ) + .arg( ArkUtils::getMonth( columns[ m_repairMonth ].ascii() ) ) + : columns[ m_fixMonth ]; + QString timestamp = QString::fromLatin1( "%1-%2-%3 %4" ) + .arg( year ) + .arg( month ) + .arg( columns[ m_fixDay ] ) + .arg( columns[ m_fixTime ] ); + + columns[ m_dateCol ] = timestamp; + } + + QStringList list; + + for ( int i = 0; i < m_numCols; ++i ) + { + list.append( columns[ i ] ); + } + + m_gui->fileList()->addItem( list ); // send the entry to the GUI + + return true; +} + +void SevenZipArch::slotReceivedTOC( KProcess*, char* data, int length ) +{ + char endchar = data[ length ]; + data[ length ] = '\0'; + + appendShellOutputData( data ); + + int startChar = 0; + + while ( !m_finished ) + { + int lfChar; + for ( lfChar = startChar; data[ lfChar ] != '\n' && lfChar < length; + lfChar++ ); + + if ( data[ lfChar ] != '\n') + break; // We are done all the complete lines + + data[ lfChar ] = '\0'; + m_buffer.append( data + startChar ); + data[ lfChar ] = '\n'; + startChar = lfChar + 1; + + // Check if the header was found + if ( m_buffer.find( m_headerString ) != -1 ) + { + if ( !m_header_removed ) + { + m_nameColumnPos = m_buffer.findRev( ' ' ) + 1; + m_header_removed = true; + } + else + { + m_finished = true; + } + } + else + { + // If the header was not found, process the line + if ( m_header_removed && !m_finished ) + { + if ( !processLine( m_buffer ) ) + { + m_header_removed = false; + m_error = true; + } + } + } + + m_buffer.resize( 0 ); + } + + if ( !m_finished ) + m_buffer.append( data + startChar); // Append what's left of the buffer + + data[ length ] = endchar; +} + +#include "sevenzip.moc" diff --git a/ark/sevenzip.h b/ark/sevenzip.h new file mode 100644 index 0000000..4a34c48 --- /dev/null +++ b/ark/sevenzip.h @@ -0,0 +1,54 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2004: Henrique Pinto + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +#ifndef SEVENZIP_H +#define SEVENZIP_H + +#include "arch.h" + +class SevenZipArch : public Arch +{ + Q_OBJECT + public: + SevenZipArch( ArkWidget *, const QString & ); + virtual ~SevenZipArch(); + + virtual void open(); + virtual void create(); + + virtual void addFile( const QStringList & ); + virtual void addDir( const QString & ); + + virtual void remove( QStringList * ); + virtual void unarchFileInternal( ); + + protected slots: + virtual bool processLine( const QCString& line ); + virtual void slotReceivedTOC( KProcess*, char*, int ); + + private: + void setHeaders(); + int m_nameColumnPos; +}; + +#endif // SEVENZIP_H diff --git a/ark/tar.cpp b/ark/tar.cpp new file mode 100644 index 0000000..5f104ef --- /dev/null +++ b/ark/tar.cpp @@ -0,0 +1,774 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 1997-1999: Rob Palmbos palm9744@kettering.edu + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + 2001: Roberto Selbach Teixeira + 2003: Georg Robbers + 2006: Henrique Pinto + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +// Note: When maintaining tar files with ark, the user should be +// aware that these options have been improved (IMHO). When you append a file +// to a tarchive, tar does not check if the file exists already, and just +// tacks the new one on the end. ark deletes the old one. +// When you update a file that exists in a tarchive, it does check if +// it exists, but once again, it creates a duplicate at the end (only if +// the file is newer though). ark deletes the old one in this case as well. +// +// Basically, tar files are great for creating and extracting, but +// not especially for maintaining. The original purpose of a tar was of +// course, for tape backups, so this is not so surprising! -Emily +// + +// C includes +#include +#include +#include +#include +#include + +// Qt includes +#include +#include +#include + +// KDE includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ark includes +#include "arkwidget.h" +#include "settings.h" +#include "tar.h" +#include "filelistview.h" +#include "tarlistingthread.h" + +TarArch::TarArch( ArkWidget *_gui, + const QString & _filename, const QString & _openAsMimeType) + : Arch( _gui, _filename), m_tmpDir( 0 ), createTmpInProgress(false), + updateInProgress(false), deleteInProgress(false), fd(0), + m_pTmpProc( 0 ), m_pTmpProc2( 0 ), failed( false ), + m_dotslash( false ), m_listingThread( 0 ) +{ + m_filesToAdd = m_filesToRemove = QStringList(); + m_archiver_program = m_unarchiver_program = ArkSettings::tarExe(); + verifyCompressUtilityIsAvailable( m_archiver_program ); + verifyUncompressUtilityIsAvailable( m_unarchiver_program ); + + m_fileMimeType = _openAsMimeType; + if ( m_fileMimeType.isNull() ) + m_fileMimeType = KMimeType::findByPath( _filename )->name(); + + kdDebug(1601) << "TarArch::TarArch: mimetype is " << m_fileMimeType << endl; + + if ( m_fileMimeType == "application/x-tbz2" ) + { + // ark treats .tar.bz2 as x-tbz, instead of duplicating the mimetype + // let's just alias it to the one we already handle. + m_fileMimeType = "application/x-tbz"; + } + + if ( m_fileMimeType == "application/x-tar" ) + { + compressed = false; + } + else + { + compressed = true; + m_tmpDir = new KTempDir( _gui->tmpDir() + + QString::fromLatin1( "temp_tar" ) ); + m_tmpDir->setAutoDelete( true ); + m_tmpDir->qDir()->cd( m_tmpDir->name() ); + // build the temp file name + KTempFile *pTempFile = new KTempFile( m_tmpDir->name(), + QString::fromLatin1(".tar") ); + + tmpfile = pTempFile->name(); + delete pTempFile; + + kdDebug(1601) << "Tmpfile will be " << tmpfile << "\n" << endl; + } +} + +TarArch::~TarArch() +{ + delete m_tmpDir; + m_tmpDir = 0; + + if ( m_listingThread && m_listingThread->finished() != true ) + { + m_listingThread->wait(); + delete m_listingThread; + m_listingThread = 0; + } +} + +int TarArch::getEditFlag() +{ + return Arch::Extract; +} + +void TarArch::updateArch() +{ + if (compressed) + { + updateInProgress = true; + int f_desc = KDE_open(QFile::encodeName(m_filename), O_CREAT | O_TRUNC | O_WRONLY, 0666); + if (f_desc != -1) + fd = fdopen( f_desc, "w" ); + else + fd = NULL; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + KProcess::Communication flag = KProcess::AllOutput; + if ( getCompressor() == "lzop" ) + { + kp->setUsePty( KProcess::Stdin, false ); + flag = KProcess::Stdout; + } + if ( !getCompressor().isNull() ) + *kp << getCompressor() << "-c" << tmpfile; + else + *kp << "cat" << tmpfile; + + + connect(kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(updateProgress( KProcess *, char *, int ))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + (Arch *)this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + + connect(kp, SIGNAL(processExited(KProcess *)), + this, SLOT(updateFinished(KProcess *)) ); + + if ( !fd || kp->start(KProcess::NotifyOnExit, flag) == false) + { + KMessageBox::error(0, i18n("Trouble writing to the archive...")); + emit updateDone(); + } + } +} + +void TarArch::updateProgress( KProcess * _proc, char *_buffer, int _bufflen ) +{ + // we're trying to capture the output of a command like this + // gzip -c myarch.tar + // and feed the output to the archive + int size; + size = fwrite(_buffer, 1, _bufflen, fd); + if (size != _bufflen) + { + _proc->kill(); + KMessageBox::error(0, i18n("Trouble writing to the archive...")); + kdWarning( 1601 ) << "trouble updating tar archive" << endl; + //kdFatal( 1601 ) << "trouble updating tar archive" << endl; + } +} + + + +QString TarArch::getCompressor() +{ + if ( m_fileMimeType == "application/x-tarz" ) + return QString( "compress" ); + + if ( m_fileMimeType == "application/x-tgz" ) + return QString( "gzip" ); + + if ( m_fileMimeType == "application/x-tbz" ) + return QString( "bzip2" ); + + if( m_fileMimeType == "application/x-tzo" ) + return QString( "lzop" ); + + return QString::null; +} + + +QString TarArch::getUnCompressor() +{ + if ( m_fileMimeType == "application/x-tarz" ) + return QString( "uncompress" ); + + if ( m_fileMimeType == "application/x-tgz" ) + return QString( "gunzip" ); + + if ( m_fileMimeType == "application/x-tbz" ) + return QString( "bunzip2" ); + + if( m_fileMimeType == "application/x-tzo" ) + return QString( "lzop" ); + + return QString::null; +} + +void +TarArch::open() +{ + if ( compressed ) + QFile::remove(tmpfile); // just to make sure + setHeaders(); + + clearShellOutput(); + + // might as well plunk the output of tar -tvf in the shell output window... + // + // Now it's essential - used later to decide whether pathnames in the + // tar archive are plain or start with "./" + KProcess *kp = m_currentProcess = new KProcess; + + *kp << m_archiver_program; + + if ( compressed ) + { + *kp << "--use-compress-program=" + getUnCompressor(); + } + + *kp << "-tvf" << m_filename; + + m_buffer = ""; + m_header_removed = false; + m_finished = false; + + connect(kp, SIGNAL(processExited(KProcess *)), + this, SLOT(slotListingDone(KProcess *))); + connect(kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput( KProcess *, char *, int ))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + + if (kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + } + + // We list afterwards because we want the signals at the end + // This unconfuses Extract Here somewhat + + if ( m_fileMimeType == "application/x-tgz" + || m_fileMimeType == "application/x-tbz" || !compressed ) + { + openFirstCreateTempDone(); + } + else + { + connect( this, SIGNAL( createTempDone() ), this, SLOT( openFirstCreateTempDone() ) ); + createTmp(); + } +} + +void TarArch::openFirstCreateTempDone() +{ + if ( compressed && ( m_fileMimeType != "application/x-tgz" ) + && ( m_fileMimeType != "application/x-tbz" ) ) + { + disconnect( this, SIGNAL( createTempDone() ), this, SLOT( openFirstCreateTempDone() ) ); + } + + Q_ASSERT( !m_listingThread ); + m_listingThread = new TarListingThread( this, m_filename ); + m_listingThread->start(); +} + +void TarArch::slotListingDone(KProcess *_kp) +{ + const QString list = getLastShellOutput(); + FileListView *flv = m_gui->fileList(); + if (flv!=NULL && flv->totalFiles()>0) + { + const QString firstfile = ((FileLVI *) flv->firstChild())->fileName(); + if (list.find(QRegExp(QString("\\s\\./%1[/\\n]").arg(firstfile)))>=0) + { + m_dotslash = true; + kdDebug(1601) << k_funcinfo << "archive has dot-slash" << endl; + } + else + { + if (list.find(QRegExp(QString("\\s%1[/\\n]").arg(firstfile)))>=0) + { + // archive doesn't have dot-slash + m_dotslash = false; + } + else + { + kdDebug(1601) << k_funcinfo << "cannot match '" << firstfile << "' in listing!" << endl; + } + } + } + + delete _kp; + _kp = m_currentProcess = NULL; +} + +void TarArch::create() +{ + emit sigCreate(this, true, m_filename, + Arch::Extract | Arch::Delete | Arch::Add + | Arch::View); +} + +void TarArch::setHeaders() +{ + ColumnList list; + + list.append(FILENAME_COLUMN); + list.append(PERMISSION_COLUMN); + list.append(OWNER_COLUMN); + list.append(GROUP_COLUMN); + list.append(SIZE_COLUMN); + list.append(TIMESTAMP_COLUMN); + list.append(LINK_COLUMN); + + emit headers( list ); +} + +void TarArch::createTmp() +{ + if ( compressed ) + { + if ( !QFile::exists(tmpfile) ) + { + QString strUncompressor = getUnCompressor(); + // at least lzop doesn't want to pipe zerosize/nonexistent files + QFile originalFile( m_filename ); + if ( strUncompressor != "gunzip" && strUncompressor !="bunzip2" && + ( !originalFile.exists() || originalFile.size() == 0 ) ) + { + QFile temp( tmpfile ); + temp.open( IO_ReadWrite ); + temp.close(); + emit createTempDone(); + return; + } + // the tmpfile does not yet exist, so we create it. + createTmpInProgress = true; + int f_desc = KDE_open(QFile::encodeName(tmpfile), O_CREAT | O_TRUNC | O_WRONLY, 0666); + if (f_desc != -1) + fd = fdopen( f_desc, "w" ); + else + fd = NULL; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + kdDebug(1601) << "Uncompressor is " << strUncompressor << endl; + *kp << strUncompressor; + KProcess::Communication flag = KProcess::AllOutput; + if (strUncompressor == "lzop") + { + // setting up a pty for lzop, since it doesn't like stdin to + // be /dev/null ( "no filename allowed when reading from stdin" ) + // - but it used to work without this ? ( Feb 13, 2003 ) + kp->setUsePty( KProcess::Stdin, false ); + flag = KProcess::Stdout; + *kp << "-d"; + } + *kp << "-c" << m_filename; + + connect(kp, SIGNAL(processExited(KProcess *)), + this, SLOT(createTmpFinished(KProcess *))); + connect(kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(createTmpProgress( KProcess *, char *, int ))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + if (kp->start(KProcess::NotifyOnExit, flag ) == false) + { + KMessageBox::error(0, i18n("Unable to fork a decompressor")); + emit sigOpen( this, false, QString::null, 0 ); + } + } + else + { + emit createTempDone(); + kdDebug(1601) << "Temp tar already there..." << endl; + } + } + else + { + emit createTempDone(); + } +} + +void TarArch::createTmpProgress( KProcess * _proc, char *_buffer, int _bufflen ) +{ + // we're trying to capture the output of a command like this + // gunzip -c myarch.tar.gz + // and put the output into tmpfile. + + int size; + size = fwrite(_buffer, 1, _bufflen, fd); + if (size != _bufflen) + { + _proc->kill(); + KMessageBox::error(0, i18n("Trouble writing to the tempfile...")); + //kdFatal( 1601 ) << "Trouble writing to archive(createTmpProgress)" << endl; + kdWarning( 1601 ) << "Trouble writing to archive(createTmpProgress)" << endl; + //exit(99); + } +} + +void TarArch::deleteOldFiles(const QStringList &urls, bool bAddOnlyNew) + // because tar is broken. Used when appending: see addFile. +{ + QStringList list; + QString str; + + QStringList::ConstIterator iter; + for (iter = urls.begin(); iter != urls.end(); ++iter ) + { + KURL url( *iter ); + // find the file entry in the archive listing + const FileLVI * lv = m_gui->fileList()->item( url.fileName() ); + if ( !lv ) // it isn't in there, so skip it. + continue; + + if (bAddOnlyNew) + { + // compare timestamps. If the file to be added is newer, delete the + // old. Otherwise we aren't adding it anyway, so we can go on to the next + // file with a "continue". + + QFileInfo fileInfo( url.path() ); + QDateTime addFileMTime = fileInfo.lastModified(); + QDateTime oldFileMTime = lv->timeStamp(); + + kdDebug(1601) << "Old file: " << oldFileMTime.date().year() << '-' << + oldFileMTime.date().month() << '-' << oldFileMTime.date().day() << + ' ' << oldFileMTime.time().hour() << ':' << + oldFileMTime.time().minute() << ':' << oldFileMTime.time().second() << + endl; + kdDebug(1601) << "New file: " << addFileMTime.date().year() << '-' << + addFileMTime.date().month() << '-' << addFileMTime.date().day() << + ' ' << addFileMTime.time().hour() << ':' << + addFileMTime.time().minute() << ':' << addFileMTime.time().second() << + endl; + + if (oldFileMTime >= addFileMTime) + { + kdDebug(1601) << "Old time is newer or same" << endl; + continue; // don't add this file to the list to be deleted. + } + } + list.append(str); + + kdDebug(1601) << "To delete: " << str << endl; + } + if(!list.isEmpty()) + remove(&list); + else + emit removeDone(); +} + + +void TarArch::addFile( const QStringList& urls ) +{ + m_filesToAdd = urls; + // tar is broken. If you add a file that's already there, it gives you + // two entries for that name, whether you --append or --update. If you + // extract by name, it will give you + // the first one. If you extract all, the second one will overwrite the + // first. So we'll first delete all the old files matching the names of + // those in urls. + m_bNotifyWhenDeleteFails = false; + connect( this, SIGNAL( removeDone() ), this, SLOT( deleteOldFilesDone() ) ); + deleteOldFiles(urls, ArkSettings::replaceOnlyWithNewer()); +} + +void TarArch::deleteOldFilesDone() +{ + disconnect( this, SIGNAL( removeDone() ), this, SLOT( deleteOldFilesDone() ) ); + m_bNotifyWhenDeleteFails = true; + + connect( this, SIGNAL( createTempDone() ), this, SLOT( addFileCreateTempDone() ) ); + createTmp(); +} + +void TarArch::addFileCreateTempDone() +{ + disconnect( this, SIGNAL( createTempDone() ), this, SLOT( addFileCreateTempDone() ) ); + QStringList * urls = &m_filesToAdd; + + KProcess *kp = m_currentProcess = new KProcess; + *kp << m_archiver_program; + + if( ArkSettings::replaceOnlyWithNewer()) + *kp << "uvf"; + else + *kp << "rvf"; + + if (compressed) + *kp << tmpfile; + else + *kp << m_filename; + + QStringList::ConstIterator iter; + KURL url( urls->first() ); + QDir::setCurrent( url.directory() ); + for (iter = urls->begin(); iter != urls->end(); ++iter ) + { + KURL fileURL( *iter ); + *kp << fileURL.fileName(); + } + + // debugging info + QValueList list = kp->args(); + QValueList::Iterator strTemp; + for ( strTemp=list.begin(); strTemp != list.end(); ++strTemp ) + { + kdDebug(1601) << *strTemp << " " << endl; + } + + connect( kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + + connect( kp, SIGNAL(processExited(KProcess*)), this, + SLOT(slotAddFinished(KProcess*))); + + if (kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + emit sigAdd(false); + } +} + +void TarArch::slotAddFinished(KProcess *_kp) +{ + disconnect( _kp, SIGNAL(processExited(KProcess*)), this, + SLOT(slotAddFinished(KProcess*))); + m_pTmpProc = _kp; + m_filesToAdd = QStringList(); + if ( compressed ) + { + connect( this, SIGNAL( updateDone() ), this, SLOT( addFinishedUpdateDone() ) ); + updateArch(); + } + else + addFinishedUpdateDone(); +} + +void TarArch::addFinishedUpdateDone() +{ + if ( compressed ) + disconnect( this, SIGNAL( updateDone() ), this, SLOT( addFinishedUpdateDone() ) ); + Arch::slotAddExited( m_pTmpProc ); // this will delete _kp + m_pTmpProc = NULL; +} + +void TarArch::unarchFileInternal() +{ + QString dest; + + if (m_destDir.isEmpty() || m_destDir.isNull()) + { + kdError(1601) << "There was no extract directory given." << endl; + return; + } + else dest = m_destDir; + + QString tmp; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program; + if (compressed) + *kp << "--use-compress-program="+getUnCompressor(); + + QString options = "-x"; + if (!ArkSettings::extractOverwrite()) + options += "k"; + if (ArkSettings::preservePerms()) + options += "p"; + options += "f"; + + kdDebug(1601) << "Options were: " << options << endl; + *kp << options << m_filename << "-C" << dest; + + // if the list is empty, no filenames go on the command line, + // and we then extract everything in the archive. + if (m_fileList) + { + for ( QStringList::Iterator it = m_fileList->begin(); + it != m_fileList->end(); ++it ) + { + *kp << QString(m_dotslash ? "./" : "")+(*it); + } + } + + connect( kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + + connect( kp, SIGNAL(processExited(KProcess*)), this, + SLOT(slotExtractExited(KProcess*))); + + if (kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + emit sigExtract(false); + } + +} + +void TarArch::remove(QStringList *list) +{ + deleteInProgress = true; + m_filesToRemove = *list; + connect( this, SIGNAL( createTempDone() ), this, SLOT( removeCreateTempDone() ) ); + createTmp(); +} + +void TarArch::removeCreateTempDone() +{ + disconnect( this, SIGNAL( createTempDone() ), this, SLOT( removeCreateTempDone() ) ); + + QString name, tmp; + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + *kp << m_archiver_program << "--delete" << "-f" ; + if (compressed) + *kp << tmpfile; + else + *kp << m_filename; + + QStringList::Iterator it = m_filesToRemove.begin(); + for ( ; it != m_filesToRemove.end(); ++it ) + { + *kp << QString(m_dotslash ? "./" : "")+(*it); + } + m_filesToRemove = QStringList(); + + connect( kp, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + connect( kp, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedOutput(KProcess*, char*, int))); + + connect( kp, SIGNAL(processExited(KProcess*)), this, + SLOT(slotDeleteExited(KProcess*))); + + if (kp->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) + { + KMessageBox::error( 0, i18n("Could not start a subprocess.") ); + emit sigDelete(false); + } +} + +void TarArch::slotDeleteExited(KProcess *_kp) +{ + m_pTmpProc2 = _kp; + if ( compressed ) + { + connect( this, SIGNAL( updateDone() ), this, SLOT( removeUpdateDone() ) ); + updateArch(); + } + else + removeUpdateDone(); +} + +void TarArch::removeUpdateDone() +{ + if ( compressed ) + disconnect( this, SIGNAL( updateDone() ), this, SLOT( removeUpdateDone() ) ); + + deleteInProgress = false; + emit removeDone(); + Arch::slotDeleteExited( m_pTmpProc2 ); + m_pTmpProc = NULL; +} + +void TarArch::addDir(const QString & _dirName) +{ + QStringList list; + list.append(_dirName); + addFile(list); +} + +void TarArch::openFinished( KProcess * ) +{ + // do nothing + // turn off busy light (when someone makes one) + kdDebug(1601) << "Open finshed" << endl; +} + +void TarArch::createTmpFinished( KProcess *_kp ) +{ + createTmpInProgress = false; + fclose(fd); + delete _kp; + _kp = m_currentProcess = NULL; + + emit createTempDone(); +} + +void TarArch::updateFinished( KProcess *_kp ) +{ + fclose(fd); + updateInProgress = false; + delete _kp; + _kp = m_currentProcess = NULL; + + emit updateDone(); +} + +void TarArch::customEvent( QCustomEvent *ev ) +{ + if ( ev->type() == 65442 ) + { + ListingEvent *event = static_cast( ev ); + switch ( event->status() ) + { + case ListingEvent::Normal: + m_gui->fileList()->addItem( event->columns() ); + break; + + case ListingEvent::Error: + m_listingThread->wait(); + delete m_listingThread; + m_listingThread = 0; + emit sigOpen( this, false, QString::null, 0 ); + break; + + case ListingEvent::ListingFinished: + m_listingThread->wait(); + delete m_listingThread; + m_listingThread = 0; + emit sigOpen( this, true, m_filename, + Arch::Extract | Arch::Delete | Arch::Add | Arch::View ); + } + } +} + +#include "tar.moc" +// kate: space-indent on; diff --git a/ark/tar.h b/ark/tar.h new file mode 100644 index 0000000..544949a --- /dev/null +++ b/ark/tar.h @@ -0,0 +1,135 @@ +/* + +ark -- archiver for the KDE project + +Copyright (C) + +1997-1999: Rob Palmbos palm9744@kettering.edu +1999: Francois-Xavier Duranceau duranceau@kde.org +1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) +2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) +2001: Roberto Selbach Teixeira +2003: Georg Robbers +2006: Henrique Pinto + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef TAR_H +#define TAR_H + +#include + + +class QString; +class QStrList; + +class KProcess; +class KTempDir; +class KTarDirectory; +class KTar; + +class ArkWidget; +class Arch; +class TarListingThread; + +// TarArch can read Tar files and Tar files compressed with gzip. +// It doesn't yet know how to list Tar files compressed with other +// compressors because the listing part is done through KTar. +// If it could be listed though, the rest would work. +// The reason we use KTar for listing is that the output tar -tvf is +// of unreliable format. + +class TarArch : public Arch +{ + Q_OBJECT + public: + TarArch( ArkWidget *_gui, const QString & _filename, + const QString & _openAsMimeType ); + virtual ~TarArch(); + + virtual void open(); + virtual void create(); + + virtual void addFile( const QStringList & ); + virtual void addDir( const QString & ); + virtual void remove( QStringList* ); + virtual void unarchFileInternal(); + + virtual int getEditFlag(); + + QString getCompressor(); + QString getUnCompressor(); + + public slots: + void updateProgress( KProcess *_kp, char *_buffer, int _bufflen ); + void openFinished( KProcess * ); + void updateFinished( KProcess * ); + void createTmpFinished( KProcess * ); + void createTmpProgress( KProcess *_kp, char *_buffer, int _bufflen ); + void slotAddFinished( KProcess * ); + void slotListingDone( KProcess * ); + void slotDeleteExited( KProcess * ); + + signals: + void removeDone(); + void createTempDone(); + void updateDone(); + + private slots: + void openFirstCreateTempDone(); + void deleteOldFilesDone(); + void addFileCreateTempDone(); + void addFinishedUpdateDone(); + void removeCreateTempDone(); + void removeUpdateDone(); + + protected: + void customEvent( QCustomEvent * ); + + private: // methods + void updateArch(); + void createTmp(); + void setHeaders(); + void processDir( const KTarDirectory *tardir, const QString & root ); + void deleteOldFiles( const QStringList &list, bool bAddOnlyNew ); + QString getEntry( const QString & filename ); + + private: // data + // if the tar is compressed, this is the temporary uncompressed tar. + KTempDir * m_tmpDir; + QString tmpfile; + QString m_fileMimeType; + bool compressed; + + // for use with createTmp and updateArch + bool createTmpInProgress; + bool updateInProgress; + + // for use with deleteOldFiles + bool deleteInProgress; + FILE *fd; + QStringList m_filesToAdd; + QStringList m_filesToRemove; + KProcess * m_pTmpProc; + KProcess * m_pTmpProc2; + bool failed; + bool m_dotslash; + TarListingThread *m_listingThread; +}; + +#endif /* TAR_H */ + diff --git a/ark/tarlistingthread.cpp b/ark/tarlistingthread.cpp new file mode 100644 index 0000000..2a98375 --- /dev/null +++ b/ark/tarlistingthread.cpp @@ -0,0 +1,161 @@ +/* + This file is part of KDE. + + Copyright (c) 2006 Henrique Pinto + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + + +#include +#include + +#include +#include +#include + +#include "tarlistingthread.h" + +// Helper function +// copied from KonqTreeViewItem::makeAccessString() +static char *makeAccessString(mode_t mode) +{ + static char buffer[10]; + + char uxbit,gxbit,oxbit; + + if ( (mode & (S_IXUSR|S_ISUID)) == (S_IXUSR|S_ISUID) ) + uxbit = 's'; + else if ( (mode & (S_IXUSR|S_ISUID)) == S_ISUID ) + uxbit = 'S'; + else if ( (mode & (S_IXUSR|S_ISUID)) == S_IXUSR ) + uxbit = 'x'; + else + uxbit = '-'; + + if ( (mode & (S_IXGRP|S_ISGID)) == (S_IXGRP|S_ISGID) ) + gxbit = 's'; + else if ( (mode & (S_IXGRP|S_ISGID)) == S_ISGID ) + gxbit = 'S'; + else if ( (mode & (S_IXGRP|S_ISGID)) == S_IXGRP ) + gxbit = 'x'; + else + gxbit = '-'; + + if ( (mode & (S_IXOTH|S_ISVTX)) == (S_IXOTH|S_ISVTX) ) + oxbit = 't'; + else if ( (mode & (S_IXOTH|S_ISVTX)) == S_ISVTX ) + oxbit = 'T'; + else if ( (mode & (S_IXOTH|S_ISVTX)) == S_IXOTH ) + oxbit = 'x'; + else + oxbit = '-'; + + buffer[0] = ((( mode & S_IRUSR ) == S_IRUSR ) ? 'r' : '-' ); + buffer[1] = ((( mode & S_IWUSR ) == S_IWUSR ) ? 'w' : '-' ); + buffer[2] = uxbit; + buffer[3] = ((( mode & S_IRGRP ) == S_IRGRP ) ? 'r' : '-' ); + buffer[4] = ((( mode & S_IWGRP ) == S_IWGRP ) ? 'w' : '-' ); + buffer[5] = gxbit; + buffer[6] = ((( mode & S_IROTH ) == S_IROTH ) ? 'r' : '-' ); + buffer[7] = ((( mode & S_IWOTH ) == S_IWOTH ) ? 'w' : '-' ); + buffer[8] = oxbit; + buffer[9] = 0; + + return buffer; +} + +TarListingThread::TarListingThread( QObject *parent, const QString& filename ) + : QThread(), m_parent( parent ) +{ + Q_ASSERT( m_parent ); + m_archive = new KTar( filename ); +} + +TarListingThread::~TarListingThread() +{ + delete m_archive; + m_archive = 0; +} + +void TarListingThread::run() +{ + if (!m_archive->open( IO_ReadOnly )) + { + ListingEvent *ev = new ListingEvent( QStringList(), ListingEvent::Error ); + qApp->postEvent( m_parent, ev ); + return; + } + + processDir( m_archive->directory(), QString() ); + + // Send an empty QStringList in an Event to signal the listing end. + ListingEvent *ev = new ListingEvent( QStringList(), ListingEvent::ListingFinished ); + qApp->postEvent( m_parent, ev ); +} + +void TarListingThread::processDir( const KTarDirectory *tardir, const QString & root ) +{ + QStringList list = tardir->entries(); + + QStringList::const_iterator itEnd = list.constEnd(); + + for ( QStringList::const_iterator it = list.constBegin(); it != itEnd; ++it ) + { + const KTarEntry* tarEntry = tardir->entry((*it)); + if (!tarEntry) + continue; + + QStringList col_list; + QString name; + if (root.isEmpty() || root.isNull()) + name = tarEntry->name(); + else + name = root + tarEntry->name(); + if ( !tarEntry->isFile() ) + name += '/'; + col_list.append( name ); + QString perms = makeAccessString(tarEntry->permissions()); + if (!tarEntry->isFile()) + perms = "d" + perms; + else if (!tarEntry->symlink().isEmpty()) + perms = "l" + perms; + else + perms = "-" + perms; + col_list.append(perms); + col_list.append( tarEntry->user() ); + col_list.append( tarEntry->group() ); + QString strSize = "0"; + if (tarEntry->isFile()) + { + strSize.sprintf("%d", ((KTarFile *)tarEntry)->size()); + } + col_list.append(strSize); + QString timestamp = tarEntry->datetime().toString(ISODate); + col_list.append(timestamp); + col_list.append(tarEntry->symlink()); + + ListingEvent *ev = new ListingEvent( col_list ); + qApp->postEvent( m_parent, ev ); + + // if it's a directory, process it. + // remember that name is root + / + the name of the directory + if ( tarEntry->isDirectory() ) + { + processDir( static_cast( tarEntry ), name ); + } + } +} diff --git a/ark/tarlistingthread.h b/ark/tarlistingthread.h new file mode 100644 index 0000000..f9de02b --- /dev/null +++ b/ark/tarlistingthread.h @@ -0,0 +1,63 @@ +/* + This file is part of KDE. + + Copyright (c) 2006 Henrique Pinto + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. +*/ + +#ifndef TARLISTINGTHREAD_H +#define TARLISTINGTHREAD_H + +#include +#include +#include + +class QString; +class KArchive; + +class ListingEvent: public QCustomEvent +{ + public: + enum Status { Normal, Error, ListingFinished }; + ListingEvent( const QStringList& data, Status st = Normal ) + : QCustomEvent( 65442 ), m_data( data ), m_status( st ) {} + + const QStringList& columns() const { return m_data; } + Status status() const { return m_status; } + + private: + QStringList m_data; + Status m_status; +}; + +class TarListingThread: public QThread +{ + public: + TarListingThread( QObject *parent, const QString& filename ); + ~TarListingThread(); + + protected: + void run(); + + private: + void processDir( const KTarDirectory *tardir, const QString & root ); + + KArchive *m_archive; + QObject *m_parent; +}; + +#endif // TARLISTINGTHREAD_H diff --git a/ark/zip.cpp b/ark/zip.cpp new file mode 100644 index 0000000..3538d11 --- /dev/null +++ b/ark/zip.cpp @@ -0,0 +1,277 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 1997-1999: Rob Palmbos palm9744@kettering.edu + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +// Qt includes +#include + +// KDE includes +#include +#include +#include +#include + +// ark includes +#include "zip.h" +#include "arkwidget.h" +#include "settings.h" + + +ZipArch::ZipArch( ArkWidget *_gui, const QString & _fileName ) + : Arch( _gui, _fileName ) +{ + m_archiver_program = "zip"; + m_unarchiver_program = "unzip"; + verifyCompressUtilityIsAvailable( m_archiver_program ); + verifyUncompressUtilityIsAvailable( m_unarchiver_program ); + + m_headerString = "----"; + m_repairYear = 9; m_fixMonth = 7; m_fixDay = 8; m_fixTime = 10; + m_dateCol = 5; + m_numCols = 7; + + m_archCols.append( new ArchColumns( 1, QRegExp( "[0-9]+" ) ) ); + m_archCols.append( new ArchColumns( 2, QRegExp( "[^\\s]+" ) ) ); + m_archCols.append( new ArchColumns( 3, QRegExp( "[0-9]+" ) ) ); + m_archCols.append( new ArchColumns( 4, QRegExp( "[0-9.]+%" ) ) ); + m_archCols.append( new ArchColumns( 7, QRegExp( "[01][0-9]" ), 2 ) ); + m_archCols.append( new ArchColumns( 8, QRegExp( "[0-3][0-9]" ), 2 ) ); + m_archCols.append( new ArchColumns( 9, QRegExp( "[0-9][0-9]" ), 2 ) ); + m_archCols.append( new ArchColumns( 10, QRegExp( "[0-9:]+" ), 6 ) ); + m_archCols.append( new ArchColumns( 6, QRegExp( "[a-fA-F0-9]+ {2}" ) ) ); + m_archCols.append( new ArchColumns( 0, QRegExp( "[^\\n]+" ), 4096 ) ); + +} + +void ZipArch::setHeaders() +{ + ColumnList list; + list.append( FILENAME_COLUMN ); + list.append( SIZE_COLUMN ); + list.append( METHOD_COLUMN ); + list.append( PACKED_COLUMN ); + list.append( RATIO_COLUMN ); + list.append( TIMESTAMP_COLUMN ); + list.append( CRC_COLUMN ); + + emit headers( list ); +} + +void ZipArch::open() +{ + setHeaders(); + + m_buffer = ""; + m_header_removed = false; + m_finished = false; + + KProcess *kp = m_currentProcess = new KProcess; + + *kp << m_unarchiver_program << "-v" << m_filename; + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedTOC(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotOpenExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigOpen( this, false, QString::null, 0 ); + } +} + + +void ZipArch::create() +{ + emit sigCreate( this, true, m_filename, + Arch::Extract | Arch::Delete | Arch::Add | Arch::View ); +} + +void ZipArch::addDir( const QString & _dirName ) +{ + if ( !_dirName.isEmpty() ) + { + bool bOldRecVal = ArkSettings::rarRecurseSubdirs(); + // must be true for add directory - otherwise why would user try? + ArkSettings::setRarRecurseSubdirs( true ); + + QStringList list; + list.append( _dirName ); + addFile( list ); + ArkSettings::setRarRecurseSubdirs( bOldRecVal ); // reset to old val + } +} + +void ZipArch::addFile( const QStringList &urls ) +{ + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program; + + if ( !m_password.isEmpty() ) + *kp << "-P" << m_password; + + if ( ArkSettings::rarRecurseSubdirs() ) + *kp << "-r"; + + if ( ArkSettings::rarStoreSymlinks() ) + *kp << "-y"; + + if ( ArkSettings::forceMSDOS() ) + *kp << "-k"; + if ( ArkSettings::convertLF2CRLF() ) + *kp << "-l"; + + if ( ArkSettings::replaceOnlyWithNewer() ) + *kp << "-u"; + + + *kp << m_filename; + + QStringList::ConstIterator iter; + KURL url( urls.first() ); + QDir::setCurrent( url.directory() ); + for ( iter = urls.begin(); iter != urls.end(); ++iter ) + { + KURL fileURL( *iter ); + *kp << fileURL.fileName(); + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotAddExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigAdd( false ); + } +} + +void ZipArch::unarchFileInternal() +{ + // if fileList is empty, all files are extracted. + // if destDir is empty, abort with error. + if ( m_destDir.isEmpty() || m_destDir.isNull() ) + { + kdError( 1601 ) << "There was no extract directory given." << endl; + return; + } + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_unarchiver_program; + + if ( !m_password.isEmpty() ) + *kp << "-P" << m_password; + + if ( ArkSettings::extractJunkPaths() && !m_viewFriendly ) + *kp << "-j" ; + + if ( ArkSettings::rarToLower() ) + *kp << "-L"; + + if ( ArkSettings::extractOverwrite() ) + *kp << "-o"; + else + *kp << "-n"; + + *kp << m_filename; + + // if the list is empty, no filenames go on the command line, + // and we then extract everything in the archive. + if ( m_fileList ) + { + QStringList::Iterator it; + + for ( it = m_fileList->begin(); it != m_fileList->end(); ++it ) + { + *kp << (*it); + } + } + + *kp << "-d" << m_destDir; + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotExtractExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigExtract( false ); + } +} + +bool ZipArch::passwordRequired() +{ + return m_lastShellOutput.findRev("unable to get password\n")!=-1 || m_lastShellOutput.endsWith("password inflating\n") || m_lastShellOutput.findRev("password incorrect--reenter:")!=-1 || m_lastShellOutput.endsWith("incorrect password\n"); +} + +void ZipArch::remove( QStringList *list ) +{ + if ( !list ) + return; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program << "-d" << m_filename; + + QStringList::Iterator it; + for ( it = list->begin(); it != list->end(); ++it ) + { + QString str = *it; + *kp << str; + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotDeleteExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigDelete( false ); + } +} + +#include "zip.moc" diff --git a/ark/zip.h b/ark/zip.h new file mode 100644 index 0000000..721d734 --- /dev/null +++ b/ark/zip.h @@ -0,0 +1,58 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 1997-1999: Rob Palmbos palm9744@kettering.edu + 1999: Francois-Xavier Duranceau duranceau@kde.org + 1999-2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef ZIPARCH_H +#define ZIPARCH_H + +#include "arch.h" + +class QString; +class QStringList; + +class ArkWidget; + +class ZipArch : public Arch +{ + Q_OBJECT + public: + ZipArch( ArkWidget *_gui, const QString & _fileName ); + virtual ~ZipArch() { } + + virtual void open(); + virtual void create(); + + virtual void addFile( const QStringList & ); + virtual void addDir( const QString & ); + + virtual void remove( QStringList * ); + virtual void unarchFileInternal(); + virtual bool passwordRequired(); + private: + void setHeaders(); +}; + +#endif /* ZIPARCH_H */ diff --git a/ark/zoo.cpp b/ark/zoo.cpp new file mode 100644 index 0000000..9116ea5 --- /dev/null +++ b/ark/zoo.cpp @@ -0,0 +1,317 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include + +#include +#include +#include +#include +#include + +// QT includes +#include +#include + +// KDE includes +#include +#include +#include +#include + +// ark includes +#include "settings.h" +#include "arkwidget.h" +#include "arch.h" +#include "zoo.h" +#include "arkutils.h" +#include "filelistview.h" + +static QString fixTime( const QString &_strTime ); + +ZooArch::ZooArch( ArkWidget *gui, const QString & fileName ) + : Arch( gui, fileName ) +{ + m_archiver_program = m_unarchiver_program = "zoo"; + verifyCompressUtilityIsAvailable( m_archiver_program ); + verifyUncompressUtilityIsAvailable( m_unarchiver_program ); + + m_headerString = "----"; +} + +bool ZooArch::processLine( const QCString &line ) +{ + const char *_line = ( const char * )line; + char columns[11][80]; + char filename[4096]; + + // Note: I'm reversing the ratio and the length for better display + + sscanf( _line, + " %79[0-9] %79[0-9%] %79[0-9] %79[0-9] %79[a-zA-Z] %79[0-9]%79[ ]%11[ 0-9:+-]%2[C ]%4095[^\n]", + columns[1], columns[0], columns[2], columns[3], columns[7], + columns[8], columns[9], columns[4], columns[10], filename ); + + QString year = ArkUtils::fixYear( columns[8] ); + + QString strDate; + strDate.sprintf( "%s-%.2d-%.2d", year.utf8().data(), + ArkUtils::getMonth( columns[7] ), atoi( columns[3] ) ); + + strlcpy( columns[3], strDate.ascii(), sizeof( columns[3]) ); + kdDebug( 1601 ) << "New timestamp is " << columns[3] << endl; + + strlcat( columns[3], " ", sizeof( columns[3] ) ); + strlcat( columns[3], fixTime( columns[4] ).ascii(), sizeof( columns[3] ) ); + + QStringList list; + list.append( QFile::decodeName( filename ) ); + + for ( int i=0; i<4; i++ ) + { + list.append( QString::fromLocal8Bit( columns[i] ) ); + } + + m_gui->fileList()->addItem( list ); // send to GUI + + return true; +} + +void ZooArch::open() +{ + setHeaders(); + + m_buffer = ""; + m_header_removed = false; + m_finished = false; + + + KProcess *kp = m_currentProcess = new KProcess; + *kp << m_archiver_program << "l" << m_filename; + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedTOC(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotOpenExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigOpen( this, false, QString::null, 0 ); + } +} + +void ZooArch::setHeaders() +{ + ColumnList list; + list.append( FILENAME_COLUMN ); + list.append( RATIO_COLUMN ); + list.append( SIZE_COLUMN ); + list.append( PACKED_COLUMN ); + list.append( TIMESTAMP_COLUMN ); + + emit headers( list ); +} + + +void ZooArch::create() +{ + emit sigCreate( this, true, m_filename, + Arch::Extract | Arch::Delete | Arch::Add | Arch::View); +} + +void ZooArch::addDir( const QString & _dirName ) +{ + if ( ! _dirName.isEmpty() ) + { + QStringList list; + list.append( _dirName ); + addFile( list ); + } +} + +void ZooArch::addFile( const QStringList &urls ) +{ + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + *kp << m_archiver_program; + + if ( ArkSettings::replaceOnlyWithNewer() ) + *kp << "-update"; + else + *kp << "-add"; + + *kp << m_filename; + + KURL url( urls.first() ); + QDir::setCurrent( url.directory() ); + + QStringList::ConstIterator iter; + + for ( iter = urls.begin(); iter != urls.end(); ++iter ) + { + KURL fileURL( *iter ); + *kp << fileURL.fileName(); + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotAddExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigAdd( false ); + } +} + +void ZooArch::unarchFileInternal() +{ + // if _fileList is empty, we extract all. + // if _destDir is empty, abort with error. + + if ( m_destDir.isEmpty() || m_destDir.isNull() ) + { + kdError( 1601 ) << "There was no extract directory given." << endl; + return; + } + + // zoo has no option to specify the destination directory + // so we have to change to it. + + bool ret = QDir::setCurrent( m_destDir ); + // We already checked the validity of the dir before coming here + Q_ASSERT(ret); + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program; + + if ( ArkSettings::extractOverwrite() ) + { + *kp << "xOOS"; + } + else + { + *kp << "x"; + } + + *kp << m_filename; + + // if the list is empty, no filenames go on the command line, + // and we then extract everything in the archive. + if (m_fileList) + { + QStringList::Iterator it; + for ( it = m_fileList->begin(); it != m_fileList->end(); ++it ) + { + *kp << (*it); + } + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotExtractExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigExtract( false ); + } +} + +void ZooArch::remove( QStringList *list ) +{ + if (!list) + return; + + KProcess *kp = m_currentProcess = new KProcess; + kp->clearArguments(); + + *kp << m_archiver_program << "D" << m_filename; + + QStringList::Iterator it; + for ( it = list->begin(); it != list->end(); ++it ) + { + QString str = *it; + *kp << str; + } + + connect( kp, SIGNAL( receivedStdout(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( receivedStderr(KProcess*, char*, int) ), + SLOT( slotReceivedOutput(KProcess*, char*, int) ) ); + connect( kp, SIGNAL( processExited(KProcess*) ), + SLOT( slotDeleteExited(KProcess*) ) ); + + if ( !kp->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + KMessageBox::error( 0, i18n( "Could not start a subprocess." ) ); + emit sigDelete( false ); + } +} + +QString fixTime( const QString &_strTime ) +{ + // it may have come from a different time zone... get rid of trailing + // +3 or -3 etc. + QString strTime = _strTime; + + if ( strTime.contains("+") || strTime.contains("-") ) + { + QCharRef c = strTime.at( 8 ); + int offset = strTime.right( strTime.length() - 9 ).toInt(); + QString strHour = strTime.left( 2 ); + int nHour = strHour.toInt(); + if ( c == '+' || c == '-' ) + { + if ( c == '+' ) + nHour = ( nHour + offset ) % 24; + else if ( c == '-' ) + { + nHour -= offset; + if ( nHour < 0 ) + nHour += 24; + } + strTime = strTime.left( 8 ); + strTime.sprintf( "%2.2d%s", nHour, strTime.right( 6 ).utf8().data() ); + } + } + else + { + strTime = strTime.left( 8 ); + } + return strTime; +} + +#include "zoo.moc" diff --git a/ark/zoo.h b/ark/zoo.h new file mode 100644 index 0000000..0e83ce1 --- /dev/null +++ b/ark/zoo.h @@ -0,0 +1,59 @@ +/* + + ark -- archiver for the KDE project + + Copyright (C) + + 2000: Corel Corporation (author: Emily Ezust, emilye@corel.com) + 2001: Corel Corporation (author: Michael Jarrett, michaelj@corel.com) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +#ifndef ZOO_H +#define ZOO_H + +#include "arch.h" + +class QString; +class QCString; +class QStringList; + +class ArkWidget; + +class ZooArch : public Arch +{ + Q_OBJECT + public: + ZooArch( ArkWidget *, const QString & ); + virtual ~ZooArch() { } + + virtual void open(); + virtual void create(); + + virtual void addFile( const QStringList & ); + virtual void addDir( const QString & ); + + virtual void remove( QStringList * ); + virtual void unarchFileInternal(); + + protected slots: + virtual bool processLine( const QCString &line ); + + private: + void setHeaders(); +}; + +#endif //ZOO_H diff --git a/charselectapplet/Makefile.am b/charselectapplet/Makefile.am new file mode 100644 index 0000000..49a70a2 --- /dev/null +++ b/charselectapplet/Makefile.am @@ -0,0 +1,19 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = kcharselect_panelapplet.la + +kcharselect_panelapplet_la_SOURCES = charselectapplet.cpp + +METASOURCES = AUTO +noinst_HEADERS = charselectapplet.h + +lnkdir = $(kde_datadir)/kicker/applets +lnk_DATA = kcharselectapplet.desktop + +EXTRA_DIST = $(lnk_DATA) + +kcharselect_panelapplet_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +kcharselect_panelapplet_la_LIBADD = $(LIB_KDEUI) + +messages: + $(XGETTEXT) *.cpp *.h -o $(podir)/kcharselectapplet.pot diff --git a/charselectapplet/charselectapplet.cpp b/charselectapplet/charselectapplet.cpp new file mode 100644 index 0000000..f2fccbc --- /dev/null +++ b/charselectapplet/charselectapplet.cpp @@ -0,0 +1,366 @@ +/***************************************************************** + +Copyright (c) 2001 Matthias Elter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "charselectapplet.h" +#include "charselectapplet.moc" + +extern "C" +{ + KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile) + { + KGlobal::locale()->insertCatalogue("kcharselectapplet"); + return new CharSelectApplet(configFile, KPanelApplet::Normal, + KPanelApplet::About | KPanelApplet::Preferences, + parent, "kcharselectapplet"); + } +} + +static int cell_width = 16; +static int cell_height = 16; +static int char_count = 0; + +CharSelectApplet::CharSelectApplet(const QString& configFile, Type type, int actions, + QWidget *parent, const char *name) + : KPanelApplet(configFile, type, actions, parent, name), + _aboutData(0), _configDialog(0) +{ + // read configuration + KConfig *c = config(); + c->setGroup("General"); + cell_width = c->readNumEntry("CellWidth", cell_width); + cell_height = c->readNumEntry("CellHeight", cell_height); + QString characters = c->readEntry("Characters", "ߩ"); + + // setup layout + QHBoxLayout *_layout = new QHBoxLayout(this); + _layout->setAutoAdd(true); + + // setup table view + _table = new CharTable(this); + + // insert chars + _table->setCharacters(characters); +} + +int CharSelectApplet::widthForHeight(int height) const +{ + // number of rows depends on panel size + int rows = (height - (lineWidth() * 2))/ cell_height; + if(rows <= 0) rows = 1; + + // calculate number of columns + float c = (float) char_count / rows; + int columns = (int) ceil(c); + if(columns <= 0) columns = 1; + + _table->setRowsAndColumns(rows, columns); + + // tell kicker how much space we need + return columns * cell_width + lineWidth() * 2; +} + +int CharSelectApplet::heightForWidth(int width) const +{ + // number of columns depends on panel size + int columns = (width - (lineWidth() * 2))/ cell_width; + if(columns <= 0) columns = 1; + + // calculate number of rows we need + float r = (float) char_count / columns; + int rows = (int) ceil(r); + if(rows <= 0) rows = 1; + + _table->setRowsAndColumns(rows, columns); + + return rows * cell_height + lineWidth() *2; +} + +void CharSelectApplet::preferences() +{ + if(!_configDialog) + _configDialog = new ConfigDialog(this); + + _configDialog->setCharacters(_table->characters()); + _configDialog->setCellWidth(cell_width); + _configDialog->setCellHeight(cell_height); + _configDialog->setInitialSize(QSize(300, 100)); + _configDialog->exec(); + + cell_width = _configDialog->cellWidth(); + cell_height = _configDialog->cellHeight(); + _table->setCharacters(_configDialog->characters()); + + emit updateLayout(); + + // write configuration + KConfig *c = config(); + c->setGroup("General"); + c->writeEntry("CellWidth", cell_width); + c->writeEntry("CellHeight", cell_height); + c->writeEntry("Characters", _configDialog->characters()); + c->sync(); +} + +void CharSelectApplet::about() +{ + if(!_aboutData) { + _aboutData = new KAboutData("kcharselectapplet", I18N_NOOP("KCharSelectApplet"), "1.0", + I18N_NOOP("A character picker applet.\n" + "Used to copy single characters to the X11 clipboard.\n" + "You can paste them to an application with the middle mouse button."), + KAboutData::License_BSD, "(c) 2001, Matthias Elter"); + _aboutData->addAuthor("Matthias Elter", 0, "elter@kde.org"); + } + + KAboutApplication dialog(_aboutData); + dialog.exec(); +} + +CharTable::CharTable(QWidget* parent, const char* name) + : QFrame(parent, name), _rows(2), _cols(2), + _activeRow(-1), _activeCol(-1), + _cWidth(cell_width), _cHeight(cell_height) +{ + setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + setFocusPolicy(QWidget::NoFocus); + setBackgroundMode(QWidget::NoBackground); +} + +void CharTable::setRowsAndColumns(int r, int c) +{ + _rows = r; + _cols = c; +} + +void CharTable::insertChar(QChar c) +{ + _map.insert(char_count++, c); +} + +void CharTable::insertString(QString s) +{ + for (unsigned int i = 0; i < s.length(); i++) + insertChar(s[i]); +} + +void CharTable::setCharacters(const QString& characters) +{ + _map.clear(); + char_count = 0; + insertString(characters); +} + +QString CharTable::characters() +{ + QString characters; + for (int r = 0; r <_rows; r++) + for (int c = 0; c <_cols; c++) + characters += _map[c + r * _cols]; + + return characters; +} + +int CharTable::findRow(int y) +{ + return y / _cHeight; +} + +int CharTable::findCol(int x) +{ + return x / _cWidth; +} + +void CharTable::resizeEvent(QResizeEvent*) +{ + _cWidth = contentsRect().width() / _cols; + _cHeight = contentsRect().height() / _rows; +} + +void CharTable::paintEvent(QPaintEvent* e) +{ + QPainter p(this); + + int xoffset = contentsRect().x(); + int yoffset = contentsRect().y(); + + for (int r = 0; r <_rows; r++) { + for (int c = 0; c <_cols; c++) { + p.setViewport(xoffset + c * _cWidth, yoffset + r * _cHeight, _cWidth, _cHeight); + p.setWindow(0, 0, _cWidth, _cHeight); + paintCell(&p, r, c); + } + } + QFrame::paintEvent(e); +} + +void CharTable::repaintCell(int r, int c) +{ + QPainter p(this); + + int xoffset = contentsRect().x(); + int yoffset = contentsRect().y(); + + p.setViewport(xoffset + c * _cWidth, yoffset + r * _cHeight, _cWidth, _cHeight); + p.setWindow(0, 0, _cWidth, _cHeight); + paintCell(&p, r, c); +} + +void CharTable::paintCell(QPainter* p, int row, int col) +{ + int w = _cWidth; + int h = _cHeight; + int x2 = w - 1; + int y2 = h - 1; + + bool active = (row == _activeRow) && (col == _activeCol); + + // draw background + if (active) { + p->setBrush(QBrush(colorGroup().highlight())); + p->setPen(NoPen); + p->drawRect(0, 0, w, h); + p->setPen(colorGroup().highlightedText()); + } + else { + p->setBrush(QBrush(colorGroup().base())); + p->setPen(NoPen); + p->drawRect(0, 0, w, h); + p->setPen(colorGroup().text()); + } + + // set font + QFont f = font(); + f.setPixelSize(10); + p->setFont(f); + + // draw char + p->drawText(0, 0, x2, y2, AlignHCenter | AlignVCenter, QString(_map[col + row * _cols])); +} + +void CharTable::mousePressEvent(QMouseEvent *e) +{ + int row = findRow(e->y()); + if (row == -1) return; + + int col = findCol(e->x()); + if (col == -1) return; + + selectCell(row, col); +} + +void CharTable::mouseMoveEvent(QMouseEvent *e) +{ + if(!(e->state() & (LeftButton | RightButton | MidButton))) return; + + int row = findRow(e->y()); + if (row == -1) return; + + int col = findCol(e->x()); + if (col == -1) return; + + selectCell(row, col); +} + +void CharTable::selectCell(int row, int col) +{ + if (row >= _rows || row < 0) return; + if (col >= _cols || col < 0) return; + + int oldRow = _activeRow; + int oldCol = _activeCol; + + _activeRow = row; + _activeCol = col; + + repaintCell(oldRow, oldCol); + repaintCell(_activeRow, _activeCol); + + QClipboard *cb = QApplication::clipboard(); + QObject::disconnect( cb, SIGNAL(dataChanged()), this, SLOT(clearCell()) ); + QString text = QString(_map[col + row * _cols]); + bool oldMode = cb->selectionModeEnabled(); + cb->setSelectionMode( true ); + cb->setText( text ); + cb->setSelectionMode( false ); + cb->setText( text ); + cb->setSelectionMode( oldMode ); + QObject::connect( cb, SIGNAL(dataChanged()), this, SLOT(clearCell()) ); +} + +void CharTable::clearCell() +{ + int oldRow = _activeRow; + int oldCol = _activeCol; + + _activeRow = -1; + _activeCol = -1; + + repaintCell(oldRow, oldCol); + + QObject::disconnect( QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clearCell()) ); +} + + +ConfigDialog::ConfigDialog(QWidget* parent, const char* name) + : KDialogBase(parent, name, true, i18n("Configuration"), + Ok | Cancel, Ok, true) +{ + QVBox *page = makeVBoxMainWidget(); + + QHBox *whbox = new QHBox(page); + QHBox *hhbox = new QHBox(page); + QHBox *chbox = new QHBox(page); + + QLabel *wlabel = new QLabel(i18n("Cell width:"), whbox); + QLabel *hlabel = new QLabel(i18n("Cell height:"), hhbox); + (void) new QLabel(i18n("Characters:"), chbox); + + _widthSpinBox = new QSpinBox(whbox); + _widthSpinBox->setMinValue(1); + _heightSpinBox = new QSpinBox(hhbox); + _heightSpinBox->setMinValue(1); + _characterInput = new KLineEdit(chbox); + + whbox->setSpacing(KDialog::spacingHint()); + hhbox->setSpacing(KDialog::spacingHint()); + chbox->setSpacing(KDialog::spacingHint()); + + whbox->setStretchFactor(wlabel, 2); + hhbox->setStretchFactor(hlabel, 2); + chbox->setStretchFactor(_characterInput, 2); +} diff --git a/charselectapplet/charselectapplet.h b/charselectapplet/charselectapplet.h new file mode 100644 index 0000000..b54dc55 --- /dev/null +++ b/charselectapplet/charselectapplet.h @@ -0,0 +1,115 @@ +/***************************************************************** + +Copyright (c) 2001 Matthias Elter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef __charselectapplet_h__ +#define __charselectapplet_h__ + +#include + +#include +#include + +class QSpinBox; +class KLineEdit; +class KAboutData; + +class ConfigDialog : public KDialogBase +{ + Q_OBJECT + +public: + ConfigDialog(QWidget* parent = 0, const char* name = 0); + + void setCharacters(const QString& s) { _characterInput->setText(s); } + void setCellWidth(int w) { _widthSpinBox->setValue(w); } + void setCellHeight(int h) { _heightSpinBox->setValue(h); } + + QString characters() { return _characterInput->text(); } + int cellWidth() { return _widthSpinBox->value(); } + int cellHeight() { return _heightSpinBox->value(); } + +private: + QSpinBox *_widthSpinBox; + QSpinBox *_heightSpinBox; + KLineEdit *_characterInput; +}; + +class CharTable : public QFrame +{ + Q_OBJECT + +public: + CharTable(QWidget* parent = 0, const char* name = 0); + + void setRowsAndColumns(int, int); + + void setCharacters(const QString&); + QString characters(); + +protected: + void paintEvent(QPaintEvent*); + void resizeEvent(QResizeEvent*); + void mousePressEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + + void paintCell(QPainter*, int, int); + void repaintCell(int, int); + void selectCell(int row, int col); + + void insertString(QString s); + void insertChar(QChar c); + + int findRow(int y); + int findCol(int x); + +protected slots: + void clearCell(); +private: + int _rows, _cols; + int _activeRow, _activeCol; + int _cWidth, _cHeight; + int _charcount; + QMap _map; +}; + +class CharSelectApplet : public KPanelApplet +{ + Q_OBJECT + +public: + CharSelectApplet(const QString& configFile, Type t = Stretch, int actions = 0, + QWidget *parent = 0, const char *name = 0); + + int widthForHeight(int height) const; + int heightForWidth(int width) const; + + void preferences(); + void about(); + +private: + CharTable *_table; + KAboutData *_aboutData; + ConfigDialog *_configDialog; +}; + +#endif diff --git a/charselectapplet/kcharselectapplet.desktop b/charselectapplet/kcharselectapplet.desktop new file mode 100644 index 0000000..029b5be --- /dev/null +++ b/charselectapplet/kcharselectapplet.desktop @@ -0,0 +1,100 @@ +[Desktop Entry] +Name=Character Selector +Name[ar]=أداة اختيار الرموز +Name[az]=Xarakter Seçici +Name[bg]=Избор на знаци +Name[br]=Dibaber arouezenn +Name[bs]=Izbor znakova +Name[ca]=Selector de caràcters +Name[cs]=Vyběr znaků +Name[cy]=Dewisydd Nod +Name[da]=Tegnvælger +Name[de]=Tabelle zur Zeichenauswahl +Name[el]=Επιλογέας χαρακτήρων +Name[eo]=Elektilo por signoj +Name[es]=Selector de caracteres +Name[et]=Sümbolite valija +Name[eu]=Karaktere autatzailea +Name[fa]=گزینندۀ نویسه +Name[fi]=Merkkivalitsin +Name[fr]=Sélecteur de caractères +Name[ga]=Roghnóir Carachtar +Name[gl]=Selector de Caracteres +Name[he]=בוחר תווים +Name[hu]=KCharselectApplet +Name[id]=Pemilih Karakter +Name[is]=Stafaval +Name[it]=Selettore di caratteri +Name[ja]=文字の選択 +Name[ka]=სიმბოლოთა შემრჩეველი +Name[kk]=Таңба тергіш +Name[km]=កម្មវិធី​ជ្រើស​តួអក្សរ +Name[nb]=Tegnvelger +Name[nds]=Tekenutwähler +Name[ne]=क्यारेक्टर चयनकर्ता +Name[nl]=Speciale tekens +Name[nn]=Teiknveljar +Name[pa]=ਅੱਖਰ ਚੋਣਕਾਰ +Name[pl]=Wybór znaku +Name[pt]=Selector de Caracteres +Name[pt_BR]=Seletor de Caracteres +Name[ru]=Выбор символа +Name[sk]=Voľba znakov +Name[sl]=Izbiranje znakov +Name[sr]=Бирач знакова +Name[sr@Latn]=Birač znakova +Name[sv]=Teckenväljare +Name[ta]= எழுத்து தேர்ந்தெடுப்பான் +Name[uk]=Вибір символів +Name[uz]=Harf tanlagich +Name[uz@cyrillic]=Ҳарф танлагич +Name[zh_CN]=字符选择器 +Name[zh_TW]=字元選擇器 +Icon=kcharselect +X-KDE-Library=kcharselect_panelapplet +X-KDE-UniqueApplet=true +Comment=Pick foreign and special characters for clipboard +Comment[ar]=يلتقط الرموز الأجنبية والخاصة من أجل الحافظة +Comment[bg]=Избор на чужди и специални знаци за копиране чрез системния буфер +Comment[bs]=Izaberite posebne i međunarodne znakove sa spiska +Comment[ca]=Selecciona caràcters estranger i especials pel porta-retalls +Comment[cs]=Výběr cizích a speciálních znaků do schránky +Comment[da]=Vælg fremmede tegn og specialtegn for klippebordet +Comment[de]=Fremdsprachige und Sonderzeichen in die Zwischenablage kopieren +Comment[el]=Επιλέξτε ειδικούς χαρακτήρες και χαρακτήρες άλλης γλώσσας για το πρόχειρο +Comment[es]=Seleccionar caracteres extranjeros y especiales para el portapapeles +Comment[et]=Võõr- ja erisümbolite valimine lõikepuhvrisse +Comment[eu]=Hautatu atzerriko karaketereak eta karaketere bereziak arbelarentzat +Comment[fa]=انتخاب نویسه‌های خارجی و ویژه برای تخته یادداشت +Comment[fi]=Poimi erikoismerkkejä leikepöydälle +Comment[fr]=Sélectionner des caractères étrangers et spéciaux +Comment[ga]=Roghnaigh carachtair iasachta agus speisialta don ghearrthaisce +Comment[he]=בחר תווים זרים ומיוחדים להדבקה +Comment[hu]=Más nyelvi és speciális karakterek másolása a vágólapra +Comment[is]=Velur útlenda og sérstaka stafi fyrir klippispjaldið +Comment[it]=Seleziona caratteri speciali e stranieri per gli appunti +Comment[ja]=クリップボードに外国語文字または特殊文字をピックアップする +Comment[ka]=გაცვლის ბუფერისთვის უცხოური და სპეციალური სიმბოლოების აღება +Comment[kk]=Пернетақтада жоқ таңбаларды алмасу буферіне теріп алу +Comment[km]=ជ្រើស​តួអក្សរ​បរទេស និង​ពិសេស​សម្រាប់​ក្តារតម្បៀតខ្ទាស់ +Comment[lt]=Parinkite užsienietiškus ar ypatingus simbolius talpyklei +Comment[nb]=Hent inn fremmede tegn og spesialtegn til utklippstavla +Comment[nds]=Frömdspraak- un Sünnertekens na de Twischenaflaag koperen +Comment[ne]=क्लिबोर्डका लागि विदेशी र विशेष क्यारेक्टर छान्नुहोस् +Comment[nl]=Buitenlandse en speciale tekens van klembord halen +Comment[nn]=Kopier spesialteikn og bokstavar frå framande språk til utklippstavla +Comment[pl]=Wstawia znaki specjalne albo diakrytyczne do schowka +Comment[pt]=Escolher caracteres especiais e estrangeiros para a área de transferência +Comment[pt_BR]=Lista de caracteres especiais para a área de transferência +Comment[ru]=Выбрать и поместить в буфер обмена специальные символы +Comment[sk]=Vložte do schánky cudzie a špeciálne znaky +Comment[sl]=Poberi tuje in posebne znake za na odložišče +Comment[sr]=Бира стране и специјалне знакове за клипборд +Comment[sr@Latn]=Bira strane i specijalne znakove za klipbord +Comment[sv]=Välj främmande tecken och specialtecken för klippbordet +Comment[tr]=Yabancı ve özel karakterleri panoya kopyalar +Comment[uk]=Вибрати і вставити в кишеню іноземні та спеціальні символи +Comment[uz]=Harf va maxsus belgilarni xotiraga olish vositasi +Comment[uz@cyrillic]=Ҳарф ва махсус белгиларни хотирага олиш воситаси +Comment[zh_CN]=将外语和特殊字符拾取到剪贴板 +Comment[zh_TW]=為剪貼簿選擇外國與特殊字元 diff --git a/configure.in.in b/configure.in.in new file mode 100644 index 0000000..d031440 --- /dev/null +++ b/configure.in.in @@ -0,0 +1,12 @@ +#MIN_CONFIG +KDE_ENABLE_HIDDEN_VISIBILITY +KDE_INIT_DOXYGEN([KDE Utils API Reference], [Version $VERSION]) + +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_CHECK_HEADERS(fcntl.h sys/sysctl.h sys/param.h sys/time.h sys/types.h sys/user.h sys/vmmeter.h sys/resource.h vm/vmparam.h unistd.h) + +AC_CHECK_SETENV +AC_CHECK_UNSETENV + +CXXFLAGS="$CXXFLAGS $KDE_DEFAULT_CXXFLAGS" diff --git a/doc/KRegExpEditor/Makefile.am b/doc/KRegExpEditor/Makefile.am new file mode 100644 index 0000000..6872b30 --- /dev/null +++ b/doc/KRegExpEditor/Makefile.am @@ -0,0 +1,5 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + +docdir = $(kde_htmldir)/$(KDE_LANG)/KRegExpEditor diff --git a/doc/KRegExpEditor/altn.png b/doc/KRegExpEditor/altn.png new file mode 100644 index 0000000..900a1e9 Binary files /dev/null and b/doc/KRegExpEditor/altn.png differ diff --git a/doc/KRegExpEditor/altntool.png b/doc/KRegExpEditor/altntool.png new file mode 100644 index 0000000..2d450e8 Binary files /dev/null and b/doc/KRegExpEditor/altntool.png differ diff --git a/doc/KRegExpEditor/anychar.png b/doc/KRegExpEditor/anychar.png new file mode 100644 index 0000000..11048ca Binary files /dev/null and b/doc/KRegExpEditor/anychar.png differ diff --git a/doc/KRegExpEditor/anychartool.png b/doc/KRegExpEditor/anychartool.png new file mode 100644 index 0000000..08425d3 Binary files /dev/null and b/doc/KRegExpEditor/anychartool.png differ diff --git a/doc/KRegExpEditor/begline.png b/doc/KRegExpEditor/begline.png new file mode 100644 index 0000000..3465a9e Binary files /dev/null and b/doc/KRegExpEditor/begline.png differ diff --git a/doc/KRegExpEditor/boundarytools.png b/doc/KRegExpEditor/boundarytools.png new file mode 100644 index 0000000..c93d764 Binary files /dev/null and b/doc/KRegExpEditor/boundarytools.png differ diff --git a/doc/KRegExpEditor/characters.png b/doc/KRegExpEditor/characters.png new file mode 100644 index 0000000..7f218bf Binary files /dev/null and b/doc/KRegExpEditor/characters.png differ diff --git a/doc/KRegExpEditor/charactertool.png b/doc/KRegExpEditor/charactertool.png new file mode 100644 index 0000000..1690018 Binary files /dev/null and b/doc/KRegExpEditor/charactertool.png differ diff --git a/doc/KRegExpEditor/compound.png b/doc/KRegExpEditor/compound.png new file mode 100644 index 0000000..a56c9bb Binary files /dev/null and b/doc/KRegExpEditor/compound.png differ diff --git a/doc/KRegExpEditor/compoundtool.png b/doc/KRegExpEditor/compoundtool.png new file mode 100644 index 0000000..d1ad43c Binary files /dev/null and b/doc/KRegExpEditor/compoundtool.png differ diff --git a/doc/KRegExpEditor/endline.png b/doc/KRegExpEditor/endline.png new file mode 100644 index 0000000..29b512e Binary files /dev/null and b/doc/KRegExpEditor/endline.png differ diff --git a/doc/KRegExpEditor/index.docbook b/doc/KRegExpEditor/index.docbook new file mode 100644 index 0000000..fda544f --- /dev/null +++ b/doc/KRegExpEditor/index.docbook @@ -0,0 +1,652 @@ + + + +]> + + + + + The Regular Expression Editor Manual + + + + Jesper K. + Pedersen +
blackie@kde.org
+
+
+ + 2001-07-03 + 0.1 + + &underFDL; + + + 2001 + Jesper K. Pedersen + + + + This Handbook describes the Regular Expression Editor widget + + + + KDE + regular expression + +
+ + + + + + Introduction + + + + The regular expression editor is an editor for editing regular expression + in a graphical style (in contrast to the ASCII syntax). Traditionally + regular expressions have been typed in the ASCII syntax, which for example + looks like ^.*kde\b. The major drawbacks of + this style are: + + It is hard to understand for + non-programmers. + + It requires that you escape + certain symbols (to match a star for example, you need to type + \*). + + It requires that you remember rules for + precedence (What does x|y* + match? a single x or a number of + y, OR a number of + x and y's mixed?) + + + + + The regular expression editor, on the other hand, lets you + draw your regular expression in an unambiguous + way. The editor solves at least item two and three above. It might not make + regular expressions available for the non-programmers, though only tests by + users can tell that. So, if are you a non programmer, who has gained the + power of regular expression from this editor, then please + let me know. + + + + + + + + + What is a Regular Expression + + A regular expression is a way to specify + conditions to be fulfilled for a situation + in mind. Normally when you search in a text editor you specify + the text to search for literally, using a + regular expression, on the other hand, you tell what a given + match would look like. Examples of this include I'm + searching for the word KDE, but only at the beginning of the + line, or I'm searching for the word + the, but it must stand on its own, + or I'm searching for files starting with the word + test, followed by a number of digits, for + example test12, test107 + and test007 + + You build regular expressions from smaller regular + expressions, just like you build large Lego toys from smaller + subparts. As in the Lego world, there are a number of basic + building blocks. In the following I will describe each of these + basic building blocks using a number of examples. + + + Searching for normal text. + If you just want to search for a given text, a then regular + expression is definitely not a good choice. The reason for this is that + regular expressions assign special meaning to some characters. This + includes the following characters: .*|$. Thus if you want to + search for the text kde. (i.e. the characters + kde followed by a period), then you would need to + specify this as kde\.The regular + expression editor solves this problem by taking care of escape rules for + you. Writing \. rather than just + . is called escaping. + + + + + Matching URLs + When you select something looking like a URL in KDE, then the + program klipper will offer to start + konqueror with the selected URL. + + Klipper does this by matching the selection + against several different regular expressions, when one of the regular + expressions matches, the accommodating command will be offered. + + The regular expression for URLs says (among other things), that the + selection must start with the text http://. This is + described using regular expressions by prefixing the text + http:// with a hat (the ^ + character). + + The above is an example of matching positions using regular + expressions. Similar, the position end-of-line can + be matched using the character $ (i.e. a dollar + sign). + + + + Searching for the word <literal>the</literal>, but not + <emphasis>the</emphasis><literal>re</literal>, + <literal>brea</literal><emphasis>the</emphasis> or + <literal>ano</literal><emphasis>the</emphasis><literal>r</literal> + Two extra position types can be matches in the above way, + namely the position at a word boundary, and + the position at a non-word + boundary. The positions are specified using the text + \b (for word-boundary) and \B (for + non-word boundary) + + Thus, searching for the word the can be done + using the regular expression \bthe\b. This specifies + that we are searching for the with no letters on each + side of it (i.e. with a word boundary on each side) + + The four position matching regular expressions are inserted in the + regular expression editor using four + different positions tool + + + + Searching for either <literal>this</literal> or <literal>that</literal> + Imagine that you want to run through your document searching for + either the word this or the word + that. With a normal search method you could do this in + two sweeps, the first time around, you would search for + this, and the second time around you would search for + that. + + Using regular expression searches you would search for both in the + same sweep. You do this by searching for + this|that. I.e. separating the two words with a + vertical bar.Note on each side of the vertical bar is a + regular expression, so this feature is not only for searching for two + different pieces of text, but for searching for two different regular + expressions. + + In the regular expression editor you do not write the vertical bar + yourself, but instead select the alternative + tool, and insert the smaller regular expressions above each other. + + + + Matching anything + Regular expressions are often compared to wildcard matching in the + shell - that is the capability to specify a number of files using the + asterisk. You will most likely recognize wildcard matching from the + following examples: + + ls *.txt - here *.txt is + the shell wildcard matching every file ending with the + .txt extension. + cat test??.res - matching every file starting with + test followed by two arbitrary characters, and finally + followed by the test .res + + + + In the shell the asterisk matches any character any number of + times. In other words, the asterisk matches anything. + This is written like .* with regular expression + syntax. The dot matches any single character, i.e. just + one character, and the asterisk, says that the + regular expression prior to it should be matched any number of + times. Together this says any single character any number of + times. + + This may seem overly complicated, but when you get the larger + picture you will see the power. Let me show you another basic regular + expression: a. The letter a on its + own is a regular expression that matches a single letter, namely the + letter a. If we combine this with the asterisk, + i.e. a*, then we have a regular expression matching + any number of a's. + + We can combine several regular expression after each + other, for example ba(na)*. + (na)* just says that what is inside + the parenthesis is repeated any number of times. + Imagine you had typed this regular expression into the search field in a + text editor, then you would have found the following words (among + others): ba, bana, + banana, bananananananana + + + Given the information above, it hopefully isn't hard for you to write the + shell wildcard test??.res as a regular expression + Answer: test..\.res. The dot on its own is any + character. To match a single dot you must write + \.This is called escaping. In + other word, the regular expression \. matches a dot, + while a dot on its own matches any character. + + In the regular expression editor, a repeated regular expression is + created using the repeat tool + + + + Replacing <literal>&</literal> with + <literal>&amp;</literal> in a HTML document In + HTML the special character & must be + written as &amp; - this is similar to + escaping in regular expressions. + + Imagine that you have written an HTML document in a normal editor + (e.g. XEmacs or Kate), and you totally forgot about this rule. What you + would do when realized your mistake was to replace every occurrences of + & with &amp;. + + This can easily be done using normal search and replace, + there is, however, one glitch. Imagine that you did remember + this rule - just a bit - and did it right + in some places. Replacing unconditionally would result in + &amp; being replaced with + &amp;amp; + + What you really want to say is that & should + only be replaced if it is not followed by the letters + amp;. You can do this using regular expressions using + positive lookahead. + + The regular expression, which only matches an ampersand if it is + not followed by the letters amp; looks as follows: + &(?!amp;). This is, of course, easier to read using + the regular expression editor, where you would use the + lookahead tools. + + + + + + + + + Using the Regular Expression Editor + + + This chapter will tell you about how the regular expression editor works. + + + + + + + The organization of the screen + + + + + + The most important part of the editor is of course the editing + area, this is the area where you draw your regular expression. This + area is the larger gray one in the middle. + + Above the editing area you have two Toolbars, the first one + contains the editing actions - + much like drawing tools in a drawing program. The second Toolbar + contains the whats this button, and buttons + for undo and redo. + + Below the editing area you find the regular expression + currently build, in the so called ascii syntax. The ascii syntax + is updated while you edit the regular expression in the graphical + editor. If you rather want to update the ascii syntax then please + do, the graphical editor is updated on the fly to reflect your + changes. + + Finally to the left of the editor area you will find a number + of pre-built regular expressions. They serve two purposes: (1) When + you load the editor with a regular expression then this regular + expression is made nicer or more comprehensive + by replacing common regular expressions. In the screen dump above, + you can see how the ascii syntax ".*" have been replaced with a box + saying "anything". (2) When you insert regular expression you may + find building blocks for your own regular expression from the set of + pre build regular expressions. See the section on + user defined regular + expressions to learn how to save your own regular expressions. + + + + + + + Editing Tools + The text in this section expects that you have read the chapter + on what a regular expression + is, or have previous knowledge on this subject. + + All the editing tools are located in the tool bar above + editing area. Each of them will be described in the following. + + + + + Selection Tool + + + + The selection tool is used to + mark elements for cut-and-paste and drag-and-drop. This is very + similar to a selection tool in any drawing program. + + + + + Text Tool + + + + + + + + + + Using this tool you will insert normal text to match. The + text is matched literally, i.e. you do not have to worry about + escaping of special characters. In the example above the following + regular expression will be build: abc\*\\\) + + + + + Character Tool + + + + + + + + Using this tool you insert + character ranges. Examples includes what in ASCII text says + [0-9], [^a-zA-Z,_]. When + inserting an item with this tool a dialog will appear, in which + you specify the character ranges. + + See description of repeated + regular expressions. + + + + + Any Character Tool + + + + + + + This is the regular expression "dot" (.). It matches any + single character. + + + + + + + + Repeat Tool + + + + + + + + This is the repeated + elements. This includes what in ASCII syntax is represented + using an asterix (*), a plus (+), a question mark (?), and + ranges ({3,5}). When you insert an item using this tool, a + dialog will appear asking for the number of times to + repeat. + + You specify what to repeat by drawing the repeated content + inside the box which this tool inserts. + + Repeated elements can both be built from the outside in and + the inside + out. That is you can first draw what to be repeated, select it + and use the repeat tool to repeat it. Alternatively you can + first insert the repeat element, and draw what is to be repeated + inside it. + + See description on the repeated + regular expressions. + + + + + + Alternative Tool + + + + + + + This is the alternative regular expression (|). You specify + the alternatives by drawing each alternative on top of each other + inside the box that this tool inserts. + + See description on alternative + regular expressions + + + + + + Compound Tool + + + + + + + The compound tool does not represent any regular + expressions. It is used to group other sub parts together in a + box, which easily can be collapsed to only its title. This can be + seen in the right part of the screen dump above. + + + + + + + Line Start/End Tools + + + + + + + + + + The line start and line end tools matches the start of the + line, and the end of the line respectively. The regular + expression in the screen dump above thus matches lines only + matches spaces. + + See description of position + regular expressions. + + + + + + + Word (Non)Boundary Tools + + + + + + + + + The boundary tools matches a word boundary respectively a + non-word boundary. The regular expression in the screen dump thus + matches any words starting with the. The word + the itself is, however, not matched. + + See description of boundary + regular expressions. + + + + + + + Positive/Negative Lookahead + Tools + + + + + + + + + The look ahead tools either specify a positive or negative + regular expression to match. The match is, however, not part of + the total match. + + Note: You are only allowed to place lookaheads at the end + of the regular expressions. The Regular Expression Editor widget + does not enforce this. + + See description of look ahead + regular expressions. + + + + + + + + User Defined Regular Expressions + Located at the left of the editing area is a list box + containing user defined regular expressions. Some regular + expressions are pre-installed with your KDE installation, while + others you can save yourself. + + These regular expression serves two purposes + (see detailed + description), namely (1) to offer you a set of building + block and (2) to make common regular expressions prettier. + + You can save your own regular expressions by right clicking the + mouse button in the editing area, and choosing Save Regular + Expression. + + If the regular expression you save is within a + compound container then the + regular expression will take part in making subsequent regular + expressions prettier. + + User defined regular expressions can be deleted or renamed by + pressing the right mouse button on top of the regular expression in + question in the list box. + + + + + + + + Reporting bugs and Suggesting Features + Bug reports and feature requests should be submitted through the + KDE Bug Tracking System. Before you report a bug or suggest a feature, + please check that it hasn't already been + reported/suggested. + + + + + + + Frequently Asked Questions + + Does the regular expression editor support back references? + No currently this is not supported. It is planned for the next + version. + + + + Does the regular expression editor support showing matches? + No, hopefully this will be available in the next version. + + + + I'm the author of a KDE program, how can I use this widget in + my application? + See The documentation for the class KRegExpEditorInterface. + + + + I can't find the <emphasis>Edit Regular expression</emphasis> button in for example + konqueror on another KDE3 installation, why? + The regular expression widget is located in the package + KDE-utils. If you do not have this package installed, then the + edit regular expressions buttons will not + appear in the programs. + + + + + + + + Credits and Licenses + + + Documentation is copyright 2001, Jesper K. Pedersen + blackie@kde.org + + + + &underGPL; + &underFDL; + + + + +
+ + diff --git a/doc/KRegExpEditor/linestartendtool.png b/doc/KRegExpEditor/linestartendtool.png new file mode 100644 index 0000000..e7c1bd8 Binary files /dev/null and b/doc/KRegExpEditor/linestartendtool.png differ diff --git a/doc/KRegExpEditor/lookaheadtools.png b/doc/KRegExpEditor/lookaheadtools.png new file mode 100644 index 0000000..a986f50 Binary files /dev/null and b/doc/KRegExpEditor/lookaheadtools.png differ diff --git a/doc/KRegExpEditor/neglookahead.png b/doc/KRegExpEditor/neglookahead.png new file mode 100644 index 0000000..3cc0291 Binary files /dev/null and b/doc/KRegExpEditor/neglookahead.png differ diff --git a/doc/KRegExpEditor/nonwordboundary.png b/doc/KRegExpEditor/nonwordboundary.png new file mode 100644 index 0000000..b22f4d4 Binary files /dev/null and b/doc/KRegExpEditor/nonwordboundary.png differ diff --git a/doc/KRegExpEditor/poslookahead.png b/doc/KRegExpEditor/poslookahead.png new file mode 100644 index 0000000..492692b Binary files /dev/null and b/doc/KRegExpEditor/poslookahead.png differ diff --git a/doc/KRegExpEditor/repeat.png b/doc/KRegExpEditor/repeat.png new file mode 100644 index 0000000..2646111 Binary files /dev/null and b/doc/KRegExpEditor/repeat.png differ diff --git a/doc/KRegExpEditor/repeattool.png b/doc/KRegExpEditor/repeattool.png new file mode 100644 index 0000000..5d525e9 Binary files /dev/null and b/doc/KRegExpEditor/repeattool.png differ diff --git a/doc/KRegExpEditor/select.png b/doc/KRegExpEditor/select.png new file mode 100644 index 0000000..e04ab17 Binary files /dev/null and b/doc/KRegExpEditor/select.png differ diff --git a/doc/KRegExpEditor/text.png b/doc/KRegExpEditor/text.png new file mode 100644 index 0000000..8b256ca Binary files /dev/null and b/doc/KRegExpEditor/text.png differ diff --git a/doc/KRegExpEditor/texttool.png b/doc/KRegExpEditor/texttool.png new file mode 100644 index 0000000..8c92526 Binary files /dev/null and b/doc/KRegExpEditor/texttool.png differ diff --git a/doc/KRegExpEditor/theEditor.png b/doc/KRegExpEditor/theEditor.png new file mode 100644 index 0000000..4e2468f Binary files /dev/null and b/doc/KRegExpEditor/theEditor.png differ diff --git a/doc/KRegExpEditor/wordboundary.png b/doc/KRegExpEditor/wordboundary.png new file mode 100644 index 0000000..0e89a6b Binary files /dev/null and b/doc/KRegExpEditor/wordboundary.png differ diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..6812bd2 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,5 @@ + +KDE_LANG = en +KDE_DOCS = AUTO +SUBDIRS = $(AUTODIRS) + diff --git a/doc/ark/Makefile.am b/doc/ark/Makefile.am new file mode 100644 index 0000000..bed8857 --- /dev/null +++ b/doc/ark/Makefile.am @@ -0,0 +1,5 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + +KDE_MANS = AUTO \ No newline at end of file diff --git a/doc/ark/index.docbook b/doc/ark/index.docbook new file mode 100644 index 0000000..224bc29 --- /dev/null +++ b/doc/ark/index.docbook @@ -0,0 +1,793 @@ + + + + + +]> + + + + +The &ark; Handbook + + + +&Matt.Johnston; &Matt.Johnston.mail; + + + + + + +2000 +Matt Johnston + + + +2004 +Henrique Pinto + + + +&FDLNotice; + +2004-06-19 +2.3.1 + + +&ark; is an archive manager for &kde;. + + +KDE +gzip +gunzip +tar +archive +zip +compression +lha +kdeutils +ark + + + + +Introduction + +&ark; is a program for managing various archive formats within the +&kde; environment. Archives can be viewed, extracted, created and +modified from within &ark;. The program can handle various formats such +as tar, gzip, +bzip2, zip, rar and +lha (if appropriate command-line programs are +installed). &ark; can work closely with &konqueror; in the &kde; +environment to handle archives, if you install the &konqueror; Integration plugin available in the kdeaddons package. + + + + +Using &ark; + + +Opening Archives + +To open an archive in &ark;, choose +Open from the File +menu. You can also open archive files by dragging and dropping from +&konqueror;. Archive files should be associated with &ark;, so you can +also right click a file in &konqueror; and +select &ark; to open it. + + + + +Working with Files + +Once an archive has been opened, you can perform various +operations on the files inside the archive. By +right clicking on a file within the +archive, or selecting a file and using the Action +menu, you can choose what you want to do: + + + +Extract will extract the file to a location you +specify on disk. + + +Delete will remove the currently +selected file(s) from the archive. + + +View will open the file in the integrated viewer, or in the default +viewer program in case the integrated viewer cannot view the file, or you have disabled it in the Configuration Window. + + +Open With... allows you to open the +file in a program you choose. + + +Edit With... will open the file a +program you choose. The difference between this and Open +With... is that any changes you make will be saved to the +file in the archive. + + + + + + +Extracting Archives + +Once an archive has been opened in &ark;, it can be extracted. To +extract files from an archive, you can either select +Extract... from the +Action menu or right click on the file. The Extract +dialog allows you to select where you will extract files to. You can +also select which files to extract: + + + +Current extracts the most recently +selected file. If multiple files are selected, only the most recently +selected one will be extracted. + + +All extracts the entire contents of the +archive. + + +Selected Files extracts all the files +which have been selected. + + +Pattern allows you to specify which +files will be extracted, corresponding to certain patterns, ⪚ +*.txt or *.jpg. Note that you can only use one +pattern at a time. + + + +You can specify the folder to extract files to in the +Extract to: text box. The default location is the +folder the archive is in. You may also choose to have the folder that you +extract into open in &konqueror; once the extraction is complete. + + + + +Creating Archives and Adding Files + +To create a new archive in &ark;, choose +New from the File +menu. + +You can then type the name of the archive, with the appropriate +extension (tar.gz, zip, bz2 +&etc;). To add files to the archive, choose Add +File... from the Action menu. If you +want to add an entire folder to an archive, choose Add +Folder... from the Action menu. + +An alternative way to add files to the archive is to drag a file +from &konqueror; or the desktop into the main &ark; window, and it will +be added to the current archive. + + + + + + +Configuring &ark; + + +General Settings + + + + +Use integrated viewer + +Use the integrated viewer to view files, if possible. + + + + +Enable Konqueror integration + +Enable the plugin for extracting or adding files to archives through Konqueror context menus. +This option only works if the Konqueror integration plugin from kdeaddons is installed on your system. + + + + + + + + +File Addition Settings + +Many of these options are only configurable for specific archive +formats. Other formats may behave either way and are not +configurable. + + + +Replace old files only with newer +files + +If you add filenames that already exist in an archive, only +replace them if the added files are newer than the ones already +present in the archive. + + + + +Force MS-DOS short filenames (Zip) + +Force names to the DOS 8.3 format. +Affects only zip files + + + + +Translate LF to DOS CRLF (Zip) + +Convert the line endings in text files to DOS format from UNIX +format. +Affects only zip files + + + + +Store symlinks as links (Zip, Rar) + +Save links inside the archive, instead of following them and +including the files being linked to. +Affects zip and rar archives. + + + + +Recursively add subfolders (Zip, +Rar) + +If you add a folder to an archive, also add any +subfolders inside. Affects zip and rar archives + + + + + + + +Extraction Settings + +Many of these options are only configurable for specific archive +formats. Other formats may behave either way and are not +configurable. + + + +Overwrite files (Zip, Tar, Zoo, Rar) + +Overwrite any files that have matching names on disk with the +one from the archive. + + + + +Preserve permissions (Tar) + +Save the user, group, and permission settings on files. Use +with care, as this may result in files being extracted that do not +belong to any valid user on your computer. + + + + +Ignore folder names (Zip) + +Extract all the files into the extraction folder, ignoring +any folder structure in the archive. + + + + +Convert filenames to lowercase (Zip, Rar) +Convert filenames to uppercase (Rar) + +Extract all files with all lowercase (or uppercase) names. + + + + + + + + +Folders + + + +Folders + +This shows the Folders dialog box, so you + can choose the default folders. You can configure a Common folder that will be used for all options, use the last used folder, or a custom folder. + + + + + + + + + +Command Reference + + +The <guimenu>File</guimenu> Menu + + + + &Ctrl;N +File +New + +Creates a new archive + + + + + &Ctrl;O +File +Open + +Opens an archive + + + + + +File +Open Recent + + +Shows a list of recent archives to choose +from + + + + + +File +New Window + + +Opens a new &ark; window + + + + + +F5 +File +Reload + + +Loads the current archive again from disk. This will +refresh &ark;'s view if another program has made changes to the +archive. + + + + + +File +Save As + + +Allows you to save the current archive under a new file +name + + + + + + +&Ctrl;W + + +File +Close + + +Closes the current archive + + + + + +&Ctrl; +Q +File +Quit + + +Closes &ark; + + + + + + +The <guimenu>Edit</guimenu> Menu + + + + + +Edit +Select... + + +Lets you select files according to their +filename. For example, you could use *.txt to select all text files. Note that you +can't use more than one filter at a time. + + + + + +&Ctrl; +A +Edit +Select All + + +Selects all the files in the archive + + + + + +Edit +Deselect All + + +Unselects all the files in the archive + + + + + +Edit +Invert Selection + + +Reverses which files are selected. Selected files become +unselected, and unselected files are selected. + + + + + +Edit +View Shell Output + + +Displays the Shell Output box, which +shows you the output of the most recent command(s) run +by &ark;. This is sometimes useful if you are having problems and want +to troubleshoot. + + + + + + + + +The <guimenu>Action</guimenu> Menu + + + + + +Action +Add File... + + +Shows the Select Files to Add dialog box, +where you can select files. Hold down &Ctrl; and click to select +multiple files. To go up a folder, +right click the folder box, and you can +choose Up (this will probably be improved +soon). The Advanced tab has options which are +specific to the type or archive you are working with. + + + + + +Action +Add Folder... + + +Shows the Add Folder... dialog box, where you +can choose a folder to add. Just choose a folder +and choose Open. + + + + + +Action +Delete + + +Removes the currently selected files from the +archive. + + + + + +Action +Extract + + +Shows the Extract dialog box, which allows +you to select where you will extract files to. You can +also select which files to extract: + + + +Current extracts the most recently selected +file. If multiple files are selected, only the most recently selected +one will be extracted. + + +All extracts the entire contents of the +archive. + + +Selected Files extracts all the files which +have been selected. + + +Pattern allows you to specify which files +will be extracted, corresponding to certain patterns, ⪚ +*.txt or *.jpg Note that you can only use one +pattern at a time. + + + + +You can specify the folder to extract files to in the +Extract to: text box. The default location is the +folder the archive is in. You may also choose to have the folder that you +extract into open in &konqueror; once the extraction is complete. + + + + + +Action +View + + +Opens the currently selected file in the associated viewer +program. + + + + + +Action +Open With... + + +Opens the currently selected file in a program you +choose. The Open With... dialog box lets +you choose which program to use. + + + + + +Action +Edit With... + + +Opens the currently selected file in a program you +choose. Any changes you make in the editor program will be +reflected in the archive, as it will be updated. + + + + + + + + +The <guimenu>Settings</guimenu> Menu + + + + + +Settings +Show/Hide Toolbar + + +Toggles whether the toolbar is displayed. + + + + + +Settings +Show/Hide Statusbar + + +Toggles whether the status bar is +displayed. + + + + + +Settings +Show/Hide Search Bar + + +Toggles whether the search bar is +displayed. + + + + + +Settings +Configure Shortcuts... + + +Displays the Configure Shortcuts dialog +box. This lets you choose shortcut keys for various menu +items. To change a shortcut, select an action from the list, +and then choose which keystroke to use. Clicking on the bottom right +hand Key button lets you choose which specific +key to use. Just press the new key. + + + + + +Settings +Configure Toolbars... + + +Displays a &kde; standard dialog where you can configure the +toolbar icons. + + + + + +Settings +Configure Ark... + + + +This opens the &ark; configuration dialog. The dialog contains four +modules (General, Addition, Extraction and Folders). Configuring &ark; is covered in the section Configuration + + + + + + + +The <guimenu>Help</guimenu> Menu + +&help.menu.documentation; + + + + + + + +Credits and License + +&ark; is Copyright © 1997-2004, The Various &ark; Developers + + +Authors: +Helio Chissini de Castro +helio@conectiva.com.br +Georg Robbers +Georg.Robbers@urz.uni-hd.de +Henrique Pinto +henrique.pinto@kdemail.net +Roberto Selbach Teixeira +maragato@kde.org +Robert Palmbos +palm9744@kettering.edu +Francois-Xavier Duranceau +duranceau@kde.org +Corel Corporation (author: Emily Ezust) +emilye@corel.com + + +Documentation Copyright © 2000 Matt Johnston +mattj@flashmail.com + +Documentation updated for &kde; 3.3 by Henrique Pinto +henrique.pinto@kdemail.net. + +&underFDL; +&underGPL; + + + + +Installation + + +How to obtain &ark; + +&install.intro.documentation; + + + + +Requirements + +In order to successfully use &ark;, you need &kde; +3.3. GNU Tar v1.12 and a recent +gzip are also needed if you want &ark; to handle tar archives. To handle other +file formats, you need the appropriate command line programs, such as +zip, unzip, ar, rar +and lha. + + + + +Compilation and Installation + +&install.compile.documentation; + + + + + +&documentation.index; + + + + diff --git a/doc/ark/man-ark.1.docbook b/doc/ark/man-ark.1.docbook new file mode 100644 index 0000000..ce2d6a8 --- /dev/null +++ b/doc/ark/man-ark.1.docbook @@ -0,0 +1,174 @@ + + + +]> + + + +KDE User's Manual + +Lauri +Watts + +&Lauri.Watts.mail; +February 25, 2005 +K Desktop Environment + + + +&kappname; +1 + + + +ark +A &kde; archiving tool + + + + +ark + + + + + + + +folder +files +archive +KDE Generic Options +Qt Generic Options + + + + +Description +&kappname; is a program for managing various archive formats +within the &kde; environment. Archives can be viewed, extracted, created +and modified from within &kappname;. The program can handle various +formats such as tar, +gzip, bzip2, +zip, rar and +lha (if appropriate command-line programs are +installed). &kappname; can work closely with &konqueror; in the &kde; +environment to handle archives, if you install the &konqueror; +Integration plugin available in the kdeaddons package. + + + + +Options + + + + + +Open extract dialog, quit when finished + + + + +Extract archive to +folder. Quit when finished. +folder will be created if it does not +exist. + + + + + +Ask for the name of the archive to add +files to. Quit when finished. + + + + + +Add files to +archive. Quit when finished. +archive will be created if it does not +exist. + + + + + +Used with . When specified, +archive will be extracted to a +subfolder of folder whose name will be +the name of archive without the +filename extension. + + + + + + + +Environment + + +$PATH + +The commandline programs to deal with the archives you wish to +handle in &kappname; must be available in your +$PATH. + + + + + + +Examples + + + +ark . +An-Archive.tar.bz2 + +Will extract An-Archive.tar.bz2 into a +folder named An-Archive in the +current directory. + + + +ark +*.jpg pictures.tar.bz2 + +Add all files ending in *.jpg to an archive named +pictures.tar.bz2, creating it if it doesn't +already exist. + + + + + + +See Also +tar(1), gzip(1), bzip2(1), zip(1), rar(1), lha(1) + +More detailed user documentation is available from help:/ark +(either enter this URL into &konqueror;, or run +khelpcenter +help:/ark). + + + + +Authors +&ark; is maintained by +HenriquePinto stampede@coltec.ufmg.br +This man page was written by &Lauri.Watts; +&Lauri.Watts.mail; for &kde; 3.4. + + + diff --git a/doc/kcalc/Makefile.am b/doc/kcalc/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/kcalc/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kcalc/commands.docbook b/doc/kcalc/commands.docbook new file mode 100644 index 0000000..22f20e7 --- /dev/null +++ b/doc/kcalc/commands.docbook @@ -0,0 +1,254 @@ + + +Command Reference + + +The <guimenu>File</guimenu> Menu + + + + + + +&Ctrl;Q + +File +Quit + +Quit &kcalc;. + + + + + + + +The <guimenu>Edit</guimenu> Menu + + + + + + +&Ctrl;Z + +Edit +Undo + +Go back in the result +stack. + + + + + +&Ctrl;&Shift;Z + +Edit +Redo + +Go forward in the result +stack. + + + + + + +&Ctrl;X + +Edit +Cut + +Delete the displayed result and copy it to the +clipboard. + + + + + +&Ctrl;C + +Edit +Copy + +Copy the displayed result to the +clipboard. + + + + + +&Ctrl;V + +Edit +Paste + +Insert the cut or copied result in the +display. + + + + + + + +The <guimenu>Constants</guimenu> Menu + + + + + +Constants +Mathematics + +Display Pi, Euler Number or Golder Ratio. + + + + + +Constants +Electromagnetism + +Display Light Speed, Elementary Charge, +Impedance of Vacuum, Permeability of Vacuum or Permittivity of Vacuum. + + + + + +Constants +Atomic & Nuclear + +Display Planck's Constant, Elementary Charge or +Fine-Structure Constant. + + + + + +Constants +Thermodynamics + +Display Boltzmann Constant, Atomic Mass Unit, Molar Gas +Constant, Stefan-Boltzmann Constant or Avogadro's Number. + + + + + +Constants +Gravitation + +Display Constant of Gravitation or Earth Acceleration. + + + + + + + + +The <guimenu>Settings</guimenu> Menu + + + + +Settings +Science/Engineering Buttons + +Display science and engineering buttons. + + + + + +Settings +Statistic Buttons + +Display statistic +buttons. + + + + + +Settings +Logic Buttons + +Display logic +buttons. + + + + + +Settings +Constants Buttons + +Display constants buttons. + + + + + +Settings +Show All + +Display all buttons available. + + + + + +Settings +Hide All + +Hide all extra buttons and display only +standard default buttons. + + + + + +Settings +Configure Shortcuts... + +Configure the keyboard shortcuts used by &kcalc;. + + + + + + +Settings +Configure &kcalc;... + +Display the &kcalc; settings dialog. + + + + + + + + +The <guimenu>Help</guimenu> Menu + +&help.menu.documentation; + + + + + + diff --git a/doc/kcalc/index.docbook b/doc/kcalc/index.docbook new file mode 100644 index 0000000..b881ee9 --- /dev/null +++ b/doc/kcalc/index.docbook @@ -0,0 +1,774 @@ + + + + + + +]> + + + +The &kcalc; Handbook + + + +&Bernd.Johannes.Wuebben; &Bernd.Johannes.Wuebben.mail; + + + +&Pamela.Roberts;&Pamela.Roberts.mail; + + + +&Anne-Marie.Mahfouf;&Anne-Marie.Mahfouf.mail; + + + + + + +2001 2002 2005 2006 +&Bernd.Johannes.Wuebben;, &Pamela.Roberts;, +&Anne-Marie.Mahfouf; + + +&FDLNotice; + +2006-02-13 +2.0.2 + +&kcalc; is a scientific calculator for &kde; + + +KDE +KCalc +calculator + + + + +Introduction + +This document describes &kcalc; version 1.8. + +&kcalc; offers many more mathematical functions than meet the eye +on a first glance. Please study the section on keyboard accelerators and +modes in this handbook to learn more about the many functions +available. + +In addition to the usual functionality offered by most scientific +calculators, &kcalc; offers a number of features, which I think are +worthwhile pointing out: + + + +&kcalc; provides trigonometric functions, logic operations, and it is +able to do statistical calculations. + + +&kcalc; allows you to cut and paste numbers from/into its display. + + +&kcalc; features a results-stack which lets +you conveniently recall previous results. + + +You can configure &kcalc;'s display colors and font. + + +You can configure &kcalc;'s precision and the number +of digits after the period. + + + &kcalc; offers a great number of useful +key-bindings, which make using &kcalc; without using a pointing device easy. +Hint: pressing (and holding) the &Ctrl;-key, displays on +every button, +the corresponding key-binding. + + + +Have fun with &kcalc;! + +Bernd Johannes Wuebben + + + + + +Usage + +General Usage + +General usage is straight forward and similar to the way most +simple scientific calculators operate, but take note of the following +special &kcalc; features: + + + +Result Stack +Each time you &LMB; click on the += button or press your keyboard's +Enter or = keys, the display result is +written to &kcalc;'s result stack. You can navigate through the result +stack with your keyboard's +&Ctrl;Z +and &Ctrl; &Shift;Z +keys. + + + + +Percent Function + +The percent function works somewhat differently to that on most +calculators. However, once understood, its enhanced functionality proves +quite useful. See the section about the percent function for further details. + + + +Cut and Paste + + + +Pressing &Ctrl;C +will place the displayed number on to the clipboard. + + +Pressing &Ctrl;V +will paste the clipboard content into the display if the content of the +clipboard is a valid floating point number. + + +It is still possible to copy/paste by clicking on &kcalc;'s display, +but this may disappear in future versions. + + + + + +Advanced functions + +When you start &kcalc; for the first time, the calculator will only +display buttons for basic arithmetic computations. +Under the menu entry Settings it is possible to +open extra buttons for &kcalc;: +it is for example possible to choose +Statistical or +Trigonometric buttons. + + + + + + +Statistical Mode + +In this mode the left column of buttons is allocated to statistical +functions: + Most of the functionality in this mode is centered around the Dat + button. To create a data list of numbers, enter a number into the calculator and press + Dat. A sequentially increasing number is shown on the display indicating + which position in the Data list the number occupies. A traditional calculator only + stores three values for statistical functions: The number of discrete items in a list, the sum of + the data items entered and the sum of the square of all data items in the list. &kcalc; differs by + actually storing each discrete value, allowing you to calculate the median value of the data. + + + + +Buttons +Function + + +N +Recall the number of data items entered + +Inv N +Display the sum of all data items entered + +Mea +Display the mean of the data items entered + +Inv Mea +Display the sum of the square of all data items entered + +Std +Display the standard deviation (n) + +Inv Std +Display the population standard deviation (n-1) + +Med +Display the median + +Dat +Enter a data item + +Inv Dat +Clear last data item entered + +Cst +Clear the store of all data item entered + + + + + + + +Trigonometric Mode + +In this mode the left column of buttons is allocated to trigonometric +functions: + + + +Buttons +Function + + +Hyp +Enter Hyperbolic sub mode. Hyp Sin for example is the hyperbolic sine: +sinh(x) + +Sin +Compute the sine + +Inv Sin +Compute the inverse sine + +Cos +Compute the cosine + +Inv Cos +Compute the inverse cosine + +Tan +Compute the tangent + +Inv Tan +Compute the inverse tangent + +Log +Compute the Log base 10 + +Inv Log +Compute 10 to the power of x + +Ln +Compute the natural logarithm. That is the log to base e + +Inv Ln +Compute e to the power of x + + + + + + +Memory Operations + +&kcalc; supports the memory operations given by standard +calculators plus six slots to hold constants. + + + Standard Memory Operations + +&kcalc; can remember results of operations for you, and re-use them in +later calculations. You can access these functions via several buttons +labelled MR, MS, +M+ and MC. + + + +MS +The MS button stores the currently +displayed result in memory. + + + +M+ +The M+ button adds the current result to the +one in memory. So, if you had stored a 20, and the current result is a 5, +your memory would contain 25 when you press it. If the memory is empty, it +acts like MS and simply stores the +result. + + + +MR +The MR button gets the value stored +in memory and puts it in the display. + + + +MC +The MC button clears the +memory. + + + +If a value is stored in memory a M will appear in +the status bar, next to the calculator mode indicator + + + +Constants + +The six constants buttons C1 to +C6 will only be visible after activating the +item Constants Buttons in the menu +Settings of the menu bar. + +To store the number shown in the &kcalc; display in one of the +six constants, first press Inv followed +by the desired button key C1 up to +C6. + +To use the value stored in any of the contants in a calculation, just + press the desired button (C1 to C6), + and the corresponding number will appear in the display. + +IIt is possible to change the label of the constants button to make it easier + to remember which button holds which constant. Click with the right mouse + button on one of the buttons C1 to + C6. A popup menu appears, in which you select + Set Name. + +There are many (mostly physical) predefined constants, which can +be put on any of the six buttons C1 - +C6 by selecting the desired constant in the +popup menu that appears after right clicking on one of the constant +buttons and selecting Choose from List. Though +the predefined constants can also be accessed via the +Constants in the menu bar, storing it on a +constants button is very handy, if the number is used +frequently. + + + + + + +Single Key Accelerators + +To simplify entering calculations from the keyboard &kcalc; has single key +accelerators for most functions. For example entering 7R +or 7r will calculate the reciprocal of 7 (1/7). + +During a computation, you can always press &Ctrl; to make each +button display its key-binding. + + + +Key +Function +Notes + + + +H +Hyp +Hyperbolic as in Hyp Sin, +the sinh(x) + +S +Sin + + +C +Cos + + +T +Tan + + +N +Ln +log base e + +L +Log +log base 10 + +I + Inv +Inverse, ⪚ if +you want arcsin(x) type i s + +\ ++/- +Change sign + +[ +x^2 + + +^ +x^y + + +! +x! +Factorial + +< +Lsh +Left shift. Note: Inv +Lsh is Right shift + +& +And +Logical AND + +* +X +Multiply + +/ +/ +Divide + +D +Dat +Enter data item in statistical mode + +O +Or +Logical OR. Note: Inv +Or is XOR + +R +1/x +Reciprocal + += += + + +Enter += + + +Return += + + +Page Up +C +Clear + +Esc +C +Clear + +Prior +C +Clear + +Page Down +AC +Clear all + +Next +AC +Clear all + +Del +AC +Clear all + + + + + + + +Comments on Specific Functions + + +Mod and Inv Mod + + + +Mod gives the remainder of dividing the displayed +number by the next input number. +22 Mod 8 = will give the result +6 +22.345 Mod 8 = will give the result +6.345 + + + +Inv Mod does integer +division of the displayed number by the next input number. +22 Inv Mod 8 = will give the result +2 +22.345 Inv Mod 8 = also gives 2 + + + + + + + +% + +Used instead of the = key, +% interprets the final operation carried out in the +current calculation as follows: + + + +If the final operator is + or - the second argument is interpreted as percentage of the first operand. + + + +If the final operator is * divide the result of the multiplication by 100. + + + +If the final operator is / give the left operand +as a percentage of the right operand. + + + + In all other cases the % key gives identical results to the = key. + + + + + + +Examples: + +150 + 50 % gives 225 (150 plus 50 percent of this amount) +42 * 3 % gives +1.26 (42 * 3 / 100) +45 / 55 % gives +81.81... (45 is 81.81.. percent of 55) + + + + + + + +Lsh and Inv Lsh + + +Lsh left shifts the integer part of the displayed +value (multiplies it by 2) n times, where n is the next input number, and +gives an integer result: +10 Lsh 3 = gives 80 +(10 multiplied by 2 three times). +10.345 Lsh 3 = also gives +80. + + + +Inv Lsh right shifts the +value (performs an integer divide by 2) n times. +16 Inv Lsh 2 = gives +4 (16 divided by 2 twice). +16.999 Inv Lsh 2 = also gives +4. + + + + + + + +Cmp, And, Or and Xor + +The Cmp, And and +Or functions perform bitwise logical operations and +therefore appear more meaningful if the Base is set to +Hex, Oct or Bin +rather than Dec. In the following +examples Base is set to Bin. + + + +Cmp performs a 1's complement (inverts the +bits). +101 Cmp gives +111...111010 + + + +And does a logical AND. +101 And 110 = gives +100 + + + +Or does the logical OR. +101 Or 110 = gives +111 + + + +Xor performs the logical +XOR (exclusive OR) operation. +101 Xor 110 = gives +11 + + + + + + + + +Questions and Answers + + + + + +How do I get e, the Euler number? +Type 1 Inv Ln. + + + +How do I get two fixed digits after the period? +Click on the Configure button, this will +bring up the configuration dialog. Check Set fixed +precision and adjust the spin control so that it shows a +2. + + +What about Precision? +The main factor determining the precision of &kcalc; is whether your libc and libmath +supports the C data type long double. If this is the case, &kcalc; will detect this +at compile time and use it as its fundamental data type to represent numbers. + + +Adjust the Precision in &kcalc;'s +Configure dialog so that the above computations +work correctly. I recommend a precision of 14 if the fundamental data type +for your copy of &kcalc; is long double, otherwise 8 or 10. + +Higher precision doesn't necessarily lead to better results. Play with +the precision and you will see what I mean. + + + + + + +&commands; + + +Credits and License + +&kcalc; Program Copyright ©: +Bernd Johannes Wuebben 1996-2000 +The &kde; Team 2000-2004 + + +&Bernd.Johannes.Wuebben; &Bernd.Johannes.Wuebben.mail; +&Evan.Teran; &Evan.Teran.mail; +&Espen.Sand; &Espen.Sand.mail; +&Chris.Howells; &Chris.Howells.mail; +&Aaron.J.Seigo; &Aaron.J.Seigo.mail; +&Charles.Samuels; &Charles.Samuels.mail; + + +&kcalc; was inspired by Martin Bartlett's xfrmcalc, +whose stack engine is still part of &kcalc;. + +Documentation Copyright © 2001,2002,2005, 2006: + +&Bernd.Johannes.Wuebben; &Bernd.Johannes.Wuebben.mail; +&Pamela.Roberts; &Pamela.Roberts.mail; +&J.Hall; &J.Hall.mail; +&Anne-Marie.Mahfouf;&Anne-Marie.Mahfouf.mail; + + +&underFDL; +&underGPL; + + + + +Installation + +&kcalc; is part of the kdeutils package within the &kde; project and will +normally be provided as part of a &kde; installation. For more details about +&kde; visit http://www.kde.org. + + + + +Compilation and Installation + +&install.intro.documentation; +&install.compile.documentation; + + + + +How to enable long double precision for &kcalc; + +If your machine supports the C data type long double +and if you have a working libc you can enable long double +precision for &kcalc;. + +Here is what to do: + + + + Check ../config.h and see whether +HAVE_LONG_DOUBLE is defined, &ie; you should be able to locate a +line saying: + +#define HAVE_LONG_DOUBLE 1 + +If you can't find such a line your system doesn't support long +double IEEE precision. + + +Edit the files kcalctype.h, +configdlg.cpp, kcalc.cpp and +kcalc_core.cpp and remove the lines: + + +#ifdef HAVE_LONG_DOUBLE +#undef HAVE_LONG_DOUBLE +#endif + + + + + Recompile &kcalc;. + + + + + + + + + + diff --git a/doc/kcalc/kcalc_on_Aix.txt b/doc/kcalc/kcalc_on_Aix.txt new file mode 100644 index 0000000..186e9d6 --- /dev/null +++ b/doc/kcalc/kcalc_on_Aix.txt @@ -0,0 +1,123 @@ +X-RDate: Mon, 11 Aug 1997 17:34:22 -0400 (EDT) +Return-Path: +Received: from cornell.edu (cornell.edu [132.236.56.6]) by + postoffice2.mail.cornell.edu (8.8.5/8.8.5) with ESMTP id JAA08757 for + ; Mon, 11 Aug 1997 09:50:57 -0400 (EDT) +Received: (from daemon@localhost) by cornell.edu (8.8.5/8.8.5) id JAA11825 for + bw18@postoffice3.mail.cornell.edu; Mon, 11 Aug 1997 09:50:56 -0400 (EDT) +Received: from polygon.math.cornell.edu (POLYGON.MATH.CORNELL.EDU + [128.84.234.110]) by cornell.edu (8.8.5/8.8.5) with SMTP id JAA11800 for + ; Mon, 11 Aug 1997 09:50:53 -0400 (EDT) +Received: from ibmmail.COM by polygon.math.cornell.edu (5.x/SMI-SVR4) id + AA10464; Mon, 11 Aug 1997 09:50:48 -0400 +Received: from IMXGATE.COM by ibmmail.COM (IBM VM SMTP V2R3) with BSMTP id + 5302; Mon, 11 Aug 97 09:50:47 EDT +Received: from mail.schoeck.de by imxgate.com (IBM VM SMTP V2R3) with TCP; + Mon, 11 Aug 97 09:49:44 EDT +Received: from isndj1.ag.schoeck.com by mail.schoeck.de (AIX 4.1/UCB 5.64/4.03) + id AA15070; Mon, 11 Aug 1997 15:46:57 +0100 +Message-Id: <9708111446.AA15070@mail.schoeck.de> +Comments: Authenticated sender is +X-PH: V4.1@cornell.edu (Cornell Modified) +Organization: Schoeck AG +Date: Mon, 11 Aug 1997 15:47:27 +1 +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 8BIT +Comments: Sender has elected to use 8-bit data in this message. If problems + arise, refer to postmaster at sender's site. +Reply-To: diehl@mail.schoeck.de +Priority: normal +In-Reply-To: +References: <9708101509.AA13824@mail.schoeck.de> +X-Mailer: Pegasus Mail for Win32 (v2.52) +XFMstatus: 0000 +From: "Jochen Diehl" +To: Bernd Johannes Wuebben +Subject: RE: kcalc under AIX + + +> O.K Jochen, +> +> das wird jetzt aber ein bische unuebersichtlich. +> Ich schlage vor, Du findest jetzt erst mal in Ruhe eine +> Loesung die fuer AIX funktioniert. Dann sende mir Dein +> kcalc.h und ich werde meine bestes tun das einzubauen. +> Ich glaube es ist am besten wenn wir das so machen, +> ein ganzen Haufen Leute sind naemlich immer zielich sauer, +> wenn ich eine neue version von kcalc rausbringe und +> es laeuft auf ihrer platform nicht mehr richtig. + +Sowas ist in der Tat aergerlich. Langsam verstehe ich, wieso +kommerzielle Softwareschmieden sich so str?uben, auf n Plattformen zu +portieren... + +Ok. Hier also mal meine Aenderungen, sind eigentlich minimal. +Immerhin funktioniert die Trigonometrie dann bei mir. Ausser beim +ersten Start: cos 0 gibt dann 0.9932483259 irgendwas, erst wenn ich +AC druecke kommt 1 raus. Sonst klappt das erstmal. AIX scheint +uebrigens asinhl und Konsorten nicht zu kennen, obwohl sinhl bekannt +ist. Nun ja, hier der diff: +kcalc.h +72a73,81 +> #if defined(_AIX) && defined(HAVE_FABSL) +> #define __LONGDOUBLE128 +> #define pi M_PI +> #define asinhl(X) asinh(X) +> #define acoshl(X) acosh(X) +> #define atanhl(X) atanh(X) +> #endif +> +> +kcalc_core.cpp +35c35 +39d38 +< #include +40a40 +> #include +68a69 +> #ifndef _AIX +69a71 +> #endif +157a160 +> #ifndef _AIX +158a162 +> #endif +Damit bricht der Compiler wenigstens mal nicht ab. + + +Anscheinend ist IBM echt zu doof zum Rechnen (wundert mich, bei den +Preisen und den unendlich vielen Seriennummern :-), Deine Definition +von pi schluckt es nicht, da kommt dann NaNQ in die Anzeige. + +Auch sonst stimmt etwas noch nicht so, ich habe nur noch nicht +herausgefunden, woran das liegt: +Nach exp(1) zeigt kcalc e^1.5 an usw. Was am Source falsch sein +soll, ist mir absolut schleierhaft, ich habe genau denselben Code in +einem eigenen Programm und da rechnet er es richtig. Weiss der Geier. + +"0!" bringt bei mir einen core dump, schaetze mal, der modfl (IBM) +ist daran schuld. Wenn ich vorher ein cout mache, bleibt das Programm +stehen, cored aber wenigstens nicht. + +Was soll's? Da ich scheinbar der einzige bin, der Interesse an KDE +auf AIX hat, stoert mich das nicht so ungemein, will sagen: ich habe +keine Probleme xcalc zu nehmen (wenn ich ueberhaupt mal einen +Taschenrechner brauche). Ansonsten gilt natuerlich die +Standardaussage: Super, dass sich jemand hinsetzt und den Code +ueberhaupt schreibt und dann noch fuer umme weggibt. + +Fass es bitte nicht als Kritik auf, sondern einfach als Info, was +unter anderen OS so alles passieren kann :-) Was Du mit deinem Source +machst, ist natuerlich Deine Sache, ich will hier ja keinen +veraergern. + +Viele Gruesse +Jochen + + + +------------------------------------------------------------- +Jochen Diehl, R/3-Basis +Schoeck AG, Vimbucher Str. 2, 76534 Baden-Baden +Tel.: +497223967381 Fax.: +497223967352 diff --git a/doc/kcalc/kcalc_on_OSF.txt b/doc/kcalc/kcalc_on_OSF.txt new file mode 100644 index 0000000..59b6e6e --- /dev/null +++ b/doc/kcalc/kcalc_on_OSF.txt @@ -0,0 +1,62 @@ +X-RDate: Mon, 01 Sep 1997 07:45:22 -0400 (EDT) +Return-Path: +Received: from cornell.edu (cornell.edu [132.236.56.6]) by + postoffice2.mail.cornell.edu (8.8.5/8.8.5) with ESMTP id KAA06175 for + ; Tue, 26 Aug 1997 10:56:10 -0400 (EDT) +Received: (from daemon@localhost) by cornell.edu (8.8.5/8.8.5) id KAA25547 for + bw18@postoffice3.mail.cornell.edu; Tue, 26 Aug 1997 10:55:42 -0400 (EDT) +Received: from polygon.math.cornell.edu (POLYGON.MATH.CORNELL.EDU + [128.84.234.110]) by cornell.edu (8.8.5/8.8.5) with SMTP id KAA25126 for + ; Tue, 26 Aug 1997 10:55:15 -0400 (EDT) +Received: from mpimail.mpi-hd.mpg.de by polygon.math.cornell.edu (5.x/SMI-SVR4) + id AA07964; Tue, 26 Aug 1997 10:54:56 -0400 +Received: from daniel.mpi-hd.mpg.de (daniel.mpi-hd.mpg.de [149.217.1.90]) by + mpimail.mpi-hd.mpg.de (8.8.2/8.8.2) with SMTP id QAA19532 for + ; Tue, 26 Aug 1997 16:54:56 +0200 (MET DST) +Received: from localhost by daniel.mpi-hd.mpg.de + (5.65v4.0/1.1.10.5/31Jul97-0446PM) id AA04869; Tue, 26 Aug 1997 16:54:56 +0200 +Date: Tue, 26 Aug 1997 16:54:56 +0200 (MET DST) +X-PH: V4.1@cornell.edu (Cornell Modified) +Message-Id: +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +XFMstatus: 0002 +From: Lars Knoll +To: wuebben@math.cornell.edu +Subject: kcalc unter dec osf4.0 + +Hi, + +ich hatte ein paar Probleme, kcalc auf einer dec alpha unter osf4.0 +zu kompilieren. Das Problem ist, dass bei diesem System + sizeof(long double) = sizeof(double) +ist, und dass Routinen namens asinl, fabsl, ... existieren, aber nicht +in irgendwelchen headers definiert werden. +Zusaetzlich funktioniert fabsl() wie erwartet, asinl gibt aber leider +immer nur 0. zurueck. Der folgende patch loest das Problem bei mir. + +Lars + + +diff -c kcalc/kcalc.h kcalc.osf/kcalc.h +*** kcalc/kcalc.h Sun Aug 3 05:01:41 1997 +--- kcalc.osf/kcalc.h Tue Aug 26 16:53:12 1997 +*************** +*** 63,68 **** +--- 63,72 ---- + + /* TAKE CARE OF TH HAVE_LONG_DOUBLE defines in core.cpp*/ + ++ /* dec osf4.0 has fabsl, but not asinl... */ ++ #ifdef __osf__ ++ #undef HAVE_FABSL ++ #endif + + #ifdef HAVE_FABSL + #define CALCAMNT long double + + + +--- +Lars Knoll knoll@mpi-hd.mpg.de + PGP pub key [6DADF3D5]: finger knoll@pluto.mpi-hd.mpg.de diff --git a/doc/kcharselect/Makefile.am b/doc/kcharselect/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/kcharselect/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kcharselect/index.docbook b/doc/kcharselect/index.docbook new file mode 100644 index 0000000..cabb4d2 --- /dev/null +++ b/doc/kcharselect/index.docbook @@ -0,0 +1,66 @@ + + + + + +]> + + + + +The &kcharselect; Handbook + + + + + + + +
+
+
+ +
+ +&FDLNotice; + +2001-01-20 +0.00.00 + + + +&kcharselect; is part of the kdeutils package. + + + + + +KDE +kdeutils +kcharselect + + +
+ + +Introduction +The documentation for &kappname; was not finished when &kde; was installed on this computer. +If you need help, please check The KDE Web site for updates, or by submitting your question to The &kde; User Mailing list. +The &kde; Team + +&underFDL; +&underGPL; + + + +&documentation.index; +
+ + diff --git a/doc/kcontrol/Makefile.am b/doc/kcontrol/Makefile.am new file mode 100644 index 0000000..930c270 --- /dev/null +++ b/doc/kcontrol/Makefile.am @@ -0,0 +1,6 @@ + +SUBDIRS = $(AUTODIRS) + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kcontrol/kcmlowbatcrit/Makefile.am b/doc/kcontrol/kcmlowbatcrit/Makefile.am new file mode 100644 index 0000000..335ba2c --- /dev/null +++ b/doc/kcontrol/kcmlowbatcrit/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG=en +KDE_DOCS=kcontrol/kcmlowbatcrit \ No newline at end of file diff --git a/doc/kcontrol/kcmlowbatcrit/index.docbook b/doc/kcontrol/kcmlowbatcrit/index.docbook new file mode 100644 index 0000000..24bf9e0 --- /dev/null +++ b/doc/kcontrol/kcmlowbatcrit/index.docbook @@ -0,0 +1,47 @@ + + + +]> + +
+ + + + +&Mike.McBride; &Mike.McBride.mail; + + + + +2002-02-12 +3.00.00 + + +KDE +KControl +Battery +Power + + + + + +Low Battery Critical + + +Use +This module works in exactly the same manner as the Low battery Warning module. By convention, this module should be set to warn you or automatically perform any action necessary just prior to the loss of battery power. + + +Section Author +This section written by &Paul.Campbell; &Paul.Campbell.mail; +Converted to Docbook by &Mike.McBride; &Mike.McBride.mail; + + + + +
diff --git a/doc/kcontrol/kcmlowbatwarn/Makefile.am b/doc/kcontrol/kcmlowbatwarn/Makefile.am new file mode 100644 index 0000000..9baf4af --- /dev/null +++ b/doc/kcontrol/kcmlowbatwarn/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG=en +KDE_DOCS=kcontrol/kcmlowbatwarn \ No newline at end of file diff --git a/doc/kcontrol/kcmlowbatwarn/index.docbook b/doc/kcontrol/kcmlowbatwarn/index.docbook new file mode 100644 index 0000000..97ceaf2 --- /dev/null +++ b/doc/kcontrol/kcmlowbatwarn/index.docbook @@ -0,0 +1,104 @@ + + + +]> + +
+ + + + +&Mike.McBride; &Mike.McBride.mail; + + + + +2002-02-12 +3.00.00 + + +KDE +KControl +Battery +Power + + + + + + +The Low Battery Warning and Low Battery Critical Panels + + + +Introduction + + +These two modules work together to control what happens when a +predetermined low battery condition occurs. There are two of them, so you can +set a warning for when time is getting close, and something more desperate for +the last minute save or suspend. + + + + + + +Use + +Low trigger + +This field specifies at which point the battery low state is detected - it +is the number of minutes left (according to APM) in your batteries. When this +number is crossed the low state is triggered and one or more of the following +things will occur + + + +Run Command +This is a shell command that will be executed when the battery +low is detected. By default, this is turned off. + + +Play Sound +This specifies a sound to play when battery low is detected. Simply specify the path to the +file to have it played. By default, this is turned off. + + +System Beep +Enabling this will cause the battery monitor to beep whenever +the battery level drops below the preset value. This is probably the least +intrusive, yet still active, method of alerting the user that the battery is +low. By default, this is on. + + +Notify +Enabling this will cause Battery to pop up a window when the +battery becomes low. + + +Suspend +If you have set up /usr/bin/apm to be run +setuid (see the instructions for the Power panel) then this check box will +appear - if checked it will cause your computer to be put into Suspend +mode. + + +Standby +Like Suspend above, but it puts your computer into Standby +mode. + + + + + +Section Author +This section written by &Paul.Campbell; &Paul.Campbell.mail; +Converted to Docbook by &Mike.McBride; &Mike.McBride.mail; + + + + +
diff --git a/doc/kcontrol/laptop/Makefile.am b/doc/kcontrol/laptop/Makefile.am new file mode 100644 index 0000000..446ee8e --- /dev/null +++ b/doc/kcontrol/laptop/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG=en +KDE_DOCS=kcontrol/laptop \ No newline at end of file diff --git a/doc/kcontrol/laptop/index.docbook b/doc/kcontrol/laptop/index.docbook new file mode 100644 index 0000000..fb83afd --- /dev/null +++ b/doc/kcontrol/laptop/index.docbook @@ -0,0 +1,111 @@ + + + +]> + +
+ + + + + + +&Mike.McBride; &Mike.McBride.mail; + + + + +2002-02-12 +3.00.00 + + +KDE +KControl +Battery +level + + + + + +The Battery Monitor Panel + + + + +Introduction + +This panel controls whether or not a battery state icon appears +in &kde;'s panel. + +Once enabled a battery will appear in your docking bar as one of +3 icons - a battery with a red X through it +indicates that APM has not been installed (in +particular /proc/apm can't be read). + +The other two icons indicate the battery state - a +small plug with a bar beside it indicates your +batteries are charging - the height of the blue portion of the bar +indicate how full your batteries are. A small +battery in the dock indicates you are running on +batteries, the amount of blue in the battery indicates how full your +batteries are. + +If you left click on the docked icon a +pop-up will tell you how much time you have left in minutes. + +If you right click you get a pop-up +that lets you put your laptop into suspend or standby modes - or to +bring up the laptop configuration widget. + +All features of Battery are configured from the Setup dialog. + + + +Use + +The configuration window can be divided into 3 parts. + + + +Show Battery Monitor +This controls whether or not the battery icon appears. This is +disabled by default. + + +Poll +This setting controls how often, in seconds, the battery is +updated. +The default is 20 seconds. + + +Icons +The battery monitor uses three icons to represent the three +states: No APM, Charging, and Not Charging. The icons shown are the large +icons. To select new ones, click on the buttons and a icon loader dialog will +pop up. +If you create your own icons - they will work with the battery +monitor - but be careful. +All the exactly white pixels in the icon get filled by blue for the +battery meter - if you want some white looking pixels to stay choose a slightly +off-white or gray color for them. +The author does not claim to be a graphic artist and would love for +someone to donate some better looking icons to the cause. + + + + + + +Section Author +This section written by &Paul.Campbell; &Paul.Campbell.mail; +Converted to Docbook by &Mike.McBride; &Mike.McBride.mail; + + + + +
diff --git a/doc/kcontrol/powerctrl/Makefile.am b/doc/kcontrol/powerctrl/Makefile.am new file mode 100644 index 0000000..eefb119 --- /dev/null +++ b/doc/kcontrol/powerctrl/Makefile.am @@ -0,0 +1,2 @@ +KDE_LANG=en +KDE_DOCS=kcontrol/powerctrl \ No newline at end of file diff --git a/doc/kcontrol/powerctrl/index.docbook b/doc/kcontrol/powerctrl/index.docbook new file mode 100644 index 0000000..2a09b95 --- /dev/null +++ b/doc/kcontrol/powerctrl/index.docbook @@ -0,0 +1,77 @@ + + + +]> + +
+ + + + +&Mike.McBride; &Mike.McBride.mail; + + + + +2002-10-16 +3.1 + + +KDE +KControl +Laptop +Power + + + + +Laptop Power Control + + +Introduction + +This tab provides a screensaver-style interface to the APM +suspend/standby modes. It allows you to configure different wait +times and/or actions depending on whether or not your laptop is +plugged into the wall. It's intended to be used in addition to the +existing &kde; screensavers - you could for example disable +suspend/standby when plugged in to the wall, but enable suspend with a +shorter time than your normal screensaver kicks in while running on +batteries. + +Standby mode seems to do different things on different laptops - +in particular on some it may not stay in standby mode and your laptop may be +continually waking/sleeping if you leave it in this mode. + + + +Use + +This panel configures the power-down feature of your laptop. It works as +a sort of extreme screen saver. +You can configure different timeouts and behavior depending on whether +your computer is plugged in or running on battery power. +For both the Powered and Not Powered, you should select one of the +following options: + +Standby - Puts your laptop into standby state +Suspend - Puts your laptop into suspend state +Off - Nothing happens at the specified time. + + +Below that, is a text box labeled Wait for. Enter +the time in minutes, that your computer should remain unused, before the laptop +is powered down. + + + +Section Author +This section written by &Paul.Campbell; &Paul.Campbell.mail; +Converted to Docbook by &Mike.McBride; &Mike.McBride.mail; + + + + +
diff --git a/doc/kdelirc/Makefile.am b/doc/kdelirc/Makefile.am new file mode 100644 index 0000000..6812bd2 --- /dev/null +++ b/doc/kdelirc/Makefile.am @@ -0,0 +1,5 @@ + +KDE_LANG = en +KDE_DOCS = AUTO +SUBDIRS = $(AUTODIRS) + diff --git a/doc/kdelirc/irkick/Makefile.am b/doc/kdelirc/irkick/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/kdelirc/irkick/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kdelirc/irkick/index.docbook b/doc/kdelirc/irkick/index.docbook new file mode 100644 index 0000000..972101c --- /dev/null +++ b/doc/kdelirc/irkick/index.docbook @@ -0,0 +1,131 @@ + +IRKick"> + KDE LIRC"> + + + + +]> + + + + +&irkick;: The KDE LIRC Server Handbook + + + +Gav +Wood + +
gav@kde.org
+
+
+ +
+ +2004-01-02 +1.0 + + +2004 +Gav Wood + + +&FDLNotice; + +&kdelirc; is the infrastructure for the KDE's +Infrared Remote Control functionality; &irkick; is the server +component of that infrastructure. + + +KDE +irkick +kdelirc +kcmlirc +lirc + + +
+ + +Introduction + + +&irkick; is a background server that provides the 'glue' between +the operating system and your KDE applications for the purpose of +controlling KDE applications with your infrared remote controls. + + + +It has a configuration tool, which may be accessed either by the +KDE Control Center or directly from the menu of &irkick;. + + + +Requirements + + +For the KDELirc framework to be utilised you must have setup a LIRC +on your KDE machine. If it is properly set up, the &irkick; icon in +the system tray will light up red. If not, it will be grey and crossed +out. + + + +For more information about LIRC, visit their website at http://www.lirc.org. + + + + + + +Using &irkick; + + +&irkick; provides one main function: When a button on a remote control is +pressed, it will temporarily become lit up. Aside from this &irkick; does +little for the user directly aside from telling them of the activity of their +remote controls. + + + +Using the right-mouse-button menu, you can configure the KDE infrared remote +control framework. + + + + + +Credits and Licenses + +&kdelirc;: The KDE LIRC Framework Copyright (c) 2004 Gav Wood +gav@kde.org. + + + +&underFDL; +&underGPL; + + + + +Installation + +&install.intro.documentation; +&install.compile.documentation; + + +
+ + diff --git a/doc/kdelirc/kcmlirc/Makefile.am b/doc/kdelirc/kcmlirc/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/kdelirc/kcmlirc/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kdelirc/kcmlirc/index.docbook b/doc/kdelirc/kcmlirc/index.docbook new file mode 100644 index 0000000..e3507c3 --- /dev/null +++ b/doc/kdelirc/kcmlirc/index.docbook @@ -0,0 +1,165 @@ + +KDE LIRC Control Center Module"> + KDE LIRC"> + + + +]> + + + + +KDE Infrared Remote Control Configuration + + + +Gav +Wood + +
gav@kde.org
+
+
+ +
+ +2004-01-02 +1.0 + + +2004 +Gav Wood + + +&FDLNotice; + +&kdelirc; configuration: The infrastructure for the KDE's +Infrared Remote Control functionality. + + +KDE +irkick +kdelirc +kcmlirc +lirc + + +
+ + +Introduction + + + + + +Requirements + + +For the KDELirc framework to be utilised you must have setup a LIRC +on your KDE machine. If it is properly set up, the &kdelirc; icon in +the system tray (show icon here) will light up red. If not, it will +be grey and crossed out. + + + +For more information about LIRC, visit their website at http://www.lirc.org. + + + + + + +Usage + + +There are several sections of the configuration. The list on the left details the remote controls and modes. The selection of that dictates the contents of the right-most list, which shows button/action bindings. Flicking the main tab over to Loaded Extensions will show a list of applications and remote controls that are recognised for the advanced functionality; some data is also viewable by selecting one of the items. + + + +Remote Controls and Modes + + +Each remote control can have a number of modes. Having multiple modes allows the same button to conduct different actions in difference situations, and is how many remote controls handle many different appliances with a limited number of buttons. A good example are the TV/Video/Satellite/DVD multi-purpose remote controls - rather than having several sets of number buttons for each appliance they have only one set which works for the currently selected appliance only. + + + +Each remote control can be in at most one mode at once (it may also be in no mode at all). The remote control also has a "default mode", which is the mode that it starts in, and the mode that it gets reset to normally. This may be set by using the Edit button. + + + +The list contains any remote controls detected on your system. Modes may be added and removed by selecting the desired remote control and using the buttons directly below the list Add, Remove. Modes may be renamed "inline" in the standard KDE fashion by first selecting the mode in the list box, and then clicking it again after a short pause. The Edit button allows mode names to be edited, and also allows you to define an icon that will show up in the system tray when that mode is entered. + + + + + +Action-Button Bindings + + +An action/button binding ("action") is a connection between a button press and an effect. The effect may be to switch modes, to start a KDE program or to execute a function in a KDE program (using DCOP). + + + +Actions may be associated with a mode of the remote control; if it is, the action will only have effect when the remote control is in that mode. Actions may also be placed out of any mode. Such actions will always have their desired effect no matter what mode that remote control happens to be in. + + + +To add an action/button binding simply use the Add button. Removal may be performed by selecting the action(s) to be removed and clicking the Remove button. Actions may be Edited with the Edit button, and moved to different modes by dragging and dropping onto the desired mode in the remotes/modes list. + + + +Actions may also be "automatically" populated. This handles the instance when you have a supported remote control and you wish to map its buttons to a supported application's functions. &kdelirc; can attempt to match buttons to functions for you; this behaviour may have to be tweaked, however. + + + + + +Loaded Extensions + + +There is another tab available named "Loaded Extensions". This details the applications and remote controls that &kdelirc; recognises. &kdelirc; can also use unsupported remote controls and applications, but the Auto-Populate function will not work as well (if at all). + + + +By clicking on an entry you can see information on it such as the author's details. + + + + + + + +Credits and Licenses + +&kdelirc; KDE LIRC Framework Copyright (c) 2004 Gav Wood +gav@kde.org. + +Documentation Copyright (c) 2004 by Gav Wood +gav@kde.org. + +&underFDL; +&underGPL; + + + + +Installation + +&install.intro.documentation; +&install.compile.documentation; + + +
+ + diff --git a/doc/kdf/Makefile.am b/doc/kdf/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/kdf/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kdf/index.docbook b/doc/kdf/index.docbook new file mode 100644 index 0000000..672ef81 --- /dev/null +++ b/doc/kdf/index.docbook @@ -0,0 +1,266 @@ + + + + + +]> + + + + +The &kdiskfree; Handbook + + + +&Jonathan.Singer; &Jonathan.Singer.mail; + + + +&Michael.Kropfberger; &Michael.Kropfberger.mail; + + + + + + + +2000-2002 +&Jonathan.Singer; + + +&FDLNotice; + +2003-09-16 +0. + +&kdiskfree; displays available file devices, along with +information about them. + + + + +KDE +kdf +kdeutils +disks +devices +mount +unmount + + + + + +Introduction + +&kdiskfree; displays the available file devices (hard drive +partitions, floppy and &CD; drives, &etc;) along with information on +their capacity, free space, type and mount point. It also allows you +to mount and unmount drives and view them in a file manager. + +&kdiskfree; is similar to the &kcontrol; Disk-Free module , but takes up less screen +space. It is useful if you want to keep a &kdiskfree; window available at +all times. + + + + +Using &kdiskfree; + + +Starting &kdiskfree; + +Type kdf at a command +prompt or select Disk Free from the +System group in the K +menu. The standard &Qt; and &kde; command options are available, and +can be listed by entering kdf + at the command prompt. + + + + +The Main window + +The main &kdiskfree; window displays the available file devices. + +Normally, the following pieces of information are included: + +&kdiskfree; Screen + + + + + + &kdiskfree; Screen + + + + + +an icon depicting the type of storage +device name +filesystem type +total size +mount point +free disk space +the percentage of space used as a number and as a +graph. + + +In the picture above, four devices are shown: one reiserfs-formatted +hard drive partition mounted at the filesystem root (/), two &CD-ROM;'s, and a floppy drive. + +Left clicking on the header of a +particular column sorts the devices according to that variable. A +second left click sorts in the opposite +order. + +Clicking on a row pops up a menu. If that device is not +currently mounted, the Mount Device option +is available. If the device is mounted, it can be unmounted by +choosing Unmount Device. Selecting +Open in File Manager opens a new window with a +graphical view of the files on that device. + + + + +The &kdiskfree; menu bar + + +The <guimenu>File</guimenu> Menu + + + + + +File +Update + +Immediately updates the display to reflect the current +status + + + + + + +&Ctrl;Q + +File +Quit + +Closes &kdiskfree; + + + + + + +The <guimenu>Settings</guimenu> menu and dialog + + + + +Settings +Configure Shortcuts... + + +The standard &kde; dialog for setting shortcuts. + + + + + + +Settings +Configure KDiskFree... + + +Opens a configuration dialog. + +Configure &kdiskfree; Screen + + + + + + Configure &kdiskfree; Screen + + + + +This dialog has two tabbed windows, General Settings +and Mount Commands + + +General Settings Click on the word +visible or hidden to turn +display of an data field on or off. Change the update +frequency by moving the slider. The value in the box on the left is +the interval (in seconds) between updates of the &kdiskfree; display to +reflect the current status. The File Manager setting +controls the command executed when the Open +Filemanager pop-up menu item is selected. +There are also two check boxes. One controls if a file manager +window will be automatically opened when a device is mounted. The +other causes an alert window to pop up if a disk gets critically +full. + + + +Mount Commands +Allows the user to specify the mount and unmount commands for a +given device, as well as the icon used to represent it. More information on +these commands can be found on the man page for mount (type +man at the +command prompt). + + + + + + + + +The <guimenu>Help</guimenu> menu + +&help.menu.documentation; + + + + + + + +Credits and License + +&kdiskfree; + +Program Copyright © 1998-2000 &Michael.Kropfberger; &Michael.Kropfberger.mail; + +Documentation Copyright © 2000 &Jonathan.Singer; &Jonathan.Singer.mail; + +&underFDL; +&underGPL; + + + +&documentation.index; + + + diff --git a/doc/kdf/kdf.png b/doc/kdf/kdf.png new file mode 100644 index 0000000..737ec7c Binary files /dev/null and b/doc/kdf/kdf.png differ diff --git a/doc/kdf/kdf_config.png b/doc/kdf/kdf_config.png new file mode 100644 index 0000000..09c9c91 Binary files /dev/null and b/doc/kdf/kdf_config.png differ diff --git a/doc/kedit/Makefile.am b/doc/kedit/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/kedit/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kedit/index.docbook b/doc/kedit/index.docbook new file mode 100644 index 0000000..ee189ab --- /dev/null +++ b/doc/kedit/index.docbook @@ -0,0 +1,1255 @@ + + + + + +]> + + + +The &kedit; Handbook + + +ThadMcGinnis + +
ctmcginnis@compuserve.com
+
+
+ + +Lauri +Watts +
lauri@kde.org
+Reviewer +
+
+ +2003-09-16 +1.3 + +&FDLNotice; + +This Handbook describes &kedit;, a simple +text editor for &kde; + + +KDE +KEdit +text editor + + + +2000 +Thad McGinnis + + +
+ + +Introduction + +&kedit; is a text editor for the &kde; Desktop. It is a +small editor which can be used with &konqueror; for text and +configuration file browsing. &kedit; also serves well for creating small +plain text documents. It is not meant to be a programmers editor, in +particular it is not meant to replace any of the more powerful editors +such as &kate;, XEmacs or +Emacs. &kedit;'s functionality will +intentionally remain rather limited to ensure a reasonably fast +start. + + + + +Some Fundamentals + +&kedit; is very simple to use. Anyone that has used a text editor +should have no problems. + + +Drag and Drop + +&kedit; uses the &kde; Drag and Drop protocol. Files may be +dragged and dropped onto &kedit; from the Desktop, &konqueror;, or some +remote &FTP; site opened in one of &konqueror;'s windows. + + + + +Command Line Options + +Though &kedit; may most often be started from the &kde; program +menu, or a desktop icon, it can also be opened at the command line +prompt of a terminal window. There are a few useful options that are +available when doing this. + + +Specify a File + +By specifying the path and name of a particular file the user can +have &kedit; open (or create) that file immediately upon startup.This +option might look something like the following: + + +%kedit /home/myhome/docs/myfile.txt + + + + + +Specify a file on the Internet + +The above-mentioned method could even be used to open files on the +internet (if the user has an active connection at the time.) An example +of this might look like the following: + + +%kedit ftp://ftp.kde.org/pub/kde/Welcome.msg + + + + + +Other Command Line Options + +The following command line help options are available + + + +kedit + +This lists the most basic options available at the command +line. + + + + +kedit + +This lists the options available for changing the way &kedit; +interacts with &Qt;. + + + + +kedit + +This lists the options available for changing the way &kedit; +interacts with &kde;. + + + + +kedit + +This lists all of the command line options. + + + + +kedit + +Lists &kedit;'s authors in the terminal window + + + + +kedit + +Lists version information for &Qt;, &kde;, and &kedit;. Also +available through kedit + + + + + + + + + +Key Bindings + +Many of the key bindings (shortcuts) are configurable by way of +the Settings menu. By default &kedit; +honors the following key bindings. + + + + + +Key Binding +Action + + + + + +Left Arrow +Move the cursor one character leftwards. + + + +Right Arrow +Move the cursor one character rightwards. + + + +Up Arrow +Move the cursor one line upwards + + + +Down Arrow +Move the cursor one line downwards. + + + +Page Up +Move the cursor one page upwards. + + + +Page Down +Move the cursor one page downwards. + + + +Backspace +Delete the character to the left of the cursor. + + + +Home +Move the cursor to the beginning of the line. + + + +End +Move the cursor to the end of the line. + + + +Delete +Delete the character to the right of the cursor. + + + +&Shift;Left +Arrow +Mark text one character leftwards. + + + +&Shift;Right +Arrow +Mark text one character rightwards. + + + +&Ctrl;A +Select all the text in the document. + + + +&Ctrl;B +Move the cursor one character leftwards. + + + + +&Ctrl;C +Copy the marked text to the clipboard. + + + +&Ctrl; +D +Delete the character to the right of the +cursor. + + + +&Ctrl;E +Move the cursor to the end of the line. + + + +&Ctrl;F +Search for text in the document. + + + +&Ctrl;G +Go to line. + + + + +&Ctrl;H +Delete the character to the left of the +cursor. + + + +&Ctrl;K +Create a new document + + + +&Ctrl; +N +Move the cursor one line downwards. + + + +&Ctrl; +P +Print. + + + +&Ctrl;V +Paste the clipboard text into the document at the text +cursor position. + + + + +&Ctrl;X +Cut the marked text, copying it to the +clipboard. + + + +&Ctrl; +Y +Yank (paste) the content of the kill-buffer (clipboard) +into the document, at the current cursor position. + + + + + + + + + + +The Menu Entries + + +The <guimenu>File</guimenu> Menu + + + + &Ctrl;N +FileNew + +This starts a new Document in a new instance of the +editor. + + + + + &Ctrl;O +FileOpen... + + +This command opens a file. It does this by means +of a dialog box which allows the user to navigate the file +system. + +The dialog operates like a small file manager. Clicking on +folders displayed in the central window directs the dialog to enter +that folder - displaying its contents. There is an entry/drop down +box which can be used to directly type in the location and name of the +file or by clicking the arrow at the side choose from a drop down list of +recently used locations. + + Below this is a filter which similarly may have data entered +directly or chosen from a drop down list of recent filter types. The +filter facility lets only files that meet its specifications be +displayed in the central window. If the filter contained text such as +*.txt then only files with the txt +extension would be visible in the selection window. + +The toolbar has left and right arrow buttons that let the user +move back and forth through previously selected folders as well as +an up arrow button for moving up the folder tree. The button with the +little house takes the user to his or her home folder, and the one +with the two arrows curved in on each other updates the view of the +current folder. The flag button lets the user set a new bookmark at +the current folder or go to one that was previously set. The icon of +the folder with the sparkle on it, allows you to create a new +folder. Finally there is drop down box on the toolbar with a list of +some commonly frequented folders. + + + + +FileOpen +Recent + + + +This is a shortcut to open recently saved +documents. Clicking on this item opens a list to the side of +the menu with a list of several of the most recently saved +files. Clicking on a specific file will open it in &kedit; - if the file +still resides at the same location. + + + + +&Ctrl;S +FileSave + +This saves the current document. If there has +already been a save of the document then this will overwrite the +previously saved file without asking for the user's consent. + + +The editor can be configured to make a backup. + + +If it is the first save of a new document the save as dialog +(described below) will be invoked. + + + + + +FileSave +As... + +This allows a document to be saved with a new file +name. This is done by means of the file dialog box described +above in the Open section of this help +file. + + + + + +&Ctrl;P +FilePrint... + +This opens a simple print dialog allowing the user to +specify what, where, and how to print. The user can choose +between the standard lpr or a custom command as well +as whether to print the whole document or a selected section. + + + + + +FileMail... + +This is used to email the current document. It +calls a mail dialog whereby the user can enter the address and subject +for the message. + +You may set your preferred mail client in &kcontrol; + + + + + + &Ctrl;W +FileClose + +This will close the editor window, if you have +more than one instance of &kedit; running, those instances will not be +closed. + + + + + +&Ctrl;Q + +File +Quit + +This closes the editor. + + + + + + + +The <guimenu>Edit</guimenu> Menu + + + + &Ctrl;Z +EditUndo + +This is used to eliminate or reverse the most recent user +action or operation. + + + + + &Ctrl;&Shift;Z +EditRedo + +This will reverse the most recent change (if any) +made using Undo. + + + + + &Ctrl;X +EditCut + +This command deletes the current selection and places it +on the clipboard. The clipboard is a feature of &kde; that +works invisibly to provide a way to transfer data between +applications. + + + + + &Ctrl;C +EditCopy + +This copies the currently selected text to the clipboard +so that it may be pasted elsewhere. The clipboard is a feature +of &kde; that works invisibly to provide a way to transfer data between +applications. + + + + + &Ctrl;V +EditPaste + +This will insert the contents of the clipboard at the +cursor position. The clipboard is feature of &kde; that works +invisibly to provide a way to transfer data between applications. + + + + + +&Ctrl;A +EditSelect +All + +This will select the entire document. This could +be very useful for copying the entire file to another +application. + + + + + &Ctrl;F +EditFind... + +This opens the find dialog which is used to +specify the text to Find in the document. There is +small text box for entering the search pattern. Two other options are +included to make the search more efficient. Selecting Case +sensitive will limit finds to entries that match the case +(upper or lower) of each of the characters in the search +pattern. Find backwards directs the search to +proceed in an upwardly direction. + + + + + F3 +EditFind +Next + +This repeats the last find operation, if any, without +calling the find dialog box. + + + + + &Ctrl;R +EditReplace... + +This command opens the replace dialog box. The +replace dialog is similar to the above-mentioned find dialog but with +the addition of a Replace with: text box. Using +this dialog the user can specify both the text to be found and text with +which to replace it. This dialog also contains two additional buttons. +The Replace button allows the user to make one +replacement at a time which is useful when not all instances of the +searched for text should be replaced. The Replace +All button should be used with caution as it will immediately +replace every instance of the specified text. + + + + + + +EditInsert +File... + +This opens the FileOpen dialog box whereby +the user can insert a complete file in the open +document. The file will be entered at the position of the +blinking text cursor. + + + + + + +EditInsert +Date + +This will enter the current date at the position of the +blinking text cursor. + + + + + + +EditClean +Spaces + +Choosing this item will remove from any selected +text any extra spaces and all carriage returns (the code for +the end of a paragraph brought about by pressing the +Enter key.) In other words, any occurrences of +two or more spaces will be reduced to one space; and all paragraphs and +blank lines will be reduced to one single +paragraph. + + + + + + +The <guimenu>Go</guimenu> Menu + + + + + +&Ctrl;G +GoGo to +Line... + +This opens the goto line dialog box which is used to have +the cursor jump to a particular line (specified by number) in the +document. The line number may be entered directly into the text +box or graphically by clicking on the up or down arrow spin controls at +the side of the text box. The little up arrow will increase the line +number and the down arrow decrease it. + + + + + + +The <guimenu>Tools</guimenu> Menu + + + + +ToolsSpelling... + +This initiates the spell checking program - a program +designed to help the user catch and correct any spelling +errors. Clicking on this entry will start the checker and bring +up the speller dialog box through which the user can control the +process. There are three text boxes lined up vertically just to the +left of center with their corresponding labels further to the left. +Starting at the top they are: + + + +Misspelled word: + +Here, the spell checker indicates the word currently under +consideration. This happens when the checker encounters a word not in +its dictionary - a file containing a list of correctly spelled words +against which it compares each word in the editor. + + + + +Replacement: + + If the checker has any similar words in its dictionary the first +one will be listed here. The user can accept the suggestion, type in +his or her own correction, or choose a different suggestion from the +next box. + + + + +Suggestions: + +The checker may list here a number of possible replacements for +the word under consideration. Clicking on any one of the suggestions +will cause that word to be entered in the +Replacement: box, above. + + + + +On dialog box are 8 buttons that allow the user to control the +spell check process. They are: + + + +Replace + +This button has the checker replace the word under consideration +in the document with the word in the Replacement: +box. + + + + +Replace All + +This button causes the checker to replace not only the current +Misspelled Word: but to automatically make the same +substitution for any other occurrences of this Misspelled +Word: in the document. + + + + +Ignore + +Activating this button will have the checker move on without +making any changes. + + + + +Ignore All + +This button tells the checker to do nothing with the current +Misspelled Word: and to pass over any other +instances of the same word. + + +This only applies to the current spell check run. If the checker +is run again later it will stop on this same word. + + + + + +Add + +Pressing this button adds the word in the Misspelled +Word: box to the checker's dictionary. This means that in the +future the checker will always consider this word to be correctly +spelled. + + + + +Help + +This invokes the &kde; help system starting at the &kedit; help +pages (this document). + + + + +Stop + +This button stops the spell check process. + + + + +Cancel + +This button cancels the spell check process. + + + + +Located horizontally along the bottom of the spell check dialog is +a progress bar. As the checking process proceeds the bar will fill from +left to right providing a graphical representation of how far along in +the document the process has reached. + + +A numerical display of the spell check process is simultaneously +displayed in the status bar of the editor. The status bar is the horizontal strip at +the bottom of the editor just outside of the text entry area. + + + + + + + + +The <guimenu>Settings</guimenu> Menu + + + + +SettingsShow +Toolbar + +When checked, this displays a movable toolbar containing +buttons used to initiate frequently used commands. The toolbar is most +commonly located at the top of the editor just under the menu. When +unchecked the toolbar is hidden. Clicking on the striated grip +will hide or unhide the bar. Clicking and dragging on this grip allows +the user to move the bar. + + + + + +SettingsShow +Statusbar + +When checked, this displays a small bar at the bottom of +the editor containing information about the status of the current +document. When unchecked the status bar is hidden. + + + + + +SettingsSave +Settings + +This saves the current editor settings to be used for +future documents. + + + + + +SettingsConfigure +Shortcuts... + +This command opens a dialog box whereby the key bindings may be changed. A display +window at the top of the dialog box shows the list of commands +available. Below the display are three radio buttons. The user may +choose a modifier key from None, +Default, and Custom. + + +Note that a set of radio buttons only allows the selection of one +of the offered items - in the way that buttons on a car radio only offer +the selection of one preset station. Also, the Default Key selection is +only available for those commands that actually have a +default shortcut.) + + + +Selecting the Custom key option activates the three check boxes and key +button at the bottom of the dialog. The user may then select a +combination of keys for the command in question by means of the check +boxes and key button. For example, with the About &kde; command selected +in the display window, the user could select &Ctrl; and &Alt;, click on +the key button, and then press the K key on the +keyboard. This would mean that anytime he or she held down the &Ctrl; +and &Alt; buttons and pressed K (while using &kedit;) +the About &kde; display box would be called. + + + + + +SettingsConfigure +Toolbars... + + +This will open the dialog whereby the toolbar +configuration may be changed. The user can choose which +shortcut buttons should appear on the toolbar, as well as whether and +where any text should appear with the buttons. Other choices include +button (icon) size and toolbar location (top, left, right, floating, or +flat.) Flat causes the toolbar to be retracted. A click on the striated +grip icon will extend it for use and another click retract it again. A +display window on the left lists the commands available to be placed on +the toolbar. A display on the right lists those commands already on the +toolbar. A set of four arrow buttons between the two displays +manipulates the selections. The right pointing arrow places any command +selected in the left pane onto the right pane, &ie;, it is added to the +toolbar. The left arrow does just the opposite, removing any action +selected in the right window from the toolbar. The up and down pointing +arrows change the position of an action selected in the right window +which changes the position of its button in the toolbar. + + + + + +SettingsConfigure KEdit... + +This menu item opens a dialog whereby several different settings may be adjusted. + + + + + + + +The <guimenuitem>Help</guimenuitem> Menu + +&help.menu.documentation; + + + + + +The Preferences Dialog + +Selecting +SettingsConfigure +KEdit from the menu brings up the preferences +dialog box. This dialog can be used to alter a number of different +settings. The settings available for change vary according to which +category the user chooses from a vertical list on the left side of the +dialog. By means of a row of five buttons along the bottom of the box +the user can control the process. She or he may invoke the +Help system, set the options to their +Default values, accept the current settings and +close the dialog by means of the OK button, +Apply the current choices to the document without +closing the dialog, or Cancel the process. The +categories Font, Color, +Spelling, and Miscellaneous +are detailed below. + + +Font + +The preferences dialog opens with this, the first category, +chosen. Here the user can change four settings and see the effects of +any changes in the text sample displayed in the rectangle at the bottom +or the box. The settings are: + + + + +Font: + +This scroll box allows the user to select by name from among the +various fonts available. The appearance of any selected font may be +seen in the sample text displayed in the rectangle at the bottom of the +dialog. + + + + +Font style: + +This, the center, selection box is used to choose between the four +basic styles of Regular, Italic, Bold, and Bold Italic. The appearance +of the selected style may be seen in the sample text displayed in the +rectangle at the bottom of the dialog. + + + + +Size: + +This, the rightmost scroll/selection box allows the user to change +font size. The larger the number chosen the larger the font size will +be. The sample text displayed in the rectangle at the bottom of the +dialog will reflect the choice of size. + + + + + + + + +Color + +This section provides access to two different color settings, +described below. Each of these settings may be changed by clicking on +its corresponding button. These are special wide buttons that are the +color of the current setting. Clicking on one of the buttons calls a +special color dialog box used to change the setting. + +The color dialog box provides a convenient and graphical way to +select a color. In the upper left of the box is a rectangular display +of a spectrum of colors. To the immediate right of this, is a vertical +bar displaying a range of intensity from the most dark at the bottom to +the most light at the top. The user may select and adjust a color by +clicking in these two boxes. Clicking in the rectangular display selects +a particular mix of red, green, and blue colors and in the vertical bar +selects a level of intensity (value). The various color attributes are +displayed in numerical form in small text boxes located directly below +the spectral rectangle and the user can see them change as the color is +adjusted. These attributes include the mix of the basic color +components (red, green, and blue) as well as hue and saturation levels. +Alternatively the user can enter figures directly in these boxes. There +is also a square at the bottom center of the dialog box which displays +the color which is under consideration at any time. To the right of +this display is another text box labeled HTML: This +shows the user the color code that would be used to specify the +particular displayed color in HTML code which is +widely used for web pages. + +In addition to the above, the color dialog allows the capture of +any color currently displayed on the desktop or in another program. +Clicking on the button with the dropper icon (located on the right side +of the dialog box) changes the shape of the mouse cursor to a set of +cross hairs. Clicking again will pick up the color attributes of +whatever color is displayed under the cross hairs. + +Furthermore the user has the option of adding any color to a +personal palette of Use custom colors by clicking on +the wide button labeled Add to Custom Colors +(which is located above the display square.) This adds the current +color to the custom color palette. This palette and any other available +palettes can be displayed using the drop down selection box located +directly above the palette display at the top right of the dialog box. +Besides the custom colors, the user can access a number of pre-prepared +palettes. + + + +Use custom colors + +By default &kedit; will use your system color scheme. If this +is enabled, you may choose a Foreground and background color below. + + + + +Foreground color: + +Here the user can specify a color for the text used in +&kedit;. + + + + +Background color: + +Here the user can specify a color for the general background of +&kedit;. + + + + + + + + +Spelling + +A spell checker is a program designed to help the user catch and +correct any spelling errors. This section of the preferences dialog +allows certain key settings to be adjusted in this regard. + + + +Create root/affix combinations not in +dictionary + +Selecting this option allows the spell checker to register as +correct combinations of root words with suffixes or +prefixes even if the particular combination is not listed in its +dictionary database of words. + + + + +Consider run-together words as spelling +errors + +Selecting this will cause the spell checker to register as +misspelled two or more correctly spelled words that are +run-together, &ie;, that do not have spaces separating +them. + + + + +Dictionary: + +Depending on the user's installation, one or more different +language spelling dictionaries may be available. This drop down box +allows the user to choose which language the spell checker should +use. + + + + +Encoding: + +There are different coding systems used to associate particular +codes with particular characters and symbols. If the user knows which +code he or she is using this drop down box allows this code to be +specified so that the spell checker can do its job correctly. + + + + +Client: + +Since &kedit; does not contain its own spell checker, an external +one must be chosen. This is where the user may specify which spell check +program to use. + + + + + + + +Miscellaneous + +This category deals with three different properties detailed +below. + + + +Word wrap: + +Word wrap is a feature that causes the editor to automatically +start a new line of text and move (wrap) the cursor to the beginning of +that new line. The drop down box at the top of the dialog provides the +following three word wrap choices: + + + +Disable Wrapping + +Choosing this will keep the editor from doing any wrapping. The +user will have to start new lines manually (with the +Enter key.) + + + + +Soft wrapping + +This choice has the editor automatically adjust the line lengths +to fit its current width. In other words, the wider the user makes the +editor the longer the lines will be; and the narrower the editor, the +shorter the lines will be. These line breaks are not saved in the file. + + + + +At specified column + +Choosing this activates a text box immediately below, labeled +Wrap column:. Here the user may specify the +maximum number of characters in a line of text. + + + +Each character including spaces fills one column. + + + + + + + + + +Make backup when saving a +file + +This check box tells the editor to rename the last saved version of +the current document before carrying out a save +command. The editor does this by adding a tilde (~) at +the end of the name of the original file. In this way the user has a +chance to recover a document if she or he had mistakenly saved something +over it. + + + + + + + + + +Credits and Licenses + +&kedit; Copyright 2000 by Bernd Johannes Wuebben +wuebben@math.cornell.edu + +Documentation Copyright 2000 by Thad McGinnis +ctmcginnis@compuserve.com. + +This version of the &kedit; Handbook is based on the original by: +Bernd Johannes Wuebben wuebben@math.cornell.edu + + + +&underFDL; +&underGPL; + + + + +Installation + +&install.intro.documentation; +&install.compile.documentation; + + + +
+ + diff --git a/doc/kfloppy/Makefile.am b/doc/kfloppy/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/kfloppy/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kfloppy/index.docbook b/doc/kfloppy/index.docbook new file mode 100644 index 0000000..9915f80 --- /dev/null +++ b/doc/kfloppy/index.docbook @@ -0,0 +1,614 @@ + + + + + + BSD"> + Minix"> +]> + + + + + + + + +The &kfloppy; Formatter Handbook + + + +Thad +McGinnis +
ctmcginnis@compuserve.com +
+ + +Nicolas +Goutte +
goutte@kde.org +
+ + +Bernd +Johannes +Wuebben +
wuebben@math.cornell.edu
+Developer +
+ + +Chris +Howells +
howells@kde.org
+Developer (User Interface re-design) +
+ + +Adriaan +de Groot +
groot@kde.org
+Developer (Add BSD support) +
+ + +Lauri +Watts +Reviewer +
lauri@kde.org
+
+ + +
+ +2005-06-01 +3.5 + + +2000 +Thad McGinnis + + + +2005 +Nicolas Goutte + + +&FDLNotice; + +&kfloppy; Formatter is a utility that provides a +straightforward graphical means to format 3.5" and 5.25" floppy +disks. + + +KDE +kfloppy +floppy +format + + +
+ + +Introduction + +&kfloppy; Formatter is a utility that provides a straightforward +graphical means to format 3.5" and 5.25" floppy disks. + +&kfloppy; depends on external programs and therefore +currently works only with &Linux; and &BSD;. Depending if you are +using &kfloppy; on &Linux; or on &BSD;, &kfloppy; has slightly different +features. + +Make sure that your floppy disk is not +mounted. &kfloppy; cannot format a mounted floppy disk. + + + + +Using &kfloppy; + +Starting &kfloppy; opens a single window by which the user may +choose appropriate settings and control the formatting process. These +options and controls are detailed below. + +Make sure that your floppy disk is not +mounted. &kfloppy; cannot format a mounted floppy disk. + + +Control Settings + +The settings are chosen by means of three drop down boxes located +at the top left center of &kfloppy;. + + +Floppy Drive + +Clicking on the top drop down box, which is labeled +Floppy drive:, offers the user the following +two choices: + + +Primary +Secondary + + +Clicking on the second drop down box from the top, which is labeled +Size:, offers the user the following +four choices: + + +3.5" 1.44MB +3.5" 720KB +5.25" 1.2MB +5.25" 360KB + + +The &Linux; version of &kfloppy; has also a choice of size named: + + +Auto-Detect + + + + +The 800KB disk format used by &Mac; floppy drives cannot be +supported on PC floppy drives since they are not capable of formatting +disks in that fashion. + + + + +<guilabel>File Systems</guilabel> + +The third drop down box, labeled File System, offers the user the +following choices, if they are applicable: + + + +Dos + +This selection will have &kfloppy; place the MS-DOS/&Windows; type +of file system on the diskette. The user will most likely want to +choose this system if she or he will be using the diskette with those +operating systems as they do not recognize other system types. +(This is supported for &Linux; and &BSD;.) + + + + +ext2 + +This selection will have &kfloppy; place the type of file system +on the diskette which is most commonly used with &Linux;, however +seldomly on floppy disks. +(This is supported for &Linux; and &BSD;.) + + + + +UFS + +This selection will have &kfloppy; place the type of file system +on the diskette which is most commonly used with FreeBSD. The user will +likely want to choose this system if he or she will only be using the +floppy disk with FreeBSD. +(This is supported for &BSD; only.) + + + + +Minix + +This selection will have &kfloppy; place the type of file system +on the diskette which often used on floppy disks used with &Linux;, +(This is supported for &Linux; only.) + + + + + + + + +Formatting Options +Within the outline of a box in the left center of &kfloppy; the user +may find a set of five formatting options. The top two are a pair of radio +buttons. This term (radio buttons) indicates a set of options among +which only one can be selected - in the same way that only one preset +channel selection may be set on a car radio.The +bottom two options are for labeling the diskette. All are explained +below: + + +Formatting Method +&kfloppy; can format a disk in the following two ways: + + + +Quick Format + +This simply puts the new file system on the disk. +All data on the disk will be lost, even if the data itself will not erased. + + + +Zero out and quick format + +This format first puts zeros on the disk and then creates the new file system. +All data on the disk will be erased. + + + +Full Format + +A full format reallocates the tracks and sectors, puts the selected +file system on the disk, and then verifies the format, blocking out any bad +sectors it finds. +All data on the disk will be erased. + + + + + + + +Verify Integrity + +This tells &kfloppy; to check that the formatting was correctly +written to the floppy. This allows bad sectors to be identified. + + +If bad sectors a found during the verify phase of a Full Format, +the formatting is aborted and the file system is not written! + + + + + +Volume Label + +The bottom two features allow the user to add (or change) a +label to the diskette. If the Volume label: check +box is selected then the user can enter a name (label) for the +diskette that is to be formatted in the text box located immediately +below. When the diskette is subsequently formatted the label will be +written to the diskette. + +Due to a limitation of the DOS file system, a label can only be +at most 11 characters long. For simplification, &kfloppy; assumes that +this limit is true for all file systems. + +The file system &Minix; cannot have any volume label. In this +case, &kfloppy; will ignore the volume label. + + + + + + +The Buttons +There are three buttons located vertically along the right side of +&kfloppy;. + + + +Format + +This button +initiates the formatting process. Once the user is sure that all the +settings are correct he or she may begin the process by clicking on +this button. +There will be a change in the two long rectangular boxes +that span the bottom of &kfloppy;. + +The upper box is a status indicator that gives information about the +process underway, especially the error encountered during the processing. + +The lower box is a progress bar. This displays both graphically +and numerically the progress of first the formatting and then the +verification. Before starting it appears to be empty - showing only +the figure 0% in the center. As each process +takes place the progress is tracked graphically as the box fills from +left to right. At the same time the number in the center will +increase reflecting the precise percentage of the process that has +been completed. + +As &kfloppy; uses external programs to format the floppy disk, +it has to rely on these programs to give the right information for +being able to display the progress bar. Unfortunately, this is not the +case. Especially, the programs writing the file systems do not return +enough data, so that the progress bar will remain at 0%. + + +Make sure that your floppy disk is not mounted. +&kfloppy; cannot format a mounted floppy disk. + + +&kfloppy; does not unmount the +floppy by itself, as this could mean that the user may overwrite a floppy +disk with important data on it. + + + + +Help + +This invokes the &kde; help system starting at the &kfloppy; help pages +(this document). + + + + +Report Bug + +Report a problem to the &kde; team. + + + + +About KFloppy + +This displays version and author information of &kfloppy;. + + + + +About KDE + +This displays version and author information of KDE. + + + + + +Quit + +Clicking on this button will close &kfloppy;. + + + + + + + + + +Command line options + +Though &kfloppy; may most often be started from the &kde; program menu, +or a desktop icon, it can also be opened at the command line prompt of a +terminal window. There are a few options that are available when doing +this. They are: + + + +kfloppy +This lists the most basic options available at the command +line. + + + + +kfloppy +This lists the options available for changing the way +&kfloppy; interacts with &Qt;. + + + + +kfloppy + +This lists the options available for changing the way &kfloppy; +interacts with KDE. + + + + +kfloppy + +This lists all of the command line options. + + + + +kfloppy + +Lists &kfloppy;'s author in the terminal window + + + + +kfloppy + +Lists version information for &Qt;, &kde;, and &kfloppy;. Also available +through kfloppy + + + + + + + +Credits and Licenses + + + +&kfloppy; Formatter Program Copyright 1997 - 2000 Bernd Johannes Wuebben +wuebben@math.cornell.edu + +&kfloppy; Formatter Program Copyright 2002 Adriaan de Groot +groot@kde.org + +&kfloppy; Formatter Program Copyright 2004, 2005 Nicolas Goutte +goutte@kde.org + +Documentation Copyright 2000 by Thad McGinnis +ctmcginnis@compuserve.com. + +Documentation Copyright 2005 by Nicolas Goutte +goutte@kde.org. + +This version of the &kfloppy; Handbook is based on the original by +David Rugge davidrugge@mindspring.com + +&underFDL; +&underGPL; + + + + +Needed External Programs + +As already written earlier in this handbook, &kfloppy; works +with the help of external programs to do the different formatting tasks. + +If one of the programs is missing, &kfloppy; tries to work nevertheless. +However the corresponding option will not be available. + + + +fdformat +This program is needed for low-level formatting, +on &Linux; and on &BSD;. If it is missing, +Full format will be disabled. + + + +dd +This program is needed for zeroing-out, +on &Linux; and on &BSD;. If it is missing, +Zero out and quick format will be disabled. + + + +mkdosfs +This program is needed for DOS formatting, +on &Linux;. + + + +newfs_msdos +This program is needed for DOS formatting, +on &BSD;. + + + +newfs +This program is needed for UFS formatting, +on &BSD;. + + + +mke2fs +This program is needed for ext2 formatting, +on &Linux; and on &BSD;. + + + +mkfs.minix +This program is needed for &Minix; formatting, +on &Linux;. + + + + + + +User-Given Devices + + +Introduction + +"User Given Devices" is the work title of a still experimental feature of +&kfloppy;. It allows the user to give a device name and to use it nearly +as if it was a floppy drive. + +This feature is mainly intended as a work-around for users having +USB floppy drives of any kind +(including ZIP disk drives) or any other non-legacy +floppy drives. + +Unfortunately at the time of writing this documentation, the feature +is not very user friendly, as it does not offer any help to the user on how +a device is called and &kfloppy; does not even remember the device name from +call to call. (This is partially a security, as the device of the +floppy drive might change between reboots.) + +As this feature was developed under &Linux;, the &BSD; version +of &kfloppy; offers less choices than &kfloppy; under &Linux;. + + + + +Using It + + +Using "User Given Devices" is quite simple, you just need to enter +a device name, for example /dev/sdz4 +in the Floppy drive: combobox instead of +selecting Primary or Secondary. + + +You need to enter the /dev/ +part of the device for two reasons: + + +It is how &kfloppy; recognizes the "User Given Devices" mode. + + +It is a security, to avoid that the user writes anything in the combobox +that is by change a device name. + + + + +Unfortunately, using any device instead of a floppy device has a few +consequences. The major one is that Full Format cannot be +selected anymore. Doing so will result in a error message box when trying to +start the format. However you can use Zero out and quick format +instead. It will not format the device, just zeroing it out, but in practice it is +nearly the same; especially all data on the device will be erased. + +Be careful when entering the device name. &kfloppy; will pass +the device name as is to the external programs. Especially it does not check +(and the external programs do not check either) if the device is a +floppy drive device. If you give your any of your main +disk partitions as device, it will be accepted. (If the partition is mounted +or if you cannot write on this device, you +will probably get an error message nevertheless, avoiding the worst.) + +Even if you can specify a floppy device like +/dev/fd0u2880, &kfloppy; will refuse to make a +Full Format on it. + +On &Linux;, you can select any file system that you want. On &BSD;, +only UFS is currently supported (and not tested at time of writing this +documentation). + +When you are ready to format, click on the Format +button as usual. You will get a message box asking you to verify the device name. + + +This is the last chance to check the device name before formating. +After it, it is too late. + + + + + +
+ + diff --git a/doc/kgpg/Makefile.am b/doc/kgpg/Makefile.am new file mode 100644 index 0000000..5271453 --- /dev/null +++ b/doc/kgpg/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG=en +KDE_DOCS=kgpg + diff --git a/doc/kgpg/editor.png b/doc/kgpg/editor.png new file mode 100644 index 0000000..f435ac8 Binary files /dev/null and b/doc/kgpg/editor.png differ diff --git a/doc/kgpg/index.docbook b/doc/kgpg/index.docbook new file mode 100644 index 0000000..2f8f983 --- /dev/null +++ b/doc/kgpg/index.docbook @@ -0,0 +1,354 @@ + +Kgpg"> + + + + +]> + + + + +The &kgpg; Handbook + + + +Jean-Baptiste +Mardelle + +
bj@altern.org
+
+
+ + + +
+ + +2002 +Jean-Baptiste Mardelle + + +&FDLNotice; + +2002-03-01 +0.02.00 + + + +&kgpg; is a simple graphical interface for GnuPG (http://gnupg.org) + + + + +KDE +Kgpg +encryption +gpg +pgp +security + + +
+ + +Introduction + + +&kgpg; is a simple interface for GnuPG, a powerful encryption utility. GnuPG (also known as gpg) is included in most distributions and should be installed on your system. You can get the latest version on http://gnupg.org. + +With &kgpg; you will be able to encrypt and decrypt your files and emails, allowing much more secure communications. A mini howto on encryption with gpg is available on gnupg's web site. + + +With &kgpg;, you don't need to remember gpg's command lines and options. Almost everything can be done with a few mouse clicks. + + + + +Getting Started + +Here is a list of &kgpg;'s main components: + + + + +System Tray Icon + + + +&kgpg; system tray applet + + + + + + + +When you start &kgpg;, a system tray icon will appear. A &LMB; +click will open the Key Manager window, while a &RMB; click will open a menu allowing quick access to some important features. +You can also drop files or text on the applet icon to encrypt or decrypt it. + + + + + + +Key Manager Window + + + +Key manager window + + + + + + +That's the central place to manage your keys. To open the Key Manager window, &LMB; on &kgpg;'s applet. +You can import, export, sign and edit your keys. Most actions can be performed with a &LMB; click on a key. + + + + + +Editor Window + + + +Editor window + + + + + + +It's a simple text editor, where you can type or paste text to encrypt/decrypt it. To open the editor, &RMB; on &kgpg;'s applet. + + + + + + +Konqueror Integration + + +&kgpg; is integrated in &konqueror;. It means that when you right click on a file, you can choose + ActionsEncrypt +File to encrypt a file. You can decrypt a file with a &LMB; click. + + + + + + + + + +Using &kgpg; + + +There are two ways to encrypt your data: + +Symmetrical encryption: your data is just encrypted with a password. Anybody who has a computer with gpg can decrypt your message if you give him/her the password. To perform a symmetrical encryption, choose "symmetrical encryption" in the options box when asked to choose an encryption key. +Key encryption: you must first create your key pair (secret key and public key) and give a passphrase. Keep your secret key in a safe plece, and exchange your public key with your friends. Then, if you want to send an encrypted message to Alex, you must encrypt the message with Alex's public key. To decrypt the message, the recipient will need Alex's secret key and passphrase. + + +Key encryption is a bit more complicated (you must exchange keys with your friends) but safer. Remember that if you encrypt a key with someone else's key, you will not be able to decrypt it. You can only decrypt messages that have been encrypted with your public key. + + +Generating a key + +If you don't have a key, &kgpg; will automatically pop up +the key generation dialog at the first startup. You can also access it +in the Key Manager from +KeysGenerate Key +Pair. + + +Key generation dialog + + + + + + +Simply enter your name, Email address and click +Ok. This will generate a standard gpg key. If +you want more options, you can click on the Expert mode button, which +will bring up a &konsole; window with all of gpg's options. + + + + +Encrypting Your Data + + + +Encrypting a File From &konqueror; + +Click on the file you want to +encrypt with the &RMB;. Choose ActionsEncrypt +File in the pop up +menu. You will then be prompted with the Public key selection +dialog. Choose the key of the recipient and click Encrypt. The +encrypted file will be saved with a .asc or .gpg extension depending on whether you +chose ASCII encryption or not. + + + + +Encrypting a File or Text With &kgpg;'s Applet + +Simply drop your file on the &kgpg; system tray applet. If it is +an unencrypted file, &kgpg; will pop up the key selection dialog (see +below). Select the encryption key, and the encrypted file will be +saved. If you drop text, the encrypted text will be pasted to the +clipboard. You can also encrypt clipboard by selecting the +Encrypt clipboard item in applet +menu. + + +Here's a screen shot of the key selection window + + + + + + +For more information on the encryption options ASCII +armor, Allow encryption with untrusted keys and +Symmetrical encryption, please refer to gpg's +documentation or man pages. + + + + +Encrypting Text From &kgpg;'s editor + +This is as simple as clicking on the +Encrypt button. You will then be prompted with +the Public key selection dialog. Choose your key and click +Encrypt again. The encrypted message will +appear in the editor window. + + + + + +Decrypting Your Data + + + +Decrypting a File From &konqueror; +Left click on the file you want to +decrypt. Enter your passphrase and it will be decrypted. You can also +drag an encrypted text file and drop it into &kgpg;'s editor window. It +will then ask the passphrase and open the decrypted text in &kgpg;'s +editor. You can even drop remote files ! You can also use the +FileDecrypt +File and choose a file to decrypt. + + + + +Decrypting Text or a File With the &kgpg; applet + +You can drop an encrypted file or selected text on the &kgpg; +system tray applet. You will then be prompted for passphrase, and the +decrypted file/text will be saved or opened in the &kgpg; editor +depending from how you configured the applet. You can also decrypt +clipboard with the decrypt clipboard menu +entry of the &kgpg; applet + + + + +Decrypting a text from the editor + +Copy or Drag and Drop the text you want to decrypt, and click on +the Decrypt button. You will be prompted for the +passphrase. + + + + + + +Key Management + +All basic key management options can be performed through +&kgpg;. To open the key management window &LMB; on &kgpg;'s applet. +Most options are available with a right click on a key. +To import/export public keys, you can use drag +and drop or the Copy/Paste keyboard shortcuts. + + +Here's a screen shot of key management + + + + + + + + + +Configuring &kgpg; + +Configuration is accessible through the &kgpg; applet menu (&RMB; +click on the applet). You can set default parameters for encryption, +decryption, user interface and applet. Most encryption options are +directly related to gpg and are documented in it's man page. + + +Here's a screen shot of the option dialog + + + + + + + + + + + + + +Credits and License + + +&kgpg; + + +Program copyright © 2002-2003 Jean-Baptiste Mardelle +bj@altern.org. + + + +&underFDL; +&underGPL; + + + +&documentation.index; + +
+ + + + diff --git a/doc/kgpg/keygen.png b/doc/kgpg/keygen.png new file mode 100644 index 0000000..6bad563 Binary files /dev/null and b/doc/kgpg/keygen.png differ diff --git a/doc/kgpg/keymanage.png b/doc/kgpg/keymanage.png new file mode 100644 index 0000000..4dcd05b Binary files /dev/null and b/doc/kgpg/keymanage.png differ diff --git a/doc/kgpg/keys.png b/doc/kgpg/keys.png new file mode 100644 index 0000000..5977ddc Binary files /dev/null and b/doc/kgpg/keys.png differ diff --git a/doc/kgpg/kicker.png b/doc/kgpg/kicker.png new file mode 100644 index 0000000..359b143 Binary files /dev/null and b/doc/kgpg/kicker.png differ diff --git a/doc/kgpg/options.png b/doc/kgpg/options.png new file mode 100644 index 0000000..40a2776 Binary files /dev/null and b/doc/kgpg/options.png differ diff --git a/doc/khexedit/Makefile.am b/doc/khexedit/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/khexedit/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/khexedit/index.docbook b/doc/khexedit/index.docbook new file mode 100644 index 0000000..fc03585 --- /dev/null +++ b/doc/khexedit/index.docbook @@ -0,0 +1,1063 @@ + + + + + +]> + + + +The &khexedit; Handbook + + + +Jonathan +Singer + +
jsinger@leeta.net
+
+
+ + +Espen +Sand + +
espensa@online.no
+
+Developer +
+ + +Lauri +Watts + +
lauri@kde.org
+
+Reviewer +
+ + +
+ + +1999-2000 +Jonathan Singer + + +&FDLNotice; + +2001-07-06 +0.08.05 + +&khexedit; is a hexadecimal editor for the &kde; +environment. + + +KDE +Kapp +edit +binary +hexadecimal + +
+ + +Introduction + +&khexedit; is an editor for the raw data of binary files. It +includes find/replace functions, bookmarks, many configuration options, +drag and drop support and other powerful features. + + + + +Starting &khexedit; +Type khexedit at a command +prompt or select Binary Editor from the +Utilities group in the KDE start +menu. + +The standard &Qt; and &kde; command line +options are available, and can be listed by entering +khexedit . + +Other command line options are: + + - open the +specified file + + +<offset> jump to position +<offset> in the opened file. + + + + +&khexedit; In A Nutshell + +The main &khexedit; window has the following components: menu bar, toolbar, +offset column, data editor window, text field, search bar, conversion field and +status bar. + + +&khexedit; Screen + + + + + + &khexedit; Screen + + + + +When a document is opened, the bytes are displayed in hexadecimal format +in the data editor window. The data can be edited, cut, copied, pasted, dragged +and dropped much as text is in an text editor or word processor. A cursor marks +the current position. Pressing the Insert key toggles between +overwrite and insert text entry modes. The data can also be displayed as octal, +binary or decimal values, by choosing the desired format in the +View menu. + +The offset column on the left indicates the position of a particular byte +in the file. The text field on the right displays the ASCII +encoding of the file. The cursor position and edits in the data editor window +are reflected in the text field. The text field can also be edited, and those +changes are reflected in the data editor window. + +The search bar allows the user to search for a specific value -- +hexadecimal, octal, binary, decimal or text. + +The conversion field displays the value of the byte at the cursor position +in a variety of bases. It also displays the value of all standard data types +starting at the cursor. + +Multiple documents can be open at the same time but only one can be +active. Use the Documents menu to select which document will +be active. + + + + +Menu Commands + +Note that most menu commands also have a keyboard shortcut. + + +<guimenu>File</guimenu> Menu + + + + + +&Ctrl;N + +File +New + +Open a new file. + + + + + +&Ctrl;O + +File +Open... + +Open an existing file. + + + + + +&Ctrl;I + +File +Insert... + +Insert an exiting file in the current +document. + + + + +File +Open Recent + +Choose from a list of the last opened +files. + + + + +File +Revert + +Return edited document to the last saved +state. + + + + + +&Ctrl;S + +File +Save + +Save document. + + + + +File +Save As... + +Save document with a new name. + + + + + +&Ctrl;W + +File +Close + +Close the current document. + + + + + +&Ctrl;P + +File +Print... + +Print the current document. + + + + +File +Export... + +Export the selected document or a portion of +it.Opens a dialog box with these options: + + +Format +Plain text, HTML table, rich text +format, C array. Use the Options tab to select +details for a C array or an HTML table. + + +Destination +The file to which the data will be +exported + + +Export Range +Selects which data will be exported -- the entire document, the +selected portion or the range between two specified +offsets. + + + + + + +File +Cancel Operation + +Stop the current operation + + + + +File +Permissions + +Set write privileges: + + + +Read only +When set, changes may not be made to the displayed +file. + + +Allow Resize +When off, individual bytes may be edited but the total number of +bytes may not be changed. + + + + + + + +File +New Window + +Open an additional &khexedit; +window + + + + +File +Close Window + +Close the current &khexedit; +window + + + + + +&Ctrl;Q + +File +Quit + +Close all &khexedit; windows + + + + + + +<guimenu>Edit</guimenu> Menu + + + + + +&Ctrl;Z + +Edit +Undo + +Undo the last action. + + + + + +&Ctrl;&Shift;Z + +Edit +Redo + +Redo the last undone action. + + + + + +&Ctrl;X + +Edit +Cut + +Delete the selected bytes and copy them to the +clipboard. + + + + + +&Ctrl;C + +Edit +Copy + +Copy the selected bytes to the +clipboard. + + + + + +&Ctrl;V + +Edit +Paste + +Insert the cut or copied bytes in the +clipboard. + + + + +Edit +Special + +Variations on Copy and +Paste: + +Copy as Text: Copies +the selected bytes as ASCII characters. +Paste into New +File. +Paste into new +window. + + + + + + + +&Ctrl;A + +Edit +Select All + +Select entire document. + + + + +Edit +Unselect + +Unselect entire document. + + + + + +&Ctrl;F + +Edit +Find... + +Find a specified pattern in the document. +Hexadecimal,decimal, octal, binary or text patterns can be searched for. +Options in the dialog box allow you to specify the starting point, +direction and range of the search. + + + + + +F3 + +Edit +Find Next + +Find the next instance of the +Find pattern. + + + + + +&Shift;F3 + +Edit +Find Previous + +Find the previous instance of the +Find pattern. + + + + + +&Ctrl;R + +Edit +Replace... + +Replace the find pattern with a different +pattern. + + + + + +&Ctrl;G + +Edit +Goto Offset... + +Move the cursor to a specified +offset. + + + + + +&Ctrl;Ins + +Edit +Insert Pattern... + +Insert a specified string of bytes. +Options in the dialog box allow you to specify the length of the pattern, +its format (hexadecimal, decimal, octal, binary or text) and the insertion +point. +If Repeat pattern is checked, the specified pattern +will be inserted repeatedly to reach the length set in +Size. + + + + + +<guimenu>View</guimenu> Menu + + + + +ViewHexadecimal +ViewDecimal +ViewOctal +ViewBinary +ViewText + +The first five choices select the format displayed in the data +editor window: hexadecimal, decimal, octal, binary or text. When text +display is selected, the extra text field is not displayed. + + + + +View +Show Offset Column + +Toggles display of offset column on and +off. + + + + +View +Show Text Field + +Toggles display of text field on and +off. + + + + +View +Offset as Decimal + +When set, all offsets are displayed and interpreted as +decimal numbers rather than as hexadecimals. + + + + +View +Upper Case (Data) + +When set, hexadecimal digits in the data are displayed +in upper case. + + + + +View +Upper Case (Offset) + +When set, hexadecimal digits in the offset value are +displayed in upper case. + + + + +View +Document Encoding + +Select the encoding used for display in the text field. +Alternative encodings like EBCDIC and 7-bit +ASCII can be used. Additional encodings can be added by the +user (not implemented yet.) + + + + + + +<guimenu>Bookmarks</guimenu> Menu + + + + + +&Ctrl;B + +Bookmarks +Add Bookmark + +Bookmark a location within the document. +Multiple bookmarks can be set for a single document. Each document has its +own set of bookmarks and the appropriate set is displayed at the bottom of the +Bookmarks menu when a document is selected. Choose a bookmark +from the menu to go to it. + + + + + +&Ctrl;E + +Bookmarks +Replace Bookmark + +Reset an existing bookmark to the current cursor +location. A dialog will be opened with the list of available bookmarks; +select the one you wish to change. + + + + + +&Ctrl;U + +Bookmarks +Remove Bookmark + +Remove an existing bookmark. A dialog will be +opened with a list of available bookmarks; select the one you wish to +remove. + + + + +Bookmarks +Remove All + +Clear the bookmark list. + + + + + +&Alt;Down + +Bookmarks +Goto Next Bookmark + +Move the cursor to the next +bookmark. + + + + +&Alt;Up + +Bookmarks +Goto Previous Bookmark + +Move the cursor to the previous +bookmark. + + + + + +<guimenu>Tools</guimenu> Menu + + + + +Tools +Extract Strings... + +Locate ASCII strings in the data. Minimum +string length, case sensitivity and a pattern to match can be +specified. + + + + +Tools +Binary Filter... + +Perform a binary operation on the data. The +operation (AND, OR, ROTATE..) and an operand can be specified in the dialog +box. Check boxes in the dialog allow the operation to be limited to selected +bytes or the region before or after the cursor. + + + + +Tools +Character Table + +Open a list of values and their ASCII +equivalents and insert the selected value at the +cursor. + + + + +Tools +Converter + +Enter a value in any of the fields and see its +equivalent in hexadecimal, decimal, octal, binary or text. A check box +allows viewing of the value at the cursor instead. + + + + +Tools +Statistics + +Display the frequency of occurrence of values in the +document. + + + + + + +<guimenu>Documents</guimenu> Menu + +Provides a list of the open documents. Selecting one makes it +active. + + + + +<guimenu>Settings</guimenu> Menu + + + + +Settings +Show Toolbar + +Toggle display of the toolbar below the +menu bar. + + + + +Settings +Show Statusbar + +Toggle display of the status bar + + + + +Settings +Show Full Path + +Toggle display of the full file path in the +titlebar + + + + +Settings +Document Tabs + +Change display of tabs for all current documents. The tab can be +displayed above or below the editor window, or hidden. You may find the tabs +more convenient than the document menu for switching documents. + + + + +Settings +Conversion Field + +Change display of the value conversion field. +It can be embedded in the main window, made a floating window or +hidden. + + + + +Settings +Searchbar + +Change display of the value search bar. It can be +displayed above or below the editor window, or hidden. + + + + +Settings +Save Options + +Save the current state of the +options. + + + + +Settings +Preferences... + +Change these settings: + + +Layout +Line and column size (in bytes). These can be set separately for +different modes. Fixed number of bytes per line. Lock column at end of +line. Grid lines between rows and columns. Width of field separators, spacing and +margins. + + +Cursor +Blink rate and shape of the cursor. Behavior of the cursor when +the window loses focus. + + +Font +Font name, style and size. Character used to display +non printing +characters in the text field. + + +Colors + All colors in &khexedit; can be customized, including odd and +even lines and columns, bookmarks, separators and grid lines. The one exception +is the selection color, which uses the setting chosen in the KDE Control +Center. + + +Files +Opening of the last, or all recent documents on +startup. Restoration of cursor position. Write protection enabled by +default. Make a backup upon saving files. Saving of Recent +Documents list on exit. The Recent Documents list can +also be cleared in this dialog. + + +Miscellaneous +Automatic copy to clipboard upon selection. Startup in insert +mode, rather than overwrite. Confirmation required for wrapping to the beginning +or end during searches. Cursor jumps to nearest byte when moved in binary +mode. Sound on typing input or fatal failure. Display of bookmarks in the offset +column and editor fields. Warning when number of printable pages exceeds a +settable limit. Maximum number of undos. + + + + + + + + + +<guimenu>Help</guimenu> Menu + +&help.menu.documentation; + + + +Toolbar +The toolbar contains icons for the following commands: + +(Except for Drag document and +Toggle write protection, all behave identically to the menu +command.) + + +Drag document -- Click this button and drag +to a text editor or a new &khexedit; window. +New +Open +Revert +Save +Print +Find +Find Next +Find Previous +Cut +Copy +Paste +Undo +Redo +Cancel Operation +Help + + +..and at the right of the toolbar.. +Toggle write protection - switch between read-only and +read/write modes. + + +Search bar + +The search bar is used to locate a specific value in the document. Enter a +value in the box, select the desired representation (hexadecimal, octal, binary, +decimal or text) and hit the Find button. Check the +Backwards box to search backwards from the cursor point or +check Ignore case for a case-insensitive text search. Click +the button on the right of the bar (X) to hide the search bar; +go to Searchbar in the Settings +menu to restore it. + + + + +Conversion field + +The conversion field displays the values of various data types at the +selected byte. For 8 bit types, it displays the value of the byte under the +cursor; for larger types, it displays the value starting at that byte. The +rightmost column displays various encodings of the current byte. Options in the +conversion field are: + + + +Show little endian decoding +When checked, causes multibyte types to be calculated using the +little-endian method used by x86 and Alpha processors. In this scheme, the first +byte represents the least significant part of the value. (0a 4e = 0x4e0a = +19978) When unchecked, causes multibyte types to be calculated using the +big-endian method used by PowerPC and Sparc processors. (0a 4e = 0x0a4e = +2638) + + + +Show unsigned as hexadecimal +When checked, causes unsigned types to be displayed in +hexadecimal, rather than decimal format. + + + +Stream length +Determines the number of bits used to calculate the values in +the fields above it. + + + + + + +Status Bar + +The status bar displays the following information: + + + +Encoding/Selection +When there is +no selection, this field shows the encoding option used. (See View +Document Encoding for more +information on encoding.) The start point and the length of the selection are +shown. + + + + +File Modified +A ! in this box indicates the +current file was modified. + + + +Insert/Overwrite +Indicates whether values entered at the keyboard are +inserted at the cursor point (INS) or overwrite the +existing data starting at the cursor(OVR). Use the +Insert key to toggle between the two modes. + + + +Size +Displays the total size of the current +document. + + + +Offset +Indicates the position of the cursor within the +document. + + + +Display mode +Indicates whether data editor window is displaying values in +hexadecimal, octal, binary, decimal or text mode. Switch between modes with +the View menu. + + + +Write Protection +Indicates whether the document can be edited +(RW) or is being viewed read-only +(R). Switch between modes with the button on the far-right +of the toolbar or the Permissions command in the +File menu. + + + + + + + + + + +Credits and License + + +&khexedit; + + +Program copyright 1999-2000 Espen Sand +espensa@online.no + +Contributors: + + +Leon Lessing leon@irlabs.com +Craig Graham +c_graham@hinge.mistral.co.uk +Dima Rogozin +dima@mercury.co.il +Edward Livingstone-Blade +sbcs@bigfoot.com + + +Documentation copyright 2000 Jonathan Singer +jsinger@leeta.net + + +&underFDL; +&underGPL; + + + + + +Compilation and Installation + +&install.intro.documentation; +&install.compile.documentation; + + + +&documentation.index; +
+ + diff --git a/doc/khexedit/khexedit1.png b/doc/khexedit/khexedit1.png new file mode 100644 index 0000000..9a61bdc Binary files /dev/null and b/doc/khexedit/khexedit1.png differ diff --git a/doc/kinfocenter/Makefile.am b/doc/kinfocenter/Makefile.am new file mode 100644 index 0000000..251280f --- /dev/null +++ b/doc/kinfocenter/Makefile.am @@ -0,0 +1,6 @@ + +SUBDIRS = $(AUTODIRS) + +KDE_LANG= en +KDE_DOCS = AUTO + diff --git a/doc/kinfocenter/blockdevices/Makefile.am b/doc/kinfocenter/blockdevices/Makefile.am new file mode 100644 index 0000000..36550bf --- /dev/null +++ b/doc/kinfocenter/blockdevices/Makefile.am @@ -0,0 +1,3 @@ + +KDE_LANG= en +KDE_DOCS = kinfocenter/blockdevices diff --git a/doc/kinfocenter/blockdevices/index.docbook b/doc/kinfocenter/blockdevices/index.docbook new file mode 100644 index 0000000..e6c44db --- /dev/null +++ b/doc/kinfocenter/blockdevices/index.docbook @@ -0,0 +1,89 @@ + + + +]> + +
+ + + + +Mike +McBride + + + + +2002-02-12 +3.00.00 + + +KDE +KControl +Block Devices +Disk space + + + + +Block Devices + + +The module window displays the available file devices and some +information about each device. It also allows you to control mount +points, and mount/unmount devices. + + + +Normally, the following pieces of information are shown in this tab: + + + +an icon depicting the type of storage +file format +total size +mount point +free disk space +the percentage of space used as a number and as a +graph. + + + +Left clicking on the header of a particular +column sorts the devices according to that variable. A second +left click sorts in the opposite order. + + + +Right clicking on a row pops up a menu. If +that device is not currently mounted, the Mount +device option is available. If the device is mounted, it +can be unmounted by choosing Unmount +device. Selecting Open +filemanager opens a new window with a graphical view of +the files on that device. + + + +The appropriate mount and unmount commands, and how the file manager is +opened from the context menu, can be configured from the &kdiskfree; +application. + + + +Section Author + +This section is modified from the kdf +documentation which was authored by Jonathan Singer +jsinger@leeta.net + +Modified for KDE 2.0 by Mike McBride +mpmcbride7@yahoo.com + + + + +
+ diff --git a/doc/kjots/Makefile.am b/doc/kjots/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/kjots/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kjots/index.docbook b/doc/kjots/index.docbook new file mode 100644 index 0000000..78e5620 --- /dev/null +++ b/doc/kjots/index.docbook @@ -0,0 +1,552 @@ + + + + + + +]> + + + +The &kjots; Handbook + + + +Matt +Johnston + +
matt.kde@caifex.org
+
+
+ + +Christoph +Neerfield + +
Christoph.Neerfield@home.ivm.de
+
+Developer +
+ + +Lauri +Watts + +
lauri@kde.org
+
+Reviewer +
+ + +
+ + +2000 +Matt Johnston + + +&FDLNotice; + +2004-10-17 +0.05.00 + +This handbook describes how to use &kjots; 0.5, a small +program which is handy for keeping miscellaneous +notes. + + +KDE +KJots +kdeutils +notes +organizer + + +
+ + +Introduction + +&kjots; is a small program that helps you to write down some short +notes and organizes them for you. + + + + +Using &kjots; + +&kjots; has two basic items used to organize your notes - +Books and Pages. + +You can create a number of books in &kjots;, and each book can +contain a number of pages, where you actually type your notes. Each book +should be given a name (so you can find what you are looking for), as +should each page. Although you aren't forced to give a page a name, it +is sensible to do so. + + +Using Books + +To create a new book, use &Ctrl;&Shift; +N or the menu entry +FileNew +Book, and you will be prompted to enter a +name for the new book. + +The name of the new book should now appear in the left part of +the window. If you want the book to be in your +Bookmarks, use &Ctrl; +B or the menu entry +BookmarksAdd Bookmark +. You can even organize your bookmarks in separate folders +just as you probably do in &konqueror;. + +If you want to have your books in a different order, you can +simply drag and drop the book to the place where you want it to be. + + +Maybe you have noticed that there is no Save anywhere. +This is not an error, &kjots; saves your books and pages automatically, +so you will never lose that small note you write when you are on the phone +and need to write down something in a hurry. + +You can also export an entire book as a text file or as a html file, +using File Export book... +. You will be then prompted to enter a +location for the file to be saved. The format of an example saved book +is shown below: + +############ +# First page +############ +Remember to go to the shops! + +############# +# Useful code +############# +10 PRINT "HELLO WORLD" +20 GOTO 10 + +################ +# The third page +################ +This is the third page and is an example for KJots. + +Remember that the dialog where you are prompted for a filename is +a standard &kde; dialog. That means it is just as easy to store the file +on your local hard disk as it is to save it on a web server, ftp server +or USB memory stick. So you can export as html and save it on a webserver, +this way you always have your notes available to you. + + + +Using Pages + +Pages are where you actually write whatever you are going to +write. Once you have created a book, you can type text in the main text +box. + +To create additional pages, you can use &Ctrl; +N or the menu entry +FileNew Page +, which will create a new page. Similarly, the current page +can be removed using File +Delete Page. + +If you need to insert the current date and time while you are +writing a note, you can use &Ctrl;I +. + +So that you can get to the page you want to see, pages can (and +should) be given a name. This can be done in the way you are used to: +select the page you want to rename, wait a second and click it once more. +You are then able to rename the page. Of course there is also a keyboard +shortcut, you can use that at any time while writing a note. The shortcut +is: &Ctrl;M. + +An other way of renaming the page is by selecting a part of your note +and then press &Ctrl;T, +the selected text will instantly become the title of the page. + +If you want fast access to a particular page, you +can assign a keyboard shortcut to that page. Go to +SettingsConfigure Shortcuts... +. + + + + +Command Reference + + +The <guimenu>File</guimenu> Menu + + + + + +&Ctrl;N + +File +New Page... + +Creates a new Page. + + + + + +&Ctrl;&Shift;N + +File +New Book... + +Creates a new Book. + + + + +File +Export Page + +Saves the current page to a text file +or a html file. + + + + +File +Export Book + +Saves the current book to a text file +or a html file. + + + + +File +Delete Page + +Deletes the current page. + + + + +File +Delete Book + +Deletes the current book. + + + + + +&Ctrl;P + +File +Print + +Prints the current book or page. + + + + + +&Ctrl;Q + +File +Quit + +Quits &kjots;. + + + + + +The <guimenu>Edit</guimenu> Menu + + + + + +&Ctrl;X + +Edit +Cut + +Cuts the currently selected +text in the main textbox and places it on the clipboard. + + + + + +&Ctrl;C + +Edit +Copy + +Copies the currently selected +text in the main textbox and places it on the clipboard. + + + + + +&Ctrl;V + +Edit +Paste + +Pastes text from the clipboard +to the main textbox. + + + + + +&Ctrl;T + +Edit +Paste as Page Title + +Renames the page to the text on the +clipboard. + + + + + +&Ctrl;F + +Edit +Find... + +Searches for text in the main +textbox. Note that this only searches the current page. + + + + + + +F3 + +Edit +Find Next + +Searches for the next occurrence +of the search text (specified with Find). + + + + + +&Ctrl;R + +Edit +Replace... + +Replaces one bit of text with another, +only on the current page. + + + + + + +&Ctrl;M + +Edit +Rename... + +Gives the possibility to rename the +current page. + + + + + +&Ctrl;I + +Edit +Insert Date + +Inserts the date and time in the +current page. + + + + + +The <guimenu>Bookmarks</guimenu> Menu + + + + + +&Ctrl;B + +Bookmarks +Add bookmark + +Adds the current page to the list of +bookmarks. See Using Books. + + + + + +Bookmarks +Edit bookmarks + +Edits the bookmarks. Here you can +search bookmarks, make comments, organize them in different folders and +much more. + + + + + +Bookmarks +New Bookmark Folder + +Makes a new folder where you can store +your bookmarks. + + + + + + +The <guimenu>Settings</guimenu> Menu + + + + +Settings +Hide/Show Toolbar + +Toggles display of the toolbar below the +menu bar. + + + + +Settings +Configure Shortcuts... + +Choose shortcut keys for various +menu items. + + + + +Settings +Configure Toolbars... + +Choose which items are present in the +toolbar. + + + + +Settings +Configure KJots... + +Configure options for &kjots;, including +the font to use and the settings for autosaving. + + + + + + + +The <guimenu>Help</guimenu> Menu + +&help.menu.documentation; + + + + + + + +Credits and License + + +&kjots; + + +Program copyright 1997 Christoph Neerfeld Christoph.Neerfeld@home.ivm.de + + +Based on the jots program included in the tkgoodstuff package. +The tkgoodstuff package is +copyright 1995-96 Mark Crimmins markcrim@umich.edu + + + +Documentation copyright 2000 Matt Johnston matt.kde@caifex.org + + +Some parts taken from documentation copyright 1998 Christoph Neerfeld +Christoph.Neerfeld@home.ivm.de + +&underFDL; + +&underGPL; + + + + +Installation + + +How to obtain &kjots; + +&install.intro.documentation; + + + + +Requirements + +In order to successfully use &kjots;, you need &kde; 2.x. There are +no other requirements. + + + + +Compilation and Installation + +&install.compile.documentation; + + + + +Configuration + +&kjots; is a nice small program, and you don't have do do anything +before running it. + + + + + +&documentation.index; +
+ + diff --git a/doc/ksim/Makefile.am b/doc/ksim/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/ksim/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/ksim/index.docbook b/doc/ksim/index.docbook new file mode 100644 index 0000000..02ecfee --- /dev/null +++ b/doc/ksim/index.docbook @@ -0,0 +1,66 @@ + + + + + +]> + + + + +The &ksim; Handbook + + + + + + + +
+
+
+ +
+ +&FDLNotice; + +2001-01-20 +0.00.00 + + + +&ksim; is part of the kdeutils package. + + + + + +KDE +kdeutils +ksim + + +
+ + +Introduction +The documentation for &kappname; was not finished when &kde; was installed on this computer. +If you need help, please check The KDE Website for updates, or by submitting your question to The &kde; User Mailing list. +The &kde; Team + +&underFDL; +&underGPL; + + + +&documentation.index; +
+ + diff --git a/doc/ktimer/Makefile.am b/doc/ktimer/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/ktimer/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/ktimer/index.docbook b/doc/ktimer/index.docbook new file mode 100644 index 0000000..5474ea9 --- /dev/null +++ b/doc/ktimer/index.docbook @@ -0,0 +1,66 @@ + + + + + +]> + + + + +The &ktimer; Handbook + + + + + + + +
+
+
+ +
+ +&FDLNotice; + +2001-01-20 +0.00.00 + + + +&ktimer; is part of the kdeutils package. + + + + + +KDE +kdeutils +ktimer + + +
+ + +Introduction +The documentation for &kappname; was not finished when &kde; was installed on this computer. +If you need help, please check The KDE Website for updates, or by submitting your question to The &kde; User Mailing list. +The &kde; Team + +&underFDL; +&underGPL; + + + +&documentation.index; +
+ + diff --git a/doc/kwallet/Makefile.am b/doc/kwallet/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/kwallet/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/kwallet/cr22-action-wallet_closed.png b/doc/kwallet/cr22-action-wallet_closed.png new file mode 100644 index 0000000..57558ac Binary files /dev/null and b/doc/kwallet/cr22-action-wallet_closed.png differ diff --git a/doc/kwallet/cr22-action-wallet_open.png b/doc/kwallet/cr22-action-wallet_open.png new file mode 100644 index 0000000..55a447f Binary files /dev/null and b/doc/kwallet/cr22-action-wallet_open.png differ diff --git a/doc/kwallet/edit1.png b/doc/kwallet/edit1.png new file mode 100644 index 0000000..1d0fe7c Binary files /dev/null and b/doc/kwallet/edit1.png differ diff --git a/doc/kwallet/edit2.png b/doc/kwallet/edit2.png new file mode 100644 index 0000000..05b6dd8 Binary files /dev/null and b/doc/kwallet/edit2.png differ diff --git a/doc/kwallet/edit3.png b/doc/kwallet/edit3.png new file mode 100644 index 0000000..9292870 Binary files /dev/null and b/doc/kwallet/edit3.png differ diff --git a/doc/kwallet/index.docbook b/doc/kwallet/index.docbook new file mode 100644 index 0000000..34b779e --- /dev/null +++ b/doc/kwallet/index.docbook @@ -0,0 +1,396 @@ + +KWallet"> + KWallet Manager"> + + + + +]> + + + +The &kwallet; Handbook + + + +&George.Staikos; &George.Staikos.mail; + + +&Lauri.Watts; &Lauri.Watts.mail; + + +GeorgeStaikos +
staikos@kde.org
+Developer +
+ +
+ +&FDLNotice; + +2005-06-15 +1.0 + + + +The wallet subsytem provides a convenient and secure way to manage all your +passwords. + + + + + +KDE +Kwallet +passwords +forms + + +
+ + +Introduction + +Computer users have a very large amount of data to manage, some of +which is sensitive. In particular, you will typically have many passwords +to manage. Remembering them is difficult, writing them down on paper or in +a text file is insecure, and using tools such at PGP is tedious and +inconvenient. + +&kwallet; saves this sensitive data for you in a strongly encrypted +file, accessible by all applications, and protected with a master +password that you define. + + +&kwallet; supports multiple wallets, so +for the most secure operation, you should use one wallet for local +passwords, and another for network passwords and form data. You can +configure this behavior in the &kwallet; &kcontrolcenter; module, however +the default setting is to store everything in one wallet. + + +A wallet is by default closed, which means that you must supply +a password to open it. Once the wallet is opened, the contents can +be accessed. + + + + +&kwalletmanager; + +&kwalletmanager; serves a number of functions. Firstly it allows you to see if +any wallets are open, which wallets those are, and which applications are +using each wallet. You can disconnect an application's access to a wallet +from within the &kwalletmanager;. + +You may also manage the wallets installed on the system, creating and +deleting wallets and manipulating their contents (changing keys, ...). + +Normally the &kwalletmanager; application is launched when +&kde; starts and remains in iconic form in the system tray. Alternatively, +when a wallet is opened, the &kwalletmanager; application will be +launched. A system tray icon indicates that a wallet is open: + + + + + + +When all +wallets are closed, the icon will reflect this by showing a closed +wallet: + + + + + + + + +Click once on the system tray wallet icon to display the &kwalletmanager; +window showing all available wallets as icons which reflect their +current status, either open or closed. + + + + + + + + + +The &kwalletmanager; Context Menu + +Right clicking on a wallet in the +&kwalletmanager; window offers +the following functions: + + + + +New Wallet... + +Create a new wallet. A dialog box will ask you +for the name of the new wallet that you want to create. + + + + +&Enter; +Open... + +Open the wallet. Opening the wallet causes the contents +of the wallet to be displayed in a new window where you can +add, delete, or modify the contents of the wallet. You may also +double click the wallet icon to cause it to open. If the wallet +is not already open, you will be requested to enter the password. +See below for details of using the wallet window. + + + + + + + + + + + + +Change Password + +Change the master password for the wallet. + + + + +Disconnect +Disconnect an application from the wallet. Currently +connected applications will appear in a submenu. + + + +Close +Force the wallet to be closed. + + + +Delete + +Delete the wallet + + + + + + +The Wallet Window + +Double clicking on a wallet in the &kwalletmanager; window will open a new +window displaying that wallet's contents. A wallet may contain any number +of folders, which allow storing of password information. By default a wallet +will contain folders named Form Data and Passwords. + + +The window has four panes: + + + + + + + + + +A summary of the contents of the current +folder +The folders contained in the wallet +The entries in the currently selected +folder +The contents of the selected folder entry + + +Folders may be added or deleted, and selecting a folder will update +the folder entry list and the summary display. Selecting a folder entry +will update the entry contents pane, and allow you to edit that +entry. + + + + + + + + +Entries may also be created or deleted via the context menu for the +folder contents. + +All folders and entries may be dragged and dropped into other wallets +or folders respectively. This allows a user to easily package up a new +wallet for transfer to another environment. For instance, a new wallet +could be created and copied onto a removable flash memory device. Important +passwords could be transferred there, so you have them available in other +locations. + + + + + + +Configuring &kwallet; + + +<guilabel>Wallet Preferences</guilabel> + +&kwallet; contains a small configuration panel with several options +that allow you to tune &kwallet; to your personal preferences. The +default settings for &kwallet; are sufficient for most users. + +Check the box to enable or disable the &kde; wallet subsystem +entirely. If this box is unchecked, then &kwallet; is entirely disabled and +none of the other options here have any effect, nor will &kwallet; record +any information, or offer to fill in forms for you. + + +<guilabel>Close Wallet</guilabel> + +Close when unused for: + +Close the current wallet after a period of inactivity. If you check this +option, set the period in the box, default is 10 minutes. When a wallet is +closed, the password is needed to access it again. + + + + +Close when screen saver starts + +Close the wallet as soon as the screensaver starts. When a wallet is +closed, the password is needed to access it again. + + + + +Close when last application stops using it + +Close the wallet as soon as applications that use it have stopped. Note +that your wallets will only be closed when all the applications that use it have +stopped. When a wallet is closed, the password is needed to access it +again. + + + + + +<guilabel>Automatic Wallet Selection</guilabel> + +Select wallet to use as default: + +Select which wallet you want to use as default wallet. + + + + +Different wallet for local passwords: + +If checked, choose a different wallet for local passwords. + + + + + +<guilabel>Wallet Manager</guilabel> + +Show manager in system tray + +Enable the wallet manager to have its icon in the system tray. + + + + +Hide System tray icon when last wallet +closes + +When there is no wallet in use anymore, remove the wallet icon from the +system tray. + + + + +Finally, there is a button labelled Launch Wallet +Manager, which does precisely that. + + + +<guilabel>Access Control</guilabel> + +There is only one option on this page: + + + +Prompt when an application accesses an open wallet + +Signal you when an application gains access to an open wallet. + + + + +Next there is a tree style view of the access controls for your wallets. + +&LMB; click on the + symbol beside a wallet name to +expand the tree. You will see the name of each application that has asked +for access to the wallet, and the policy you set for it. You cannot edit +policies here, or add them, but it is possible to delete an entry by &RMB; +clicking on it and choosing Delete From the +context menu that appears, or by simply selecting it and pressing the +Delete key. + + + + + + +Advanced Features + +Wallets can be dragged from the &kwalletmanager; window. This allows +you to drag the wallet to a file browser window, where you can choose to +copy, move, or link the wallet, as desired. + +You might use this to save a wallet to portable media, such as a +USB keychain, so that you can take your passwords with you to work or +on a vacation, and still have easy access to important sites. + +Future versions will have built-in functions for easy export or +copying of data to portable devices. + + + + +Credits and Licenses + +&kwallet; © 2003 &George.Staikos; +Documentation © &Lauri.Watts; and &George.Staikos; + + + +&underFDL; +&underGPL; + + + +&documentation.index; + +
+ + diff --git a/doc/kwallet/kwalletmanager.png b/doc/kwallet/kwalletmanager.png new file mode 100644 index 0000000..67c7220 Binary files /dev/null and b/doc/kwallet/kwalletmanager.png differ diff --git a/doc/kwallet/password1.png b/doc/kwallet/password1.png new file mode 100644 index 0000000..d5cb22a Binary files /dev/null and b/doc/kwallet/password1.png differ diff --git a/doc/kwallet/password2.png b/doc/kwallet/password2.png new file mode 100644 index 0000000..c116e93 Binary files /dev/null and b/doc/kwallet/password2.png differ diff --git a/doc/superkaramba/Makefile.am b/doc/superkaramba/Makefile.am new file mode 100644 index 0000000..085981d --- /dev/null +++ b/doc/superkaramba/Makefile.am @@ -0,0 +1,4 @@ + +KDE_LANG = en +KDE_DOCS = AUTO + diff --git a/doc/superkaramba/index.docbook b/doc/superkaramba/index.docbook new file mode 100644 index 0000000..df175f0 --- /dev/null +++ b/doc/superkaramba/index.docbook @@ -0,0 +1,261 @@ + +SuperKaramba"> + + + + +]> + + + +The &superkaramba; Handbook + + +Hans +Karlsson +karlsson.h@home.se + + + + + +2005 +Hans Karlsson + + +2005-08-04 +0.3.5 +&FDLNotice; + + +&superkaramba; is a tool that allows you to easily create interactive +widgets on your &kde; desktop. + + +KDE +desktop +karamba + + + + + + + + +Questions, Answers, and Tips + + +Frequently asked questions + +Installation + + +Where can I find &superkaramba; RPM's? + + + + +The SuperKaramba web site (http://netdragon.sourceforge.net) has a list of user-submitted RPMs for several distributions. Other user-subm +itted RPMs have been posted to kde-look.org and to the SuperKaramba Help +forum. + + + +When I try to compile, I get this error: +Python.h: No such file or directory + +You will need to install the python-devel +package. Once that package is installed you should run +./configure and make again. + + + +When I try to compile, I get this error: +cannot find -lselinux + + +You will need to install the libselinux-devel +package. Once that package is installed you should run +./configure and make again. + + + + +After running ./configure, make +and make install, the &superkaramba; executable is not +where I expected it to be. When I try to run superkaramba +from the command line it says command not +found. + + +In some distributions ./configure has a default prefix path that +differs to what you might expect. For example, in Mandrake the default +prefix is /usr/local/kde and the +executable is installed in /usr/local/kde/bin. +There are a few things you can do to fix this. +You could run ./configure +--prefix=/usr to specify the prefix that +you prefer and then try make and make +install again. Or you could create a symbolic link in your +preferred directory that links to the executable. Or you could add the +install directory to your $PATH. + + + + + +General + + +How do I get rid of the &kde; panel? Do I have to keep &kicker; +running? + +Many themes depend on &kicker; and will not work well without +it. If you don't want &kicker; to show on your desktop, you can set it to +auto-hide. Another solution is to change the auto-hide setting in a +~/.kde file. For more information see the wiki page about +secret +configuration settings. + + + + +Can I run a system tray theme while the &kicker; system tray is +running? + +It's better not to. If you run a theme with a SysTray on it +while a regular kicker systray is running, the theme will +steal all the icons from the first systray. This is because +in &kde; and Gnome, the systray icons are really little windows and there is +only one copy of each running. If you want to run a system tray theme, you can +remove the system tray from &kicker;. + + + + +How do I set up my themes to run automatically on startup? + + +Turn on &kde; session support in the &kcontrolcenter;. When session +support is enabled, any theme that is left running when you logout will +automatically start on startup. For some themes you will also need to &RMB; +click and reload the theme at least once after running it so that the config +file will get written to your home directory. +Another solution is to create a desktop config file in the &kde; +autostart directory. +To create a desktop config file, open an editor and enter the +following: +[Desktop Entry] +Exec=superkaramba {location of theme file}.theme +Name={theme name} +Type=Application +X-KDE-StartupNotify=false +Then save it as +themename.desktop into the +autostart directory at $KDEHOME/Autostart/. + + + +Why is the Edit Script option +disabled when I &RMB; click on a theme? +Some &superkaramba; themes don't include a +Python script. This is normal and those themes +will still work fine without one. However, if the theme does use a +Python script, &superkaramba; may have not been +able to load the script. This is usually due to +Python errors. Run the theme from the command line +to find out the specific error message. + + + + +Why is the Configure Theme menu disabled +when I &RMB; click on a theme? + + +The Configure Theme menu is only enabled if +the theme has added options to it. Some themes do not have any configuration +options or use a different configuration method. + + + + + +Troubleshooting + + +My themes start up in different locations each time I start +&kde;. + + +Close all &superkaramba; themes and then delete any session files in +$KDEHOME/share/config/session/ +that begin with &superkaramba;. Restart &kde; and start your themes again. Now +they will stay in the right place. + + + + +The backgrounds of my themes are black instead of transparent. + +In &kde;, transparency only works when the desktop background +is a wallpaper image that is centered or scaled. If the background is a +plain color or a tiled image then &superkaramba; themes will not be +transparent. In Gnome, there is a known issue that themes will have a black +background even when a wallpaper is set. Unfortunately there is no current +solution. Your theme should work fine otherwise. + + + + + + + + +Credits and Licenses + +&superkaramba; is written by +AdamGeitgey +adam@rootnode.org and +HansKarlsson karlsson.h@home.se + + + + + + +&underFDL; +&underGPL; + + + + + diff --git a/kcalc/ChangeLog b/kcalc/ChangeLog new file mode 100644 index 0000000..00abb5b --- /dev/null +++ b/kcalc/ChangeLog @@ -0,0 +1,387 @@ +2005-12-29 Klaus Niederkrger + * Fixed BUG 116835, BUG 118300, BUG 118909 + +2005-10-?? Klaus Niederkrger + * Added arbitrary precision + +2005-04-30 Klaus Niederkrger + * Fix BUG 100316 + +2005-04-25 Klaus Niederkrger + * Fix BUG 99817. + +2005-04-20 Klaus Niederkrger + * Change C-style casts for C++ casts, removed some C-style typedefs + +2005-04-02 Klaus Niederkrger + * GUI: added statusflags to display, looks very neat (this was + contributed by Bernd Brandstetter; well done!) + +2005-03-30 Klaus Niederkrger + * added a Memory-Store button (contributed by Bernd Brandstetter) + +2005-03-29 Klaus Niederkrger + * fix M+/- button to change when inverse is pressed + +2005-03-08 Evan Teran + * updated about box to reflect my correct email address. This one is + permanent and will never change again + +2005-02-05 Klaus Niederkrger + * fix BUG 98522: M- button did not work at least since KDE-3.2. Shame on me, and thanks to + Bernd Brandstetter for reporting the bug. + +2004-12-21 Klaus Niederkrger + * added some more contants and dropped Pi-button since not needed. + Instead new cube and cube root button. + +2004-12-17 Klaus Niederkrger + * almost finished feature which allows to choose from list + of scientific constants + +2004-12-17 Klaus Niederkrger + * started implementation of a list of scientific constants + +2004-12-06 Klaus Niederkrger + * further refactoring of configuration options for const buttons + +2004-12-05 Klaus Niederkrger + * understood how kconfigxt handles indexed configuration options + +2004-12-03 Klaus Niederkrger + * moving through history is now done via undo/redo + this implements wish BUG 93938 + +2004-11-23 Klaus Niederkrger + * improved const buttons + +2004-10-20 Klaus Niederkrger + * clean up Const-Buttons. More work still required. + +2004-10-16 Klaus Niederkrger + * improve Const-Buttons: set value by using INV-Button instead of config-menu + +2004-09-24 Klaus Niederkrger + * fixed BUG 90009: the display does not resize in vertical direction anymore + +2004-09-24 Klaus Niederkrger + * fixed small bug: switching off Logic-mode tried to change item in statusbar, + but item did not exist. + +2004-09-11 Klaus Niederkrger * + * fix bug 82433: show a check mark next to the angle mode in popup menu + +2004-09-10 Klaus Niederkrger * + * bundle precedence of operators and function pointers into a single + struct. + +2004-09-08 Klaus Niederkrger + * moved angle mode logic into GUI + +2004-09-04 Klaus Niederkrger + * reduced the number of entry points into the CalcEngine + Aim: enterOperation the only entry point + +2004-08-2? Klaus Niederkrger + * added some labels and tooltips for inverse mode + +2004-08-2? Klaus Niederkrger + * fix to BUG 74657 + * fix to BUG 78726 + +2004-07-30 Klaus Niederkrger + * Square root button did not work correctly after pressing CTRL (Bug 86004) + +2004-07-30 Klaus Niederkrger + * Added Accels for Const-Buttons + +2004-07-29 Klaus Niederkrger + * Fixed BUG 67984 (thanks to Andr Wbbeking) + +2004-07-17 Klaus Niederkrger + * Fixed BUG 85357 + +2004-06-05 Klaus Niederkrger + * It was not possible to paste a hex-number starting with "0x" in hex-mode, because hex-mode + prepended automatically "0x" leading to "0x0x...". + +2004-05-16 Klaus Niederkrger + * Refactored a bit the kcalc_button code. In particular use Richtext only, when needed (a bit faster, + but a lot still to be done). + +2004-05-04 Klaus Niederkrger + * Masked "&" for the label of the AND button, when displaying the corresponding accel. + Thanks to Sigrid from Trolltech. + +2004-04-27 Klaus Niederkrger + * Buttons have now their own modes (like inverse Mode etc.) + This allows moving tooltips and labels into kcalc_button.cpp + instead of having everything in kcalc.cpp. + This needs to be cleaned up and the tooltips and labels should be + revised. + +2004-04-05 Klaus Niederkrger + * Changed accel for OR-button from "O" to "|" + * More accels are visible, when "Ctrl" is used + * disable some buttons like "Sin", "Cos" etc., when not + in decimal mode + +2004-04-05 Klaus Niederkrger + * Pasted numbers in Hex-Mode are now always interpreted as + hex-numbers (BUG 65167). + +2004-03-26 Klaus Niederkrger + * Centered labels on buttons + +2004-03-24 Klaus Niederkrger + * Press (and hold) CTRL-key to see accels for all + buttons (BUG 69850). + +2004-03-19 Klaus Niederkrger + * Labels like e.g. "x^y" are drawn with QSimpleRichText + Need to center the labels better!! + * KCalcButton supports now two different labels, one for normal, one + for inverse mode. Switch between the two happens via a signal. + +2004-03-11 Klaus Niederkrger + * Moved functions that paint e.g. "x^y" to the KCalcButton-class. + +2004-03-01 Klaus Niederkrger + * Created class KCalcButton, which is now used for all QPushButtons. + This will allow later to change the labels more easily, if INV is + pressed, and mucho more... + +2004-02-25 Thomas Weber + * "x^2" and "x^y"-buttons have now superscripted labels + * pressing "INV"-button changes "x^2"-button to square-root etc. + +2004-02-25 Klaus Niederkrger + * Changed many accels from "accel()->insert()" to + "button->addAccel()". Fixes BUG 75555. + * deactivate EE-button, when Base != DEC + +2004-02-10 Klaus Niederkrger + * First step to fix bug 66397. Changing Basemode via Popupmenu is + too clumsy for most programmers. Maybe backport to KDE 3.2 later, + once it has been tested. GUI does not look nice. + +2004-02-06 Klaus Niederkrger + * Fixed bug 73437. Pasting empty clipboard made kcalc crash. + +2004-02-04 Klaus Niederkrger + * Moved more accels from keyPressEvent into accels + +2004-01-27 Klaus Niederkrger + * Fix paste-function: Pasting e.g. "123 \n" did not work + because of the trailing spaces and returns. + +2004-01-25 Klaus Niederkrger + * Applied patch from Thomas Weber: Creates buttons C1-C6 + to store constants + +2003-12-06 Klaus Niederkrger + * Fix problem with several identical labels in statusbar + with the help of newly added statusbar->hasItem. + +2003-12-06 Klaus Niederkrger + * Make Percent work the way it did in KDE-3.1 again (documentation + was not updated to this KDE-version, which confused me on 2003/08/28) + +2003-11-04 Klaus Niederkrger + * More reorganization and preparation for getting accels right. + +2003-10-31 Klaus Niederkrger + * Split Constructor into more subfunctions. + To be continued. + +2003-10-20 Klaus Niederkrger + * At last the calculator window resizes, when buttons are hidden/shown + * Added a few extra buttons to "fill gaps". + +2003-10-14 Klaus Niederkrger + * RadioButtons for Base and Angle converted to PopUpMenu+Button + * Layout changed + * Moved ENTER form keyPressedEvent to Accel() + +2003-10-10 Klaus Niederkrger + * Number buttons look like numeric keyboard (on US-keyboards that is) + * Initialize ToggleActions correctly + +2003-10-09 Klaus Niederkrger + * Reverted the menubar stuff after several complaints. + Now Kcalc-GUI looks again like on 2003-09-11. + +2003-09-30 Klaus Niederkrger + * Fixed bug (unitialized pointers) + +2003-09-26 Klaus Niederkrger + * Moved all type of buttons to menubars, which can be hidden/showed + via the menubar. This is quite experimental and full of bugs. + +2003-09-11 Klaus Niederkrger + * Button groups can be switch on/off via actions. + This is not yet the final GUI-Layout (yes, it looks broken). + * Accordingly the Stat/Trig-mode has been deleted from + configure window. + +2003-09-11 Klaus Niederkrger + * deleted a few #includes + +2003-09-02 Klaus Niederkrger + * dropped configure-button and Help-button + * created menubar with standard-actions + * ConfigDialog is not modal anymore + * copy/paste/cut-standard actions applied to calc_display + +2003-08-28 Klaus Niederkrger + * created Pi-button and moved Inv-button to make space for it + * label of "."-button is now localized + * Caption is set via signal/slots + * Fixed "%"-mode to make it again more conformant with documentation. + "x^y%" does still not work. Did it ever? + * Number-keys are now handled by KAccel instead of keyPressEvent + * ConfigDialog is modal + +2003-08-27 Klaus Niederkrger + * moved result_history from CalcEngine into DispLogic + * reactivation of rounding towards zero for cos(90) etc. + * quit is done in a more KDE conformant way + * Caption is set via slots etc. + +2003-08-12 Klaus Niederkrger + * continued separation: now display is independent class and + handles everything related to itself. + GUI passes only information between core and display. + +2003-08-04 Klaus Niederkrger + * finished the separation of gui-code from the calculating core. + this still needs some clean-up + +2003-02-11 Evan Teran + * replaced cheasy stack with STL stack classes (it really should have been + two stacks, but was mushed into one with a linked list dividing content) + * made it use new headers (no .h) when _ISOC99_SOURCE is defined + * added replace current gui code with ui files to TODO list + +2002-05-10 Evan Teran + * altered makefile to remove building of it as a library then linking that + to a dummy object file, this was silly and caused inclusion of an uneeded + source file + * bumped version to reflect new options dialog, next version will be 2.0.0 + as it will have many new changes/features + +2002-03-11 Evan Teran + * started work on making calculator code _seperate_ from the + gui code, the goal here is the make the calculating core + replacable with any library (hopfully with better precision) simply by + wrapping it in a class + * made it some many buttons are disabled when unavailabled (A-F) not enabled + unless we are in HEX mode, less confusion for users who arent familiar with + different bases + * removed some code that is never getting called + * why oh why are exceptions disabled in the standard config, I would like to + use them :( + +2001-10-18 Evan Teran + * removed configdlg.* from source tree as it is not part of the compile + * changed options dialog to use smarter layouts, and also fixed spinbox + size problem so they are now usable + * synced changed I made to the KDE 2.2.1 release version to match CVS + version which compiles under KDE 3.0 w/ QT 3.0.0 + * made sure the clear (clear entry) button functioned properly, my minor + change before broke it in some situations + + +2001-10-12 Evan Teran + * Reorganized code for all files, much more consistant now + * completely reworked the cvb (convert to binary) function + it now is sane, the last one did a rediculous amount of + unneeded work + * changed C/C++ headers to use new style as per ANSI/ISO + standard + * removed fontdlg.cpp/h from tree, not even used in compile :P + * made binary mode 32-bit + * reorganized UpdateDisplay code to make more sense + * found possible nasty memleak in EnterEqual + * now use my UNUSED macro to perform (void)var on unused parameters + to avoid compile warnings, much more readable this way + * merged setXXX functions to angle_selected/base_selected + then removed the setXXX functions as they no longer have any purpose + * changed a ton of code to use true C++ bools, makes logic + more clear + * made cvb a static member of QtCalculator instead of an ugly global + function + * changed history to use a simple vectory object instead of the storing + the values in a dynamically allocated QList, it was clearly leaking memory + as it was almost never released, this could have been fixed by enabling the + autodelete feature of QList...but why dynamically allocate when we are + storing numerical values?!? simple array with an int as an iterator :) + * changed error trapping from C style signal trapping, rather use exceptions + much cleaner that way + * removed un-used TopOfStack function + * fixed ability to enter a decimal point when in hex/oct/bin mode, those are + integer value only modes + * fixed problem with entering multiple decimal points in decimal mode + * changed CALCAMNT to be defined by a typedef, I did notice that at least my + C++ math headers are broken...functions like cos should (by newest + standards) use float, double, or long double versions automatically based on + datatype, however mine (Redhat 7.1) seems to only have the old double + versions, and have alternate names for these functions + * fixed the fact that the normal clear button seemingly did nothing + + +1999-08-22 Bernd Johannes Wuebben + + * kcalc_core.cpp (UpdateDisplay): + Re-enabled the use of long double. Most if not all distributions + come now with a working glib math library. + +Mon Nov 16 18:05:01 1998 Mario Weilguni + + * There was an error in the stdev forumal. Fixed. + * the population standard deviation had the same fault. Fixed. + +Mon Nov 16 18:05:01 1998 Mario Weilguni + + * calculation the facturial of a too large number was delayed, + even though infinity was already reached. Now kcalc stops + calculation if infinity is reached and displays an error + +Mon May 4 06:28:09 1998 Bernd Johannes Wuebben + + * Added the comma key as an accelerator for '.' + +Sat Apr 18 16:26:52 1998 Bernd Johannes Wuebben + + * Some inverse functions didn't compute right. Wonder who broke them. + +Sun Feb 8 16:11:34 1998 Bernd Johannes Wuebben + + * removed a compiler warning + +Sat Nov 22 14:30:37 1997 Bernd Johannes Wuebben + + * stats.cpp: fixed some bugs in the stats module + mean should now be correct + std shoudl now be correct too. + +Sat Sep 20 23:59:30 1997 Bernd Johannes Wuebben + + * kcalc.cpp: Added statistical functions + +Mon Sep 15 00:34:58 1997 Bernd Johannes Wuebben + + * added cut and pasted functionality + * implemented EE + * implemented result stack + * implemented precision and fixed precision + * added key bindings + * tooltips + * added configuration dialog + + +Sat Aug 2 22:06:59 1997 Bernd Johannes Wuebben + + * kcalc.h: clean up + + diff --git a/kcalc/Makefile.am b/kcalc/Makefile.am new file mode 100644 index 0000000..551d7d4 --- /dev/null +++ b/kcalc/Makefile.am @@ -0,0 +1,40 @@ +AM_CPPFLAGS= -I$(srcdir)/knumber -D_ISOC99_SOURCE $(all_includes) + +SUBDIRS = knumber + +bin_PROGRAMS = +lib_LTLIBRARIES = +kdeinit_LTLIBRARIES = kcalc.la + +kcalc_la_SOURCES = kcalc.cpp kcalc_button.cpp kcalc_const_button.cpp \ + kcalc_const_menu.cpp kcalc_core.cpp kcalcdisplay.cpp \ + dlabel.cpp stats.cpp colors.ui general.ui \ + constants.ui kcalc_settings.kcfgc + + +METASOURCES = AUTO + +noinst_HEADERS = kcalc.h kcalc_button.h kcalc_const_button.h \ + kcalc_const_menu.h kcalc_core.h kcalcdisplay.h \ + kcalctype.h dlabel.h stats.h + +kcalc_la_LDFLAGS = $(all_libraries) -module -avoid-version +kcalc_la_LIBADD = $(LIB_KDEUI) knumber/libknumber.la + +KDE_ICON = kcalc + +xdg_apps_DATA = kcalc.desktop +kde_kcfg_DATA = kcalc.kcfg + +rcdir = $(kde_datadir)/kcalc +rc_DATA = kcalcui.rc + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcalc.pot + +updatedir = $(kde_datadir)/kconf_update +update_DATA = kcalcrc.upd + +DOXYGEN_EMPTY = YES +include $(top_srcdir)/admin/Doxyfile.am + diff --git a/kcalc/README b/kcalc/README new file mode 100644 index 0000000..eb64d7c --- /dev/null +++ b/kcalc/README @@ -0,0 +1,8 @@ +KCalc +===== +KCalc is currently covered under the GPL version 2. A copy of this +license can be found in a file named COPYING, in the toplevel directory. + +Have fun with kcalc! + + diff --git a/kcalc/TODO b/kcalc/TODO new file mode 100644 index 0000000..533c7d4 --- /dev/null +++ b/kcalc/TODO @@ -0,0 +1,15 @@ +== ToDo == +* find a real fix for cos 90 != 0 bug (only in double version of compile) + +* get rid of dlabel.h & dlabel.cpp +* key groups for color configuration need to be rethought +* better to handle keys with "accel" or with "keyPressEvent"? + +* think about either doing RichText by hand on labels, or only draw visible buttons, to enhance startup time. + +Following examples from the handbook do not work anymore as explained +in the documentation. Need to update the documentation!! +* 22.345 Mod 8 = will give the result 6.345 +* 10.345 Lsh 3 = also gives 80 +* 16 Inv Lsh 2 = gives 4 (16 divided by 2 twice). +* 16.999 Inv Lsh 2 = also gives 4 \ No newline at end of file diff --git a/kcalc/colors.ui b/kcalc/colors.ui new file mode 100644 index 0000000..26f4b28 --- /dev/null +++ b/kcalc/colors.ui @@ -0,0 +1,278 @@ + +Colors + + + Colors + + + + 0 + 0 + 375 + 331 + + + + + unnamed + + + 0 + + + + groupBox3 + + + Display Colors + + + + unnamed + + + + textLabel3 + + + &Foreground: + + + kcfg_ForeColor + + + + + textLabel4 + + + &Background: + + + kcfg_BackColor + + + + + spacer5 + + + Horizontal + + + Expanding + + + + 110 + 20 + + + + + + kcfg_BackColor + + + + + + + 189 + 255 + 180 + + + + + + kcfg_ForeColor + + + + + + + 0 + 0 + 0 + + + + + + + + groupBox4 + + + Button Colors + + + + unnamed + + + + textLabel5 + + + &Functions: + + + kcfg_FunctionButtonsColor + + + + + textLabel7 + + + He&xadecimals: + + + kcfg_HexButtonsColor + + + + + textLabel10 + + + O&perations: + + + kcfg_OperationButtonsColor + + + + + kcfg_FunctionButtonsColor + + + + + + + + kcfg_StatButtonsColor + + + + + + + + kcfg_MemoryButtonsColor + + + + + + + + spacer6 + + + Horizontal + + + Expanding + + + + 41 + 20 + + + + + + kcfg_OperationButtonsColor + + + + + + + + kcfg_HexButtonsColor + + + + + + + + textLabel8 + + + &Numbers: + + + kcfg_NumberButtonsColor + + + + + kcfg_NumberButtonsColor + + + + + + + + textLabel6 + + + St&atistic functions: + + + kcfg_StatButtonsColor + + + + + textLabel9 + + + &Memory: + + + kcfg_MemoryButtonsColor + + + + + + + spacer4 + + + Vertical + + + Expanding + + + + 20 + 0 + + + + + + + kcfg_ForeColor + kcfg_BackColor + kcfg_FunctionButtonsColor + kcfg_StatButtonsColor + kcfg_HexButtonsColor + kcfg_NumberButtonsColor + kcfg_MemoryButtonsColor + kcfg_OperationButtonsColor + + + diff --git a/kcalc/configure.in.bot b/kcalc/configure.in.bot new file mode 100644 index 0000000..cb7005a --- /dev/null +++ b/kcalc/configure.in.bot @@ -0,0 +1,12 @@ +if test "x$kcalc_gmp_found" = "xno"; then + cat << EOF + +KCalc will not be compiled as you are missing the GMP library. +Please install the libgmp packages +or get GMP from http://www.swox.com/gmp/ +then run configure again + +EOF + + +fi diff --git a/kcalc/configure.in.in b/kcalc/configure.in.in new file mode 100644 index 0000000..3501f1e --- /dev/null +++ b/kcalc/configure.in.in @@ -0,0 +1,78 @@ +AC_CHECK_HEADERS(ieeefp.h) + +AC_CHECK_FUNCS(fabsl) + +AC_DEFUN([KDE_C_LONG_DOUBLE], +[ + AC_CACHE_CHECK(for long double, ac_cv_c_long_double, + [ + ac_save_LIBS="$LIBS" + LIBS="-lm $LIBS" + AC_TRY_RUN( + [ +#define _ISOC99_SOURCE 1 +#define _GNU_SOURCE 1 +#include +#include +#include +#include + +int main() { +/* The Stardent Vistra knows sizeof(long double), but does not support it. */ +long double foo = 1.0; +char buffer[10]; +/* On Ultrix 4.3 cc, long double is 4 and double is 8. */ +int result = (sizeof(long double) <= sizeof(double)); +/* the following is needed for a broken printf in glibc2 */ +if (!result) { + foo = foo * 3; + sprintf(buffer,"%0.0Lf",foo); + result = strcmp(buffer, "3"); +/* and now something mean ;-) */ + foo = powl(fabsl(foo), 1); +} +exit(result); } + ], + ac_cv_c_long_double=yes, ac_cv_c_long_double=no, + ac_cv_c_long_double=no + ) + LIBS="$ac_save_LIBS" + ]) + if test $ac_cv_c_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have support for long double in printf]) + fi +]) +KDE_C_LONG_DOUBLE + +have_l_funcs=yes +AC_CHECK_LIB(m, asinl,,have_l_funcs=no) +AC_CHECK_LIB(m, sqrtl,,have_l_funcs=no) + +if test "xyes" = "x$have_l_funcs" ; then + AC_DEFINE(HAVE_L_FUNCS,1,[Define if you have *l math functions (absl, ...)]) +fi + +AC_LANG_C +AC_CHECK_LIB(m, isinf, [ + AC_DEFINE_UNQUOTED(HAVE_FUNC_ISINF, 1, [Define if you have isinf]) +]) +AC_CHECK_LIB(m, round, [ + AC_DEFINE_UNQUOTED(HAVE_FUNC_ROUND, 1, [Define if you have round]) +]) +AC_CHECK_LIB(m, roundl, [ + AC_DEFINE_UNQUOTED(HAVE_FUNC_ROUNDL, 1, [Define if you have round]) +]) + +kcalc_gmp_found=yes +LIBGMP= +KDE_CHECK_HEADER([gmp.h], [ + KDE_CHECK_LIB(gmp, main, [ + LIBGMP="-lgmp" + AC_DEFINE(HAVE_GMP, 1, [Define if you have libgmp]) + ]) + ],[ + DO_NOT_COMPILE="kcalc $DO_NOT_COMPILE" + kcalc_gmp_found=no + ] +) +AC_SUBST(LIBGMP) diff --git a/kcalc/confvalues.h b/kcalc/confvalues.h new file mode 100644 index 0000000..0ec1fae --- /dev/null +++ b/kcalc/confvalues.h @@ -0,0 +1,48 @@ +/* + + KCalc + + Copyright (C) Bernd Johannes Wuebben + wuebben@math.cornell.edu + wuebben@kde.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + + +#ifndef _CONF_VALUES_H_ +#define _CONF_VALUES_H_ + +typedef struct _DefStruct +{ + QColor forecolor; + QColor backcolor; + QColor numberButtonColor; + QColor functionButtonColor; + QColor statButtonColor; + QColor hexButtonColor; + QColor memoryButtonColor; + QColor operationButtonColor; + + int precision; + int fixedprecision; + bool fixed; + bool beep; + bool capres; + QFont font; +} DefStruct; + +#endif // _CONF_VALUES_H_ diff --git a/kcalc/constants.ui b/kcalc/constants.ui new file mode 100644 index 0000000..f7c734e --- /dev/null +++ b/kcalc/constants.ui @@ -0,0 +1,491 @@ + +Constants + + + Constants + + + + 0 + 0 + 534 + 596 + + + + Constants + + + + unnamed + + + + mainGroupBox + + + Configure Constants + + + + unnamed + + + + groupBox0 + + + C1 + + + + unnamed + + + + kcfg_nameConstant0 + + + 6 + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 70 + 21 + + + + + + kcfg_valueConstant0 + + + 40 + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 80 + 21 + + + + + + kPushButton0 + + + Predefined + + + + + + + groupBox1 + + + C2 + + + + unnamed + + + + kcfg_nameConstant1 + + + 6 + + + + + spacer3 + + + Horizontal + + + Expanding + + + + 70 + 21 + + + + + + kcfg_valueConstant1 + + + 40 + + + + + spacer4 + + + Horizontal + + + Expanding + + + + 80 + 21 + + + + + + kPushButton1 + + + Predefined + + + + + + + groupBox2 + + + C3 + + + + unnamed + + + + kcfg_nameConstant2 + + + 6 + + + + + spacer5 + + + Horizontal + + + Expanding + + + + 70 + 21 + + + + + + kcfg_valueConstant2 + + + 40 + + + + + spacer6 + + + Horizontal + + + Expanding + + + + 80 + 21 + + + + + + kPushButton2 + + + Predefined + + + + + + + groupBox3 + + + C4 + + + + unnamed + + + + kcfg_nameConstant3 + + + 6 + + + + + spacer7 + + + Horizontal + + + Expanding + + + + 70 + 21 + + + + + + kcfg_valueConstant3 + + + 40 + + + + + spacer8 + + + Horizontal + + + Expanding + + + + 80 + 21 + + + + + + kPushButton3 + + + Predefined + + + + + + + groupBox4 + + + C5 + + + + unnamed + + + + kcfg_nameConstant4 + + + 6 + + + + + spacer9 + + + Horizontal + + + Expanding + + + + 70 + 21 + + + + + + kcfg_valueConstant4 + + + 40 + + + + + spacer10 + + + Horizontal + + + Expanding + + + + 80 + 21 + + + + + + kPushButton4 + + + Predefined + + + + + + + groupBox5 + + + C6 + + + + unnamed + + + + kcfg_nameConstant5 + + + 6 + + + + + spacer11 + + + Horizontal + + + Expanding + + + + 70 + 21 + + + + + + kcfg_valueConstant5 + + + 40 + + + + + spacer12 + + + Horizontal + + + Expanding + + + + 80 + 21 + + + + + + kPushButton5 + + + Predefined + + + + + + + + + spacer13 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + + + + + kpushbutton.h + kpushbutton.h + kpushbutton.h + kpushbutton.h + kpushbutton.h + kpushbutton.h + + diff --git a/kcalc/dlabel.cpp b/kcalc/dlabel.cpp new file mode 100644 index 0000000..8c6c062 --- /dev/null +++ b/kcalc/dlabel.cpp @@ -0,0 +1,184 @@ +/* + $Id$ + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include + +#include "kcalc_settings.h" +#include "kcalc_core.h" +#include "dlabel.h" +#include "dlabel.moc" + + + +DispLogic::DispLogic(QWidget *parent, const char *name, + KActionCollection *coll) + :KCalcDisplay(parent,name), _history_index(0) +{ + KNumber::setDefaultFloatOutput(true); + KNumber::setDefaultFractionalInput(true); + _back = KStdAction::undo(this, SLOT(history_back()), coll); + _forward = KStdAction::redo(this, SLOT(history_forward()), coll); + + _forward->setEnabled(false); + _back->setEnabled(false); +} + +DispLogic::~DispLogic() +{ +} + +void DispLogic::changeSettings() +{ + QPalette pal = palette(); + + pal.setColor(QColorGroup::Text, KCalcSettings::foreColor()); + pal.setColor(QColorGroup::Foreground, KCalcSettings::foreColor()); + pal.setColor(QColorGroup::Background, KCalcSettings::backColor()); + + setPalette(pal); + setBackgroundColor(KCalcSettings::backColor()); + + setFont(KCalcSettings::font()); + + setPrecision(KCalcSettings::precision()); + + if(KCalcSettings::fixed() == false) + setFixedPrecision(-1); + else + setFixedPrecision(KCalcSettings::fixedPrecision()); + + setBeep(KCalcSettings::beep()); + setGroupDigits(KCalcSettings::groupDigits()); + updateDisplay(); +} + +void DispLogic::update_from_core(CalcEngine const &core, + bool store_result_in_history) +{ + bool tmp_error; + KNumber const & output = core.lastOutput(tmp_error); + if(tmp_error) sendEvent(EventError); + if (setAmount(output) && store_result_in_history && + output != KNumber::Zero) + { + // add this latest value to our history + _history_list.insert(_history_list.begin(), output); + _history_index = 0; + _back->setEnabled(true); + _forward->setEnabled(false); + } +} + +void DispLogic::EnterDigit(int data) +{ + char tmp; + switch(data) + { + case 0: + tmp = '0'; + break; + case 1: + tmp = '1'; + break; + case 2: + tmp = '2'; + break; + case 3: + tmp = '3'; + break; + case 4: + tmp = '4'; + break; + case 5: + tmp = '5'; + break; + case 6: + tmp = '6'; + break; + case 7: + tmp = '7'; + break; + case 8: + tmp = '8'; + break; + case 9: + tmp = '9'; + break; + case 0xA: + tmp = 'A'; + break; + case 0xB: + tmp = 'B'; + break; + case 0xC: + tmp = 'C'; + break; + case 0xD: + tmp = 'D'; + break; + case 0xE: + tmp = 'E'; + break; + case 0xF: + tmp = 'F'; + break; + default: + tmp = '?'; + break; + } + + newCharacter(tmp); +} + +void DispLogic::history_forward() +{ + Q_ASSERT(! _history_list.empty()); + Q_ASSERT(_history_index > 0); + + _history_index --; + + setAmount(_history_list[_history_index]); + + if(_history_index == 0) _forward->setEnabled(false); + + _back->setEnabled(true); +} + +void DispLogic::history_back() +{ + Q_ASSERT(! _history_list.empty()); + Q_ASSERT( _history_index < static_cast(_history_list.size()) ); + + setAmount(_history_list[_history_index]); + + _history_index ++; + + if( _history_index == static_cast(_history_list.size()) ) + _back->setEnabled(false); + _forward->setEnabled(true); +} + diff --git a/kcalc/dlabel.h b/kcalc/dlabel.h new file mode 100644 index 0000000..a9c33c6 --- /dev/null +++ b/kcalc/dlabel.h @@ -0,0 +1,64 @@ +/* + + $Id$ + + KCalc + + Copyright (C) Bernd Johannes Wuebben + wuebben@math.cornell.edu + wuebben@kde.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + + +#ifndef _D_LABEL_H_ +#define _D_LABEL_H_ + +#include +#include "kcalcdisplay.h" + +class CalcEngine; +class KAction; +class KActionCollection; + +class DispLogic : public KCalcDisplay +{ +Q_OBJECT + +public: + DispLogic(QWidget *parent, const char *name, + KActionCollection *coll); + ~DispLogic(); + + void changeSettings(); + void EnterDigit(int data); + void update_from_core(CalcEngine const &core, + bool store_result_in_history = false); + +private slots: + void history_back(void); + void history_forward(void); + +private: + QValueVector _history_list; + int _history_index; + + KAction *_forward; + KAction *_back; +}; + +#endif diff --git a/kcalc/general.ui b/kcalc/general.ui new file mode 100644 index 0000000..7ec8b15 --- /dev/null +++ b/kcalc/general.ui @@ -0,0 +1,199 @@ + +General + + + General + + + + 0 + 0 + 295 + 262 + + + + General + + + + unnamed + + + 0 + + + + groupBox1 + + + Precision + + + + unnamed + + + + kcfg_Fixed + + + Set &decimal precision + + + + + textLabel1 + + + false + + + Decimal &digits: + + + kcfg_FixedPrecision + + + + + kcfg_FixedPrecision + + + false + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 21 + 20 + + + + + + textLabel2 + + + &Maximum number of digits: + + + kcfg_Fixed + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 101 + 20 + + + + + + kcfg_Precision + + + + + + + groupBox2 + + + Misc + + + + unnamed + + + + kcfg_Beep + + + &Beep on error + + + true + + + + + kcfg_CaptionResult + + + Show &result in window title + + + + + kcfg_GroupDigits + + + Group digits + + + + + + + spacer3 + + + Vertical + + + Expanding + + + + 20 + 31 + + + + + + + + kcfg_Fixed + toggled(bool) + kcfg_FixedPrecision + setEnabled(bool) + + + kcfg_Fixed + toggled(bool) + textLabel1 + setEnabled(bool) + + + + kcfg_Precision + kcfg_Fixed + kcfg_FixedPrecision + kcfg_Beep + kcfg_CaptionResult + + + diff --git a/kcalc/hi16-app-kcalc.png b/kcalc/hi16-app-kcalc.png new file mode 100644 index 0000000..deb6fcd Binary files /dev/null and b/kcalc/hi16-app-kcalc.png differ diff --git a/kcalc/hi22-app-kcalc.png b/kcalc/hi22-app-kcalc.png new file mode 100644 index 0000000..8ef1df8 Binary files /dev/null and b/kcalc/hi22-app-kcalc.png differ diff --git a/kcalc/hi32-app-kcalc.png b/kcalc/hi32-app-kcalc.png new file mode 100644 index 0000000..3406316 Binary files /dev/null and b/kcalc/hi32-app-kcalc.png differ diff --git a/kcalc/hi48-app-kcalc.png b/kcalc/hi48-app-kcalc.png new file mode 100644 index 0000000..3da02ad Binary files /dev/null and b/kcalc/hi48-app-kcalc.png differ diff --git a/kcalc/hi64-app-kcalc.png b/kcalc/hi64-app-kcalc.png new file mode 100644 index 0000000..5ebe853 Binary files /dev/null and b/kcalc/hi64-app-kcalc.png differ diff --git a/kcalc/hisc-app-kcalc.svgz b/kcalc/hisc-app-kcalc.svgz new file mode 100644 index 0000000..4690fb4 Binary files /dev/null and b/kcalc/hisc-app-kcalc.svgz differ diff --git a/kcalc/kcalc.cpp b/kcalc/kcalc.cpp new file mode 100644 index 0000000..e7599cf --- /dev/null +++ b/kcalc/kcalc.cpp @@ -0,0 +1,2306 @@ +/* + kCalculator, a simple scientific calculator for KDE + + Copyright (C) 1996-2000 Bernd Johannes Wuebben + wuebben@kde.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include "../config.h" + +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dlabel.h" +#include "kcalc.h" +#include "kcalc_const_menu.h" +#include "version.h" +#include "general.h" +#include "colors.h" +#include "constants.h" +#include +#include "kcalc_settings.h" + + + +static const char description[] = I18N_NOOP("KDE Calculator"); +static const char version[] = KCALCVERSION; + + +KCalculator::KCalculator(QWidget *parent, const char *name) + : KMainWindow(parent, name), inverse(false), + hyp_mode(false), memory_num(0.0), calc_display(NULL), + mInternalSpacing(4), core() +{ + /* central widget to contain all the elements */ + QWidget *central = new QWidget(this); + setCentralWidget(central); + KAcceleratorManager::setNoAccel( central ); + + // Detect color change + connect(kapp,SIGNAL(kdisplayPaletteChanged()), SLOT(set_colors())); + + calc_display = new DispLogic(central, "display", actionCollection()); + + setupMainActions(); + + setupStatusbar(); + + createGUI(); + + // How can I make the toolBar not appear at all? + // This is not a nice solution. + toolBar()->close(); + + // Create Button to select BaseMode + BaseChooseGroup = new QHButtonGroup(i18n("Base"), central); + connect(BaseChooseGroup, SIGNAL(clicked(int)), SLOT(slotBaseSelected(int))); + BaseChooseGroup->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, false); + + + pbBaseChoose[0] = new QRadioButton(i18n("He&x"), BaseChooseGroup, + "Hexadecimal-Switch"); + QToolTip::add(pbBaseChoose[0], i18n("Switch base to hexadecimal.")); + + pbBaseChoose[1] = new QRadioButton(i18n("&Dec"), BaseChooseGroup, + "Decimal-Switch"); + QToolTip::add(pbBaseChoose[1], i18n("Switch base to decimal.")); + + pbBaseChoose[2] = new QRadioButton(i18n("&Oct"), BaseChooseGroup, + "Octal-Switch"); + QToolTip::add(pbBaseChoose[2], i18n("Switch base to octal.")); + + pbBaseChoose[3] = new QRadioButton(i18n("&Bin"), BaseChooseGroup, + "Binary-Switch"); + QToolTip::add(pbBaseChoose[3], i18n("Switch base to binary.")); + + + // Create Button to select AngleMode + pbAngleChoose = new QPushButton(i18n("&Angle"), + central, "ChooseAngleMode-Button"); + QToolTip::add(pbAngleChoose, i18n("Choose the unit for the angle measure")); + pbAngleChoose->setAutoDefault(false); + + KPopupMenu *angle_menu = new KPopupMenu(pbAngleChoose, "AngleMode-Selection-Menu"); + angle_menu->insertItem(i18n("Degrees"), 0); + angle_menu->insertItem(i18n("Radians"), 1); + angle_menu->insertItem(i18n("Gradians"), 2); + + angle_menu->setCheckable(true); + connect(angle_menu, SIGNAL(activated(int)), SLOT(slotAngleSelected(int))); + pbAngleChoose->setPopup(angle_menu); + + + + pbInv = new KCalcButton("Inv", central, "Inverse-Button", + i18n("Inverse mode")); + pbInv->setAccel(Key_I); + connect(pbInv, SIGNAL(toggled(bool)), SLOT(slotInvtoggled(bool))); + connect(this, SIGNAL(switchShowAccels(bool)), + pbInv, SLOT(slotSetAccelDisplayMode(bool))); + pbInv->setToggleButton(true); + + // + // Create Calculator Buttons + // + + // First the widgets that are the parents of the buttons + mSmallPage = new QWidget(central); + mLargePage = new QWidget(central); + mNumericPage = setupNumericKeys(central); + + setupLogicKeys(mSmallPage); + setupStatisticKeys(mSmallPage); + setupScientificKeys(mSmallPage); + setupConstantsKeys(mSmallPage); + + + pbMod = new KCalcButton(mSmallPage, "Modulo-Button"); + pbMod->addMode(ModeNormal, "Mod", i18n("Modulo")); + pbMod->addMode(ModeInverse, "IntDiv", i18n("Integer division")); + pbMod->setAccel(Key_Colon); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + pbMod, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMod, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMod, SIGNAL(clicked(void)), SLOT(slotModclicked(void))); + + pbReci = new KCalcButton(mSmallPage, "Reciprocal-Button"); + pbReci->addMode(ModeNormal, "1/x", i18n("Reciprocal")); + pbReci->setAccel(Key_R); + connect(this, SIGNAL(switchShowAccels(bool)), + pbReci, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbReci, SIGNAL(clicked(void)), SLOT(slotReciclicked(void))); + + pbFactorial = new KCalcButton(mSmallPage, "Factorial-Button"); + pbFactorial->addMode(ModeNormal, "x!", i18n("Factorial")); + pbFactorial->setAccel(Key_Exclam); + connect(this, SIGNAL(switchShowAccels(bool)), + pbFactorial, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbFactorial, SIGNAL(clicked(void)),SLOT(slotFactorialclicked(void))); + + // Representation of x^2 is moved to the function + // changeRepresentation() that paints the letters When + // pressing the INV Button a sqrt symbol will be drawn on that + // button + pbSquare = new KCalcButton(mSmallPage, "Square-Button"); + pbSquare->addMode(ModeNormal, "x2", i18n("Square"), true); + pbSquare->addMode(ModeInverse, "x3", i18n("Third power"), true); + connect(this, SIGNAL(switchShowAccels(bool)), + pbSquare, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + pbSquare, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(pbSquare, SIGNAL(clicked(void)), SLOT(slotSquareclicked(void))); + + pbRoot = new KSquareButton(mSmallPage, "Square-Button"); + pbRoot->addMode(ModeNormal, "sqrt(x)", i18n("Square root")); + pbRoot->addMode(ModeInverse, "sqrt[3](x)", i18n("Cube root")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbRoot, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + pbRoot, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(pbRoot, SIGNAL(clicked(void)), SLOT(slotRootclicked(void))); + + + // Representation of x^y is moved to the function + // changeRepresentation() that paints the letters When + // pressing the INV Button y^x will be drawn on that button + pbPower = new KCalcButton(mSmallPage, "Power-Button"); + pbPower->addMode(ModeNormal, "xy", i18n("x to the power of y"), true); + pbPower->addMode(ModeInverse, "x1/y", i18n("x to the power of 1/y"), true); + connect(this, SIGNAL(switchShowAccels(bool)), + pbPower, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + pbPower, SLOT(slotSetMode(ButtonModeFlags,bool))); + pbPower->setAccel(Key_AsciiCircum); + connect(pbPower, SIGNAL(clicked(void)), SLOT(slotPowerclicked(void))); + + + // + // All these layouts are needed because all the groups have their + // own size per row so we can't use one huge QGridLayout (mosfet) + // + QGridLayout *smallBtnLayout = new QGridLayout(mSmallPage, 6, 4, 0, + mInternalSpacing); + QGridLayout *largeBtnLayout = new QGridLayout(mLargePage, 5, 2, 0, + mInternalSpacing); + + QHBoxLayout *topLayout = new QHBoxLayout(); + QHBoxLayout *btnLayout = new QHBoxLayout(); + + // bring them all together + QVBoxLayout *mainLayout = new QVBoxLayout(central, mInternalSpacing, + mInternalSpacing); + + mainLayout->addLayout(topLayout); + mainLayout->addLayout(btnLayout); + + // button layout + btnLayout->addWidget(mSmallPage, 0, AlignTop); + btnLayout->addSpacing(2*mInternalSpacing); + btnLayout->addWidget(mNumericPage, 0, AlignTop); + btnLayout->addSpacing(2*mInternalSpacing); + btnLayout->addWidget(mLargePage, 0, AlignTop); + + // small button layout + smallBtnLayout->addWidget(pbStat["NumData"], 0, 0); + smallBtnLayout->addWidget(pbScientific["HypMode"], 0, 1); + smallBtnLayout->addWidget(pbLogic["AND"], 0, 2); + smallBtnLayout->addWidget(pbMod, 0, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xA), 0, 4); + smallBtnLayout->addWidget(pbConstant[0], 0, 5); + + smallBtnLayout->addWidget(pbStat["Mean"], 1, 0); + smallBtnLayout->addWidget(pbScientific["Sine"], 1, 1); + smallBtnLayout->addWidget(pbLogic["OR"], 1, 2); + smallBtnLayout->addWidget(pbReci, 1, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xB), 1, 4); + smallBtnLayout->addWidget(pbConstant[1], 1, 5); + + smallBtnLayout->addWidget(pbStat["StandardDeviation"], 2, 0); + smallBtnLayout->addWidget(pbScientific["Cosine"], 2, 1); + smallBtnLayout->addWidget(pbLogic["XOR"], 2, 2); + smallBtnLayout->addWidget(pbFactorial, 2, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xC), 2, 4); + smallBtnLayout->addWidget(pbConstant[2], 2, 5); + + smallBtnLayout->addWidget(pbStat["Median"], 3, 0); + smallBtnLayout->addWidget(pbScientific["Tangent"], 3, 1); + smallBtnLayout->addWidget(pbLogic["LeftShift"], 3, 2); + smallBtnLayout->addWidget(pbSquare, 3, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xD), 3, 4); + smallBtnLayout->addWidget(pbConstant[3], 3, 5); + + smallBtnLayout->addWidget(pbStat["InputData"], 4, 0); + smallBtnLayout->addWidget(pbScientific["Log10"], 4, 1); + smallBtnLayout->addWidget(pbLogic["RightShift"], 4, 2); + smallBtnLayout->addWidget(pbRoot, 4, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xE), 4, 4); + smallBtnLayout->addWidget(pbConstant[4], 4, 5); + + smallBtnLayout->addWidget(pbStat["ClearData"], 5, 0); + smallBtnLayout->addWidget(pbScientific["LogNatural"], 5, 1); + smallBtnLayout->addWidget(pbLogic["One-Complement"], 5, 2); + smallBtnLayout->addWidget(pbPower, 5, 3); + smallBtnLayout->addWidget(NumButtonGroup->find(0xF), 5, 4); + smallBtnLayout->addWidget(pbConstant[5], 5, 5); + + smallBtnLayout->setRowStretch(0, 0); + smallBtnLayout->setRowStretch(1, 0); + smallBtnLayout->setRowStretch(2, 0); + smallBtnLayout->setRowStretch(3, 0); + smallBtnLayout->setRowStretch(4, 0); + smallBtnLayout->setRowStretch(5, 0); + + // large button layout + largeBtnLayout->addWidget(pbClear, 0, 0); + largeBtnLayout->addWidget(pbAC, 0, 1); + + largeBtnLayout->addWidget(pbParenOpen, 1, 0); + largeBtnLayout->addWidget(pbParenClose, 1, 1); + + largeBtnLayout->addWidget(pbMemRecall, 2, 0); + largeBtnLayout->addWidget(pbMemStore, 2, 1); + + largeBtnLayout->addWidget(pbMemPlusMinus, 3, 0); + largeBtnLayout->addWidget(pbMC, 3, 1); + + largeBtnLayout->addWidget(pbPercent, 4, 0); + largeBtnLayout->addWidget(pbPlusMinus, 4, 1); + + // top layout + topLayout->addWidget(pbAngleChoose); + topLayout->addWidget(BaseChooseGroup); + topLayout->addStretch(); + topLayout->addWidget(pbInv); + mainLayout->insertWidget(0, calc_display); + + mFunctionButtonList.append(pbScientific["HypMode"]); + mFunctionButtonList.append(pbInv); + mFunctionButtonList.append(pbRoot); + mFunctionButtonList.append(pbScientific["Sine"]); + mFunctionButtonList.append(pbPlusMinus); + mFunctionButtonList.append(pbScientific["Cosine"]); + mFunctionButtonList.append(pbReci); + mFunctionButtonList.append(pbScientific["Tangent"]); + mFunctionButtonList.append(pbFactorial); + mFunctionButtonList.append(pbScientific["Log10"]); + mFunctionButtonList.append(pbSquare); + mFunctionButtonList.append(pbScientific["LogNatural"]); + mFunctionButtonList.append(pbPower); + + mMemButtonList.append(pbEE); + mMemButtonList.append(pbMemRecall); + mMemButtonList.append(pbMemPlusMinus); + mMemButtonList.append(pbMemStore); + mMemButtonList.append(pbMC); + mMemButtonList.append(pbClear); + mMemButtonList.append(pbAC); + + mOperationButtonList.append(pbX); + mOperationButtonList.append(pbParenOpen); + mOperationButtonList.append(pbParenClose); + mOperationButtonList.append(pbLogic["AND"]); + mOperationButtonList.append(pbDivision); + mOperationButtonList.append(pbLogic["OR"]); + mOperationButtonList.append(pbLogic["XOR"]); + mOperationButtonList.append(pbPlus); + mOperationButtonList.append(pbMinus); + mOperationButtonList.append(pbLogic["LeftShift"]); + mOperationButtonList.append(pbLogic["RightShift"]); + mOperationButtonList.append(pbPeriod); + mOperationButtonList.append(pbEqual); + mOperationButtonList.append(pbPercent); + mOperationButtonList.append(pbLogic["One-Complement"]); + mOperationButtonList.append(pbMod); + + set_colors(); + // Show the result in the app's caption in taskbar (wishlist - bug #52858) + if (KCalcSettings::captionResult() == true) + connect(calc_display, + SIGNAL(changedText(const QString &)), + SLOT(setCaption(const QString &))); + calc_display->changeSettings(); + set_precision(); + + // Switch to decimal + resetBase(); + slotAngleSelected(0); + + updateGeometry(); + + adjustSize(); + setFixedSize(sizeHint()); + + UpdateDisplay(true); + + // Read and set button groups + + actionStatshow->setChecked(KCalcSettings::showStat()); + slotStatshow(KCalcSettings::showStat()); + + actionScientificshow->setChecked(KCalcSettings::showScientific()); + slotScientificshow(KCalcSettings::showScientific()); + + actionLogicshow->setChecked(KCalcSettings::showLogic()); + slotLogicshow(KCalcSettings::showLogic()); + + actionConstantsShow->setChecked(KCalcSettings::showConstants()); + slotConstantsShow(KCalcSettings::showConstants()); +} + +KCalculator::~KCalculator() +{ + KCalcSettings::writeConfig(); + delete calc_display; +} + +void KCalculator::setupMainActions(void) +{ + // file menu + KStdAction::quit(this, SLOT(close()), actionCollection()); + + // edit menu + KStdAction::cut(calc_display, SLOT(slotCut()), actionCollection()); + KStdAction::copy(calc_display, SLOT(slotCopy()), actionCollection()); + KStdAction::paste(calc_display, SLOT(slotPaste()), actionCollection()); + + // settings menu + actionStatshow = new KToggleAction(i18n("&Statistic Buttons"), 0, + actionCollection(), "show_stat"); + actionStatshow->setChecked(true); + connect(actionStatshow, SIGNAL(toggled(bool)), + SLOT(slotStatshow(bool))); + + actionScientificshow = new KToggleAction(i18n("Science/&Engineering Buttons"), + 0, actionCollection(), "show_science"); + actionScientificshow->setChecked(true); + connect(actionScientificshow, SIGNAL(toggled(bool)), + SLOT(slotScientificshow(bool))); + + actionLogicshow = new KToggleAction(i18n("&Logic Buttons"), 0, + actionCollection(), "show_logic"); + actionLogicshow->setChecked(true); + connect(actionLogicshow, SIGNAL(toggled(bool)), + SLOT(slotLogicshow(bool))); + + actionConstantsShow = new KToggleAction(i18n("&Constants Buttons"), 0, + actionCollection(), "show_constants"); + actionConstantsShow->setChecked(true); + connect(actionConstantsShow, SIGNAL(toggled(bool)), + SLOT(slotConstantsShow(bool))); + + + (void) new KAction(i18n("&Show All"), 0, this, SLOT(slotShowAll()), + actionCollection(), "show_all"); + + (void) new KAction(i18n("&Hide All"), 0, this, SLOT(slotHideAll()), + actionCollection(), "hide_all"); + + KStdAction::preferences(this, SLOT(showSettings()), actionCollection()); + + KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), +actionCollection()); + +} + +void KCalculator::setupStatusbar(void) +{ + // Status bar contents + statusBar()->insertFixedItem(" NORM ", 0, true); + statusBar()->setItemAlignment(0, AlignCenter); + + statusBar()->insertFixedItem(" HEX ", 1, true); + statusBar()->setItemAlignment(1, AlignCenter); + + statusBar()->insertFixedItem(" DEG ", 2, true); + statusBar()->setItemAlignment(2, AlignCenter); + + statusBar()->insertFixedItem(" \xa0\xa0 ", 3, true); // Memory indicator + statusBar()->setItemAlignment(3, AlignCenter); +} + +QWidget* KCalculator::setupNumericKeys(QWidget *parent) +{ + Q_CHECK_PTR(mSmallPage); + Q_CHECK_PTR(mLargePage); + + QWidget *thisPage = new QWidget(parent); + + KCalcButton *tmp_pb; + + NumButtonGroup = new QButtonGroup(0, "Num-Button-Group"); + connect(NumButtonGroup, SIGNAL(clicked(int)), + SLOT(slotNumberclicked(int))); + + tmp_pb = new KCalcButton("0", thisPage, "0-Button"); + tmp_pb->setAccel(Key_0); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0); + + tmp_pb = new KCalcButton("1", thisPage, "1-Button"); + tmp_pb->setAccel(Key_1); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 1); + + tmp_pb = new KCalcButton("2", thisPage, "2-Button"); + tmp_pb->setAccel(Key_2); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 2); + + tmp_pb = new KCalcButton("3", thisPage, "3-Button"); + tmp_pb->setAccel(Key_3); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 3); + + tmp_pb = new KCalcButton("4", thisPage, "4-Button"); + tmp_pb->setAccel(Key_4); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 4); + + tmp_pb = new KCalcButton("5", thisPage, "5-Button"); + tmp_pb->setAccel(Key_5); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 5); + + tmp_pb = new KCalcButton("6", thisPage, "6-Button"); + tmp_pb->setAccel(Key_6); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 6); + + tmp_pb = new KCalcButton("7", thisPage, "7-Button"); + tmp_pb->setAccel(Key_7); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 7); + + tmp_pb = new KCalcButton("8", thisPage, "8-Button"); + tmp_pb->setAccel(Key_8); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 8); + + tmp_pb = new KCalcButton("9", thisPage, "9-Button"); + tmp_pb->setAccel(Key_9); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 9); + + pbEE = new KCalcButton(thisPage, "EE-Button"); + pbEE->addMode(ModeNormal, "x" "\xb7" "10y", + i18n("Exponent"), true); + pbEE->setAccel(Key_E); + connect(this, SIGNAL(switchShowAccels(bool)), + pbEE, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbEE, SIGNAL(clicked(void)), SLOT(slotEEclicked(void))); + + pbParenClose = new KCalcButton(")", mLargePage, "ParenClose-Button"); + pbParenClose->setAccel(Key_ParenRight); + connect(this, SIGNAL(switchShowAccels(bool)), + pbParenClose, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbParenClose,SIGNAL(clicked(void)),SLOT(slotParenCloseclicked(void))); + + pbX = new KCalcButton("X", thisPage, "Multiply-Button", i18n("Multiplication")); + pbX->setAccel(Key_multiply); + connect(this, SIGNAL(switchShowAccels(bool)), + pbX, SLOT(slotSetAccelDisplayMode(bool))); + accel()->insert("Pressed '*'", i18n("Pressed Multiplication-Button"), + 0, Key_Asterisk, pbX, SLOT(animateClick())); + connect(pbX, SIGNAL(clicked(void)), SLOT(slotXclicked(void))); + + pbDivision = new KCalcButton("/", thisPage, "Division-Button", i18n("Division")); + pbDivision->setAccel(Key_Slash); + connect(this, SIGNAL(switchShowAccels(bool)), + pbDivision, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbDivision, SIGNAL(clicked(void)), SLOT(slotDivisionclicked(void))); + + pbPlus = new KCalcButton("+", thisPage, "Plus-Button", i18n("Addition")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbPlus, SLOT(slotSetAccelDisplayMode(bool))); + pbPlus->setAccel(Key_Plus); + connect(pbPlus, SIGNAL(clicked(void)), SLOT(slotPlusclicked(void))); + + pbMinus = new KCalcButton("-", thisPage, "Minus-Button", i18n("Subtraction")); + pbMinus->setAccel(Key_Minus); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMinus, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMinus, SIGNAL(clicked(void)), SLOT(slotMinusclicked(void))); + + pbPeriod = new KCalcButton(KGlobal::locale()->decimalSymbol(), thisPage, + "Period-Button", i18n("Decimal point")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbPeriod, SLOT(slotSetAccelDisplayMode(bool))); + accel()->insert("Decimal Point (Period)", i18n("Pressed Decimal Point"), + 0, Key_Period, pbPeriod, SLOT(animateClick())); + accel()->insert("Decimal Point (Comma)", i18n("Pressed Decimal Point"), + 0, Key_Comma, pbPeriod, SLOT(animateClick())); + connect(pbPeriod, SIGNAL(clicked(void)), SLOT(slotPeriodclicked(void))); + + pbEqual = new KCalcButton("=", thisPage, "Equal-Button", i18n("Result")); + pbEqual->setAccel(Key_Enter); + connect(this, SIGNAL(switchShowAccels(bool)), + pbEqual, SLOT(slotSetAccelDisplayMode(bool))); + accel()->insert("Entered Equal", i18n("Pressed Equal-Button"), + 0, Key_Equal, pbEqual, SLOT(animateClick())); + accel()->insert("Entered Return", i18n("Pressed Equal-Button"), + 0, Key_Return, pbEqual, SLOT(animateClick())); + connect(pbEqual, SIGNAL(clicked(void)), SLOT(slotEqualclicked(void))); + + + QGridLayout *thisLayout = new QGridLayout(thisPage, 5, 4, 0, + mInternalSpacing); + + // large button layout + thisLayout->addWidget(pbEE, 0, 0); + thisLayout->addWidget(pbDivision, 0, 1); + thisLayout->addWidget(pbX, 0, 2); + thisLayout->addWidget(pbMinus, 0, 3); + + thisLayout->addWidget(NumButtonGroup->find(7), 1, 0); + thisLayout->addWidget(NumButtonGroup->find(8), 1, 1); + thisLayout->addWidget(NumButtonGroup->find(9), 1, 2); + thisLayout->addMultiCellWidget(pbPlus, 1, 2, 3, 3); + + thisLayout->addWidget(NumButtonGroup->find(4), 2, 0); + thisLayout->addWidget(NumButtonGroup->find(5), 2, 1); + thisLayout->addWidget(NumButtonGroup->find(6), 2, 2); + //thisLayout->addMultiCellWidget(pbPlus, 1, 2, 3, 3); + + thisLayout->addWidget(NumButtonGroup->find(1), 3, 0); + thisLayout->addWidget(NumButtonGroup->find(2), 3, 1); + thisLayout->addWidget(NumButtonGroup->find(3), 3, 2); + thisLayout->addMultiCellWidget(pbEqual, 3, 4, 3, 3); + + thisLayout->addMultiCellWidget(NumButtonGroup->find(0), 4, 4, 0, 1); + thisLayout->addWidget(pbPeriod, 4, 2); + //thisLayout->addMultiCellWidget(pbEqual, 3, 4, 3, 3); + + thisLayout->addColSpacing(0,10); + thisLayout->addColSpacing(1,10); + thisLayout->addColSpacing(2,10); + thisLayout->addColSpacing(3,10); + thisLayout->addColSpacing(4,10); + + + pbMemRecall = new KCalcButton("MR", mLargePage, "MemRecall-Button", i18n("Memory recall")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMemRecall, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMemRecall, SIGNAL(clicked(void)), + SLOT(slotMemRecallclicked(void))); + pbMemRecall->setDisabled(true); // At start, there is nothing in memory + + pbMemPlusMinus = new KCalcButton(mLargePage, "MPlusMinus-Button"); + pbMemPlusMinus->addMode(ModeNormal, "M+", i18n("Add display to memory")); + pbMemPlusMinus->addMode(ModeInverse, "M-", i18n("Subtract from memory")); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + pbMemPlusMinus, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMemPlusMinus, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMemPlusMinus,SIGNAL(clicked(void)), + SLOT(slotMemPlusMinusclicked(void))); + + pbMemStore = new KCalcButton("MS", mLargePage, "MemStore-Button", + i18n("Memory store")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMemStore, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMemStore, SIGNAL(clicked(void)), SLOT(slotMemStoreclicked(void))); + + + pbMC = new KCalcButton("MC", mLargePage, "MemClear-Button", i18n("Clear memory")); + connect(this, SIGNAL(switchShowAccels(bool)), + pbMC, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbMC, SIGNAL(clicked(void)), SLOT(slotMCclicked(void))); + + pbClear = new KCalcButton("C", mLargePage, "Clear-Button", i18n("Clear")); + pbClear->setAccel(Key_Prior); + connect(this, SIGNAL(switchShowAccels(bool)), + pbClear, SLOT(slotSetAccelDisplayMode(bool))); + accel()->insert("Entered 'ESC'", i18n("Pressed ESC-Button"), 0, + Key_Escape, pbClear, SLOT(animateClick())); + connect(pbClear, SIGNAL(clicked(void)), SLOT(slotClearclicked(void))); + + pbAC = new KCalcButton("AC", mLargePage, "AC-Button", i18n("Clear all")); + pbAC->setAccel(Key_Delete); + connect(this, SIGNAL(switchShowAccels(bool)), + pbAC, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbAC, SIGNAL(clicked(void)), SLOT(slotACclicked(void))); + + pbParenOpen = new KCalcButton("(", mLargePage, "ParenOpen-Button"); + pbParenOpen->setAccel(Key_ParenLeft); + connect(this, SIGNAL(switchShowAccels(bool)), + pbParenOpen, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbParenOpen, SIGNAL(clicked(void)),SLOT(slotParenOpenclicked(void))); + + pbPercent = new KCalcButton("%", mLargePage, "Percent-Button", i18n("Percent")); + pbPercent->setAccel(Key_Percent); + connect(this, SIGNAL(switchShowAccels(bool)), + pbPercent, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbPercent, SIGNAL(clicked(void)), SLOT(slotPercentclicked(void))); + + pbPlusMinus = new KCalcButton("\xb1", mLargePage, "Sign-Button", i18n("Change sign")); + pbPlusMinus->setAccel(Key_Backslash); + connect(this, SIGNAL(switchShowAccels(bool)), + pbPlusMinus, SLOT(slotSetAccelDisplayMode(bool))); + connect(pbPlusMinus, SIGNAL(clicked(void)), SLOT(slotPlusMinusclicked(void))); + + + tmp_pb = new KCalcButton("A", mSmallPage, "A-Button"); + tmp_pb->setAccel(Key_A); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xA); + + tmp_pb = new KCalcButton("B", mSmallPage, "B-Button"); + tmp_pb->setAccel(Key_B); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xB); + + tmp_pb = new KCalcButton("C", mSmallPage, "C-Button"); + tmp_pb->setAccel(Key_C); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xC); + + tmp_pb = new KCalcButton("D", mSmallPage, "D-Button"); + tmp_pb->setAccel(Key_D); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xD); + + tmp_pb = new KCalcButton("E", mSmallPage, "E-Button"); + tmp_pb->setAccel(Key_E); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xE); + + tmp_pb = new KCalcButton("F", mSmallPage, "F-Button"); + tmp_pb->setAccel(Key_F); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + NumButtonGroup->insert(tmp_pb, 0xF); + + return thisPage; +} + +void KCalculator::setupLogicKeys(QWidget *parent) +{ + Q_CHECK_PTR(parent); + + KCalcButton *tmp_pb; + + tmp_pb = new KCalcButton("AND", parent, "AND-Button", i18n("Bitwise AND")); + pbLogic.insert("AND", tmp_pb); + tmp_pb->setAccel(Key_Ampersand); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotANDclicked(void))); + + tmp_pb = new KCalcButton("OR", parent, "OR-Button", i18n("Bitwise OR")); + pbLogic.insert("OR", tmp_pb); + tmp_pb->setAccel(Key_Bar); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotORclicked(void))); + + tmp_pb = new KCalcButton("XOR", parent, "XOR-Button", i18n("Bitwise XOR")); + pbLogic.insert("XOR", tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotXORclicked(void))); + + tmp_pb = new KCalcButton("Cmp", parent, "One-Complement-Button", + i18n("One's complement")); + pbLogic.insert("One-Complement", tmp_pb); + tmp_pb->setAccel(Key_AsciiTilde); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotNegateclicked(void))); + + tmp_pb = new KCalcButton("Lsh", parent, "LeftBitShift-Button", + i18n("Left bit shift")); + tmp_pb->setAccel(Key_Less); + pbLogic.insert("LeftShift", tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), + SLOT(slotLeftShiftclicked(void))); + + tmp_pb = new KCalcButton("Rsh", parent, "RightBitShift-Button", + i18n("Right bit shift")); + tmp_pb->setAccel(Key_Greater); + pbLogic.insert("RightShift", tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), + SLOT(slotRightShiftclicked(void))); +} + +void KCalculator::setupScientificKeys(QWidget *parent) +{ + Q_CHECK_PTR(parent); + + KCalcButton *tmp_pb; + + tmp_pb = new KCalcButton("Hyp", parent, "Hyp-Button", i18n("Hyperbolic mode")); + pbScientific.insert("HypMode", tmp_pb); + tmp_pb->setAccel(Key_H); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(toggled(bool)), SLOT(slotHyptoggled(bool))); + tmp_pb->setToggleButton(true); + + tmp_pb = new KCalcButton(parent, "Sin-Button"); + pbScientific.insert("Sine", tmp_pb); + tmp_pb->addMode(ModeNormal, "Sin", i18n("Sine")); + tmp_pb->addMode(ModeInverse, "Asin", i18n("Arc sine")); + tmp_pb->addMode(ModeHyperbolic, "Sinh", i18n("Hyperbolic sine")); + tmp_pb->addMode(ButtonModeFlags(ModeInverse | ModeHyperbolic), + "Asinh", i18n("Inverse hyperbolic sine")); + tmp_pb->setAccel(Key_S); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotSinclicked(void))); + + tmp_pb = new KCalcButton(parent, "Cos-Button"); + pbScientific.insert("Cosine", tmp_pb); + tmp_pb->addMode(ModeNormal, "Cos", i18n("Cosine")); + tmp_pb->addMode(ModeInverse, "Acos", i18n("Arc cosine")); + tmp_pb->addMode(ModeHyperbolic, "Cosh", i18n("Hyperbolic cosine")); + tmp_pb->addMode(ButtonModeFlags(ModeInverse | ModeHyperbolic), + "Acosh", i18n("Inverse hyperbolic cosine")); + tmp_pb->setAccel(Key_C); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotCosclicked(void))); + + tmp_pb = new KCalcButton(parent, "Tan-Button"); + pbScientific.insert("Tangent", tmp_pb); + tmp_pb->addMode(ModeNormal, "Tan", i18n("Tangent")); + tmp_pb->addMode(ModeInverse, "Atan", i18n("Arc tangent")); + tmp_pb->addMode(ModeHyperbolic, "Tanh", i18n("Hyperbolic tangent")); + tmp_pb->addMode(ButtonModeFlags(ModeInverse | ModeHyperbolic), + "Atanh", i18n("Inverse hyperbolic tangent")); + tmp_pb->setAccel(Key_T); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)),SLOT(slotTanclicked(void))); + + tmp_pb = new KCalcButton(parent, "Ln-Button"); + tmp_pb->addMode(ModeNormal, "Ln", i18n("Natural log")); + tmp_pb->addMode(ModeInverse, "e x ", i18n("Exponential function"), + true); + pbScientific.insert("LogNatural", tmp_pb); + tmp_pb->setAccel(Key_N); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotLnclicked(void))); + + tmp_pb = new KCalcButton(parent, "Log-Button"); + tmp_pb->addMode(ModeNormal, "Log", i18n("Logarithm to base 10")); + tmp_pb->addMode(ModeInverse, "10 x ", i18n("10 to the power of x"), + true); + pbScientific.insert("Log10", tmp_pb); + tmp_pb->setAccel(Key_L); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotLogclicked(void))); + +} + +void KCalculator::setupStatisticKeys(QWidget *parent) +{ + Q_CHECK_PTR(parent); + + KCalcButton *tmp_pb; + + tmp_pb = new KCalcButton(parent, "Stat.NumData-Button"); + tmp_pb->addMode(ModeNormal, "N", i18n("Number of data entered")); + tmp_pb->addMode(ModeInverse, QString::fromUtf8("\xce\xa3") + + "x", i18n("Sum of all data items")); + pbStat.insert("NumData", tmp_pb); + mStatButtonList.append(tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatNumclicked(void))); + + tmp_pb = new KCalcButton(parent, "Stat.Median-Button"); + tmp_pb->addMode(ModeNormal, "Med", i18n("Median")); + pbStat.insert("Median", tmp_pb); + mStatButtonList.append(tmp_pb); + QToolTip::add(tmp_pb, i18n("Median")); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatMedianclicked(void))); + + tmp_pb = new KCalcButton(parent, "Stat.Mean-Button"); + tmp_pb->addMode(ModeNormal, "Mea", i18n("Mean")); + tmp_pb->addMode(ModeInverse, QString::fromUtf8("\xce\xa3") + + "x2", + i18n("Sum of all data items squared"), true); + pbStat.insert("Mean", tmp_pb); + mStatButtonList.append(tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatMeanclicked(void))); + + tmp_pb = new KCalcButton(parent, "Stat.StandardDeviation-Button"); + tmp_pb->addMode(ModeNormal, QString::fromUtf8("σ",-1) + "N-1", + i18n("Sample standard deviation"), true); + tmp_pb->addMode(ModeInverse, QString::fromUtf8("σ",-1) + "N", + i18n("Standard deviation"), true); + pbStat.insert("StandardDeviation", tmp_pb); + mStatButtonList.append(tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatStdDevclicked(void))); + + tmp_pb = new KCalcButton(parent, "Stat.DataInput-Button"); + tmp_pb->addMode(ModeNormal, "Dat", i18n("Enter data")); + tmp_pb->addMode(ModeInverse, "CDat", i18n("Delete last data item")); + pbStat.insert("InputData", tmp_pb); + mStatButtonList.append(tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatDataInputclicked(void))); + + tmp_pb = new KCalcButton(parent, "Stat.ClearData-Button"); + tmp_pb->addMode(ModeNormal, "CSt", i18n("Clear data store")); + pbStat.insert("ClearData", tmp_pb); + mStatButtonList.append(tmp_pb); + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(tmp_pb, SIGNAL(clicked(void)), SLOT(slotStatClearDataclicked(void))); +} + +void KCalculator::setupConstantsKeys(QWidget *parent) +{ + Q_CHECK_PTR(parent); + + ConstButtonGroup = new QButtonGroup(0, "Const-Button-Group"); + connect(ConstButtonGroup, SIGNAL(clicked(int)), SLOT(slotConstclicked(int))); + + + KCalcConstButton *tmp_pb; + tmp_pb = new KCalcConstButton(parent, 0, "C1"); + tmp_pb->setAccel(ALT + Key_1); + pbConstant[0] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 0); + + tmp_pb = new KCalcConstButton(parent, 1, "C2"); + tmp_pb->setAccel(ALT + Key_2); + pbConstant[1] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 1); + + tmp_pb = new KCalcConstButton(parent, 2, "C3"); + tmp_pb->setAccel(ALT + Key_3); + pbConstant[2] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 2); + + tmp_pb = new KCalcConstButton(parent, 3, "C4"); + tmp_pb->setAccel(ALT + Key_4); + pbConstant[3] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 3); + + tmp_pb = new KCalcConstButton(parent, 4, "C5"); + tmp_pb->setAccel(ALT + Key_5); + pbConstant[4] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 4); + + tmp_pb = new KCalcConstButton(parent, 5, "C6"); + tmp_pb->setAccel(ALT + Key_6); + pbConstant[5] = tmp_pb; + connect(this, SIGNAL(switchShowAccels(bool)), + tmp_pb, SLOT(slotSetAccelDisplayMode(bool))); + connect(this, SIGNAL(switchMode(ButtonModeFlags,bool)), + tmp_pb, SLOT(slotSetMode(ButtonModeFlags,bool))); + ConstButtonGroup->insert(tmp_pb, 5); + + changeButtonNames(); + + // add menu with scientific constants + KCalcConstMenu *tmp_menu = new KCalcConstMenu(this); + menuBar()->insertItem(i18n("&Constants"), tmp_menu, -1, 2); + connect(tmp_menu, SIGNAL(activated(int)), this, + SLOT(slotConstantToDisplay(int))); +} + +void KCalculator::slotConstantToDisplay(int constant) +{ + calc_display->setAmount(KCalcConstMenu::Constants[constant].value); + + UpdateDisplay(false); +} + +void KCalculator::updateGeometry(void) +{ + QObjectList *l; + QSize s; + int margin; + + // + // Calculator buttons + // + s.setWidth(mSmallPage->fontMetrics().width("MMMM")); + s.setHeight(mSmallPage->fontMetrics().lineSpacing()); + + // why this stupid cast! + l = const_cast(mSmallPage->children()); + + for(uint i=0; i < l->count(); i++) + { + QObject *o = l->at(i); + if( o->isWidgetType() ) + { + QWidget *tmp_widget = dynamic_cast(o); + margin = QApplication::style(). + pixelMetric(QStyle::PM_ButtonMargin, (tmp_widget))*2; + tmp_widget->setFixedSize(s.width()+margin, s.height()+margin); + //tmp_widget->setMinimumSize(s.width()+margin, s.height()+margin); + tmp_widget->installEventFilter( this ); + tmp_widget->setAcceptDrops(true); + } + } + + // why this stupic cast !! + l = const_cast(mLargePage->children()); + + int h1 = (NumButtonGroup->find(0x0F))->minimumSize().height(); + int h2 = static_cast( (static_cast(h1) + 4.0) / 5.0 ); + s.setWidth(mLargePage->fontMetrics().width("MMM") + + QApplication::style(). + pixelMetric(QStyle::PM_ButtonMargin, NumButtonGroup->find(0x0F))*2); + s.setHeight(h1 + h2); + + for(uint i = 0; i < l->count(); i++) + { + QObject *o = l->at(i); + if(o->isWidgetType()) + { + QWidget *tmp_widget = dynamic_cast(o); + tmp_widget->setFixedSize(s); + tmp_widget->installEventFilter(this); + tmp_widget->setAcceptDrops(true); + } + } + + pbInv->setFixedSize(s); + pbInv->installEventFilter(this); + pbInv->setAcceptDrops(true); + + + + l = (QObjectList*)mNumericPage->children(); // silence please + + h1 = (NumButtonGroup->find(0x0F))->minimumSize().height(); + h2 = (int)((((float)h1 + 4.0) / 5.0)); + s.setWidth(mLargePage->fontMetrics().width("MMM") + + QApplication::style(). + pixelMetric(QStyle::PM_ButtonMargin, NumButtonGroup->find(0x0F))*2); + s.setHeight(h1 + h2); + + for(uint i = 0; i < l->count(); i++) + { + QObject *o = l->at(i); + if(o->isWidgetType()) + { + QWidget *tmp_widget = dynamic_cast(o); + tmp_widget->setFixedSize(s); + tmp_widget->installEventFilter(this); + tmp_widget->setAcceptDrops(true); + } + } + + // Set Buttons of double size + QSize t(s); + t.setWidth(2*s.width()); + NumButtonGroup->find(0x00)->setFixedSize(t); + t = s; + t.setHeight(2*s.height()); + pbEqual->setFixedSize(t); + pbPlus->setFixedSize(t); +} + +void KCalculator::slotBaseSelected(int base) +{ + int current_base; + + // set display & statusbar (if item exist in statusbar) + switch(base) + { + case 3: + current_base = calc_display->setBase(NumBase(2)); + if (statusBar()->hasItem(1)) statusBar()->changeItem("BIN",1); + calc_display->setStatusText(1, "Bin"); + break; + case 2: + current_base = calc_display->setBase(NumBase(8)); + if (statusBar()->hasItem(1)) statusBar()->changeItem("OCT",1); + calc_display->setStatusText(1, "Oct"); + break; + case 1: + current_base = calc_display->setBase(NumBase(10)); + if (statusBar()->hasItem(1)) statusBar()->changeItem("DEC",1); + calc_display->setStatusText(1, "Dec"); + break; + case 0: + current_base = calc_display->setBase(NumBase(16)); + if (statusBar()->hasItem(1)) statusBar()->changeItem("HEX",1); + calc_display->setStatusText(1, "Hex"); + break; + default: + if (statusBar()->hasItem(1)) statusBar()->changeItem("Error",1); + calc_display->setStatusText(1, "Error"); + return; + } + + // Enable the buttons not available in this base + for (int i=0; ifind(i)->setEnabled (true); + + // Disable the buttons not available in this base + for (int i=current_base; i<16; i++) + NumButtonGroup->find(i)->setEnabled (false); + + // Only enable the decimal point in decimal + pbPeriod->setEnabled(current_base == NB_DECIMAL); + // Only enable the x*10^y button in decimal + pbEE->setEnabled(current_base == NB_DECIMAL); + + // Disable buttons that make only sense with floating point + // numbers + if(current_base != NB_DECIMAL) + { + pbScientific["HypMode"]->setEnabled(false); + pbScientific["Sine"]->setEnabled(false); + pbScientific["Cosine"]->setEnabled(false); + pbScientific["Tangent"]->setEnabled(false); + pbScientific["LogNatural"]->setEnabled(false); + pbScientific["Log10"]->setEnabled(false); + } + else + { + pbScientific["HypMode"]->setEnabled(true); + pbScientific["Sine"]->setEnabled(true); + pbScientific["Cosine"]->setEnabled(true); + pbScientific["Tangent"]->setEnabled(true); + pbScientific["LogNatural"]->setEnabled(true); + pbScientific["Log10"]->setEnabled(true); + } +} + +void KCalculator::keyPressEvent(QKeyEvent *e) +{ + if ( ( e->state() & KeyButtonMask ) == 0 || ( e->state() & ShiftButton ) ) { + switch (e->key()) + { + case Key_Next: + pbAC->animateClick(); + break; + case Key_Slash: + case Key_division: + pbDivision->animateClick(); + break; + case Key_D: + pbStat["InputData"]->animateClick(); // stat mode + break; + case Key_BracketLeft: + case Key_twosuperior: + pbSquare->animateClick(); + break; + case Key_Backspace: + calc_display->deleteLastDigit(); + // pbAC->animateClick(); + break; + } + } + + if (e->key() == Key_Control) + emit switchShowAccels(true); +} + +void KCalculator::keyReleaseEvent(QKeyEvent *e) +{ + if (e->key() == Key_Control) + emit switchShowAccels(false); +} + +void KCalculator::slotAngleSelected(int number) +{ + pbAngleChoose->popup()->setItemChecked(0, false); + pbAngleChoose->popup()->setItemChecked(1, false); + pbAngleChoose->popup()->setItemChecked(2, false); + + switch(number) + { + case 0: + _angle_mode = DegMode; + statusBar()->changeItem("DEG", 2); + pbAngleChoose->popup()->setItemChecked(0, true); + calc_display->setStatusText(2, "Deg"); + break; + case 1: + _angle_mode = RadMode; + statusBar()->changeItem("RAD", 2); + pbAngleChoose->popup()->setItemChecked(1, true); + calc_display->setStatusText(2, "Rad"); + break; + case 2: + _angle_mode = GradMode; + statusBar()->changeItem("GRA", 2); + pbAngleChoose->popup()->setItemChecked(2, true); + calc_display->setStatusText(2, "Gra"); + break; + default: // we shouldn't ever end up here + _angle_mode = RadMode; + } +} + +void KCalculator::slotEEclicked(void) +{ + calc_display->newCharacter('e'); +} + +void KCalculator::slotInvtoggled(bool flag) +{ + inverse = flag; + + emit switchMode(ModeInverse, flag); + + if (inverse) + { + statusBar()->changeItem("INV", 0); + calc_display->setStatusText(0, "Inv"); + } + else + { + statusBar()->changeItem("NORM", 0); + calc_display->setStatusText(0, QString::null); + } +} + +void KCalculator::slotHyptoggled(bool flag) +{ + // toggle between hyperbolic and standart trig functions + hyp_mode = flag; + + emit switchMode(ModeHyperbolic, flag); +} + + + +void KCalculator::slotMemRecallclicked(void) +{ + // temp. work-around + calc_display->sendEvent(KCalcDisplay::EventReset); + + calc_display->setAmount(memory_num); + UpdateDisplay(false); +} + +void KCalculator::slotMemStoreclicked(void) +{ + EnterEqual(); + + memory_num = calc_display->getAmount(); + calc_display->setStatusText(3, "M"); + statusBar()->changeItem("M",3); + pbMemRecall->setEnabled(true); +} + +void KCalculator::slotNumberclicked(int number_clicked) +{ + calc_display->EnterDigit(number_clicked); +} + +void KCalculator::slotSinclicked(void) +{ + if (hyp_mode) + { + // sinh or arsinh + if (!inverse) + core.SinHyp(calc_display->getAmount()); + else + core.AreaSinHyp(calc_display->getAmount()); + } + else + { + // sine or arcsine + if (!inverse) + switch(_angle_mode) + { + case DegMode: + core.SinDeg(calc_display->getAmount()); + break; + case RadMode: + core.SinRad(calc_display->getAmount()); + break; + case GradMode: + core.SinGrad(calc_display->getAmount()); + break; + } + else + switch(_angle_mode) + { + case DegMode: + core.ArcSinDeg(calc_display->getAmount()); + break; + case RadMode: + core.ArcSinRad(calc_display->getAmount()); + break; + case GradMode: + core.ArcSinGrad(calc_display->getAmount()); + break; + } + } + + UpdateDisplay(true); +} + +void KCalculator::slotPlusMinusclicked(void) +{ + // display can only change sign, when in input mode, otherwise we + // need the core to do this. + if (!calc_display->sendEvent(KCalcDisplay::EventChangeSign)) + { + core.InvertSign(calc_display->getAmount()); + UpdateDisplay(true); + } +} + +void KCalculator::slotMemPlusMinusclicked(void) +{ + bool tmp_inverse = inverse; // store this, because next command deletes inverse + EnterEqual(); // finish calculation so far, to store result into MEM + + if (!tmp_inverse) memory_num += calc_display->getAmount(); + else memory_num -= calc_display->getAmount(); + + pbInv->setOn(false); + statusBar()->changeItem("M",3); + calc_display->setStatusText(3, "M"); + pbMemRecall->setEnabled(true); +} + +void KCalculator::slotCosclicked(void) +{ + if (hyp_mode) + { + // cosh or arcosh + if (!inverse) + core.CosHyp(calc_display->getAmount()); + else + core.AreaCosHyp(calc_display->getAmount()); + } + else + { + // cosine or arccosine + if (!inverse) + switch(_angle_mode) + { + case DegMode: + core.CosDeg(calc_display->getAmount()); + break; + case RadMode: + core.CosRad(calc_display->getAmount()); + break; + case GradMode: + core.CosGrad(calc_display->getAmount()); + break; + } + else + switch(_angle_mode) + { + case DegMode: + core.ArcCosDeg(calc_display->getAmount()); + break; + case RadMode: + core.ArcCosRad(calc_display->getAmount()); + break; + case GradMode: + core.ArcCosGrad(calc_display->getAmount()); + break; + } + } + + UpdateDisplay(true); +} + +void KCalculator::slotReciclicked(void) +{ + core.Reciprocal(calc_display->getAmount()); + UpdateDisplay(true); +} + +void KCalculator::slotTanclicked(void) +{ + if (hyp_mode) + { + // tanh or artanh + if (!inverse) + core.TangensHyp(calc_display->getAmount()); + else + core.AreaTangensHyp(calc_display->getAmount()); + } + else + { + // tan or arctan + if (!inverse) + switch(_angle_mode) + { + case DegMode: + core.TangensDeg(calc_display->getAmount()); + break; + case RadMode: + core.TangensRad(calc_display->getAmount()); + break; + case GradMode: + core.TangensGrad(calc_display->getAmount()); + break; + } + else + switch(_angle_mode) + { + case DegMode: + core.ArcTangensDeg(calc_display->getAmount()); + break; + case RadMode: + core.ArcTangensRad(calc_display->getAmount()); + break; + case GradMode: + core.ArcTangensGrad(calc_display->getAmount()); + break; + } + } + + UpdateDisplay(true); +} + +void KCalculator::slotFactorialclicked(void) +{ + core.Factorial(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotLogclicked(void) +{ + if (!inverse) + core.Log10(calc_display->getAmount()); + else + core.Exp10(calc_display->getAmount()); + + UpdateDisplay(true); +} + + +void KCalculator::slotSquareclicked(void) +{ + if (!inverse) + core.Square(calc_display->getAmount()); + else + core.Cube(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotRootclicked(void) +{ + if (!inverse) + core.SquareRoot(calc_display->getAmount()); + else + core.CubeRoot(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotLnclicked(void) +{ + if (!inverse) + core.Ln(calc_display->getAmount()); + else + core.Exp(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotPowerclicked(void) +{ + if (inverse) + { + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_PWR_ROOT); + pbInv->setOn(false); + } + else + { + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_POWER); + } + // temp. work-around + KNumber tmp_num = calc_display->getAmount(); + calc_display->sendEvent(KCalcDisplay::EventReset); + calc_display->setAmount(tmp_num); + UpdateDisplay(false); +} + +void KCalculator::slotMCclicked(void) +{ + memory_num = 0; + statusBar()->changeItem(" \xa0\xa0 ",3); + calc_display->setStatusText(3, QString::null); + pbMemRecall->setDisabled(true); +} + +void KCalculator::slotClearclicked(void) +{ + calc_display->sendEvent(KCalcDisplay::EventClear); +} + +void KCalculator::slotACclicked(void) +{ + core.Reset(); + calc_display->sendEvent(KCalcDisplay::EventReset); + + UpdateDisplay(true); +} + +void KCalculator::slotParenOpenclicked(void) +{ + core.ParenOpen(calc_display->getAmount()); + + // What behavior, if e.g.: "12(6*6)"?? + //UpdateDisplay(true); +} + +void KCalculator::slotParenCloseclicked(void) +{ + core.ParenClose(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotANDclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_AND); + + UpdateDisplay(true); +} + +void KCalculator::slotXclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_MULTIPLY); + + UpdateDisplay(true); +} + +void KCalculator::slotDivisionclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_DIVIDE); + + UpdateDisplay(true); +} + +void KCalculator::slotORclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_OR); + + UpdateDisplay(true); +} + +void KCalculator::slotXORclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_XOR); + + UpdateDisplay(true); +} + +void KCalculator::slotPlusclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_ADD); + + UpdateDisplay(true); +} + +void KCalculator::slotMinusclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_SUBTRACT); + + UpdateDisplay(true); +} + +void KCalculator::slotLeftShiftclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_LSH); + + UpdateDisplay(true); +} + +void KCalculator::slotRightShiftclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_RSH); + + UpdateDisplay(true); +} + +void KCalculator::slotPeriodclicked(void) +{ + calc_display->newCharacter('.'); +} + +void KCalculator::EnterEqual() +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_EQUAL); + + UpdateDisplay(true, true); +} + +void KCalculator::slotEqualclicked(void) +{ + EnterEqual(); +} + +void KCalculator::slotPercentclicked(void) +{ + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_PERCENT); + + UpdateDisplay(true); +} + +void KCalculator::slotNegateclicked(void) +{ + core.Complement(calc_display->getAmount()); + + UpdateDisplay(true); +} + +void KCalculator::slotModclicked(void) +{ + if (inverse) + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_INTDIV); + else + core.enterOperation(calc_display->getAmount(), + CalcEngine::FUNC_MOD); + + UpdateDisplay(true); +} + +void KCalculator::slotStatNumclicked(void) +{ + if(!inverse) + { + core.StatCount(0); + } + else + { + pbInv->setOn(false); + core.StatSum(0); + } + + UpdateDisplay(true); +} + +void KCalculator::slotStatMeanclicked(void) +{ + if(!inverse) + core.StatMean(0); + else + { + pbInv->setOn(false); + core.StatSumSquares(0); + } + + UpdateDisplay(true); +} + +void KCalculator::slotStatStdDevclicked(void) +{ + if(inverse) + { + // std (n-1) + core.StatStdDeviation(0); + pbInv->setOn(false); + } + else + { + // std (n) + core.StatStdSample(0); + } + + UpdateDisplay(true); +} + +void KCalculator::slotStatMedianclicked(void) +{ + if(!inverse) + { + // std (n-1) + core.StatMedian(0); + } + else + { + // std (n) + core.StatMedian(0); + pbInv->setOn(false); + } + // it seems two different modes should be implemented, but...? + UpdateDisplay(true); +} + +void KCalculator::slotStatDataInputclicked(void) +{ + if(!inverse) + { + core.StatDataNew(calc_display->getAmount()); + } + else + { + pbInv->setOn(false); + core.StatDataDel(0); + statusBar()->message(i18n("Last stat item erased"), 3000); + } + + UpdateDisplay(true); +} + +void KCalculator::slotStatClearDataclicked(void) +{ + if(!inverse) + { + core.StatClearAll(0); + statusBar()->message(i18n("Stat mem cleared"), 3000); + } + else + { + pbInv->setOn(false); + UpdateDisplay(false); + } +} + +void KCalculator::slotConstclicked(int button) +{ + if(!inverse) + { + //set the display to the configured value of Constant Button + calc_display->setAmount(pbConstant[button]->constant()); + } + else + { + pbInv->setOn(false); + KCalcSettings::setValueConstant(button, calc_display->text()); + // below set new tooltip + pbConstant[button]->setLabelAndTooltip(); + // work around: after storing a number, pressing a digit should start + // a new number + calc_display->setAmount(calc_display->getAmount()); + } + + UpdateDisplay(false); +} + +void KCalculator::showSettings() +{ + // Check if there is already a dialog and if so bring + // it to the foreground. + if(KConfigDialog::showDialog("settings")) + return; + + // Create a new dialog with the same name as the above checking code. + KConfigDialog *dialog = new KConfigDialog(this, "settings", KCalcSettings::self()); + dialog->enableButtonSeparator( true ); + + // Add the general page. Store the settings in the General group and + // use the icon package_settings. + General *general = new General(0, "General"); + int maxprec = 1000; + general->kcfg_Precision->setMaxValue(maxprec); + dialog->addPage(general, i18n("General"), "package_settings", i18n("General Settings")); + + QWidget *fontWidget = new QWidget(0,"Font"); + QVBoxLayout *fontLayout = new QVBoxLayout(fontWidget); + KFontChooser *mFontChooser = + new KFontChooser(fontWidget, "kcfg_Font", false, QStringList(), false, 6); + + fontLayout->addWidget(mFontChooser); + dialog->addPage(fontWidget, i18n("Font"), "fonts", i18n("Select Display Font")); + + // color settings + + Colors *color = new Colors(0, "Color"); + + dialog->addPage(color, i18n("Colors"), "colors", i18n("Button & Display Colors")); + + // constant settings + + Constants *constant = new Constants(0, "Constant" ); + tmp_const = constant; + + KCalcConstMenu *tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst0(int))); + (constant->kPushButton0)->setPopup(tmp_menu); + + tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst1(int))); + (constant->kPushButton1)->setPopup(tmp_menu); + + tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst2(int))); + (constant->kPushButton2)->setPopup(tmp_menu); + + tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst3(int))); + (constant->kPushButton3)->setPopup(tmp_menu); + + tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst4(int))); + (constant->kPushButton4)->setPopup(tmp_menu); + + tmp_menu = new KCalcConstMenu(this); + connect(tmp_menu, SIGNAL(activated(int)), + SLOT(slotChooseScientificConst5(int))); + (constant->kPushButton5)->setPopup(tmp_menu); + + dialog->addPage(constant, i18n("Constants"), "constants"); + + + // When the user clicks OK or Apply we want to update our settings. + connect(dialog, SIGNAL(settingsChanged()), SLOT(updateSettings())); + + // Display the dialog. + dialog->show(); +} + + +// these 6 slots are just a quick hack, instead of setting the +// TextEdit fields in the configuration dialog, we are setting the +// Settingvalues themselves!! +void KCalculator::slotChooseScientificConst0(int option) +{ + (tmp_const->kcfg_valueConstant0)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant0)->setText(KCalcConstMenu::Constants[option].label); +} + +void KCalculator::slotChooseScientificConst1(int option) +{ + (tmp_const->kcfg_valueConstant1)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant1)->setText(KCalcConstMenu::Constants[option].label); +} + +void KCalculator::slotChooseScientificConst2(int option) +{ + (tmp_const->kcfg_valueConstant2)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant2)->setText(KCalcConstMenu::Constants[option].label); +} + +void KCalculator::slotChooseScientificConst3(int option) +{ + (tmp_const->kcfg_valueConstant3)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant3)->setText(KCalcConstMenu::Constants[option].label); +} + +void KCalculator::slotChooseScientificConst4(int option) +{ + (tmp_const->kcfg_valueConstant4)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant4)->setText(KCalcConstMenu::Constants[option].label); +} + +void KCalculator::slotChooseScientificConst5(int option) +{ + (tmp_const->kcfg_valueConstant5)->setText(KCalcConstMenu::Constants[option].value); + + (tmp_const->kcfg_nameConstant5)->setText(KCalcConstMenu::Constants[option].label); +} + + +void KCalculator::slotStatshow(bool toggled) +{ + if(toggled) + { + pbStat["NumData"]->show(); + pbStat["Mean"]->show(); + pbStat["StandardDeviation"]->show(); + pbStat["Median"]->show(); + pbStat["InputData"]->show(); + pbStat["ClearData"]->show(); + } + else + { + pbStat["NumData"]->hide(); + pbStat["Mean"]->hide(); + pbStat["StandardDeviation"]->hide(); + pbStat["Median"]->hide(); + pbStat["InputData"]->hide(); + pbStat["ClearData"]->hide(); + } + adjustSize(); + setFixedSize(sizeHint()); + KCalcSettings::setShowStat(toggled); +} + +void KCalculator::slotScientificshow(bool toggled) +{ + if(toggled) + { + pbScientific["HypMode"]->show(); + pbScientific["Sine"]->show(); + pbScientific["Cosine"]->show(); + pbScientific["Tangent"]->show(); + pbScientific["Log10"]->show(); + pbScientific["LogNatural"]->show(); + pbAngleChoose->show(); + if(!statusBar()->hasItem(2)) + statusBar()->insertFixedItem(" DEG ", 2, true); + statusBar()->setItemAlignment(2, AlignCenter); + calc_display->setStatusText(2, "Deg"); + slotAngleSelected(0); + } + else + { + pbScientific["HypMode"]->hide(); + pbScientific["Sine"]->hide(); + pbScientific["Cosine"]->hide(); + pbScientific["Tangent"]->hide(); + pbScientific["Log10"]->hide(); + pbScientific["LogNatural"]->hide(); + pbAngleChoose->hide(); + if(statusBar()->hasItem(2)) + statusBar()->removeItem(2); + calc_display->setStatusText(2, QString::null); + } + adjustSize(); + setFixedSize(sizeHint()); + KCalcSettings::setShowScientific(toggled); +} + +void KCalculator::slotLogicshow(bool toggled) +{ + if(toggled) + { + pbLogic["AND"]->show(); + pbLogic["OR"]->show(); + pbLogic["XOR"]->show(); + pbLogic["One-Complement"]->show(); + pbLogic["LeftShift"]->show(); + pbLogic["RightShift"]->show(); + if(!statusBar()->hasItem(1)) + statusBar()->insertFixedItem(" HEX ", 1, true); + statusBar()->setItemAlignment(1, AlignCenter); + calc_display->setStatusText(1, "Hex"); + resetBase(); + BaseChooseGroup->show(); + for (int i=10; i<16; i++) + (NumButtonGroup->find(i))->show(); + } + else + { + pbLogic["AND"]->hide(); + pbLogic["OR"]->hide(); + pbLogic["XOR"]->hide(); + pbLogic["One-Complement"]->hide(); + pbLogic["LeftShift"]->hide(); + pbLogic["RightShift"]->hide(); + // Hide Hex-Buttons, but first switch back to decimal + resetBase(); + BaseChooseGroup->hide(); + if(statusBar()->hasItem(1)) + statusBar()->removeItem(1); + calc_display->setStatusText(1, QString::null); + for (int i=10; i<16; i++) + (NumButtonGroup->find(i))->hide(); + } + adjustSize(); + setFixedSize(sizeHint()); + KCalcSettings::setShowLogic(toggled); +} + +void KCalculator::slotConstantsShow(bool toggled) +{ + if(toggled) + { + pbConstant[0]->show(); + pbConstant[1]->show(); + pbConstant[2]->show(); + pbConstant[3]->show(); + pbConstant[4]->show(); + pbConstant[5]->show(); + + } + else + { + pbConstant[0]->hide(); + pbConstant[1]->hide(); + pbConstant[2]->hide(); + pbConstant[3]->hide(); + pbConstant[4]->hide(); + pbConstant[5]->hide(); + } + adjustSize(); + setFixedSize(sizeHint()); + KCalcSettings::setShowConstants(toggled); +} + +// This function is for setting the constant names configured in the +// kcalc settings menu. If the user doesn't enter a name for the +// constant C1 to C6 is used. +void KCalculator::changeButtonNames() +{ + pbConstant[0]->setLabelAndTooltip(); + pbConstant[1]->setLabelAndTooltip(); + pbConstant[2]->setLabelAndTooltip(); + pbConstant[3]->setLabelAndTooltip(); + pbConstant[4]->setLabelAndTooltip(); + pbConstant[5]->setLabelAndTooltip(); +} + +void KCalculator::slotShowAll(void) +{ + // I wonder why "setChecked" does not emit "toggled" + if(!actionStatshow->isChecked()) actionStatshow->activate(); + if(!actionScientificshow->isChecked()) actionScientificshow->activate(); + if(!actionLogicshow->isChecked()) actionLogicshow->activate(); + if(!actionConstantsShow->isChecked()) actionConstantsShow->activate(); +} + +void KCalculator::slotHideAll(void) +{ + // I wonder why "setChecked" does not emit "toggled" + if(actionStatshow->isChecked()) actionStatshow->activate(); + if(actionScientificshow->isChecked()) actionScientificshow->activate(); + if(actionLogicshow->isChecked()) actionLogicshow->activate(); + if(actionConstantsShow->isChecked()) actionConstantsShow->activate(); +} + +void KCalculator::updateSettings() +{ + changeButtonNames(); + set_colors(); + set_precision(); + // Show the result in the app's caption in taskbar (wishlist - bug #52858) + disconnect(calc_display, SIGNAL(changedText(const QString &)), + this, 0); + if (KCalcSettings::captionResult()) + { + connect(calc_display, + SIGNAL(changedText(const QString &)), + SLOT(setCaption(const QString &))); + } + else + { + setCaption(QString::null); + } + calc_display->changeSettings(); + + updateGeometry(); + resize(minimumSize()); + + // + // 1999-10-31 Espen Sand: Don't ask me why ;) + // + kapp->processOneEvent(); + setFixedHeight(minimumHeight()); +} + +void KCalculator::UpdateDisplay(bool get_amount_from_core, + bool store_result_in_history) +{ + if(get_amount_from_core) + { + calc_display->update_from_core(core, store_result_in_history); + } + else + { + calc_display->update(); + } + + pbInv->setOn(false); + +} + +void KCalculator::set_colors() +{ + QPushButton *p = NULL; + + calc_display->changeSettings(); + + QColor bg = palette().active().background(); + + QPalette numPal(KCalcSettings::numberButtonsColor(), bg); + for(int i=0; i<10; i++) + { + (NumButtonGroup->find(i))->setPalette(numPal); + } + + QPalette funcPal(KCalcSettings::functionButtonsColor(), bg); + for(p = mFunctionButtonList.first(); p; + p=mFunctionButtonList.next()) + { + p->setPalette(funcPal); + } + + QPalette statPal(KCalcSettings::statButtonsColor(), bg); + for(p = mStatButtonList.first(); p; p=mStatButtonList.next()) + { + p->setPalette(statPal); + } + + QPalette hexPal(KCalcSettings::hexButtonsColor(), bg); + for(int i=10; i<16; i++) + { + (NumButtonGroup->find(i))->setPalette(hexPal); + } + + QPalette memPal(KCalcSettings::memoryButtonsColor(), bg); + for(p = mMemButtonList.first(); p; p=mMemButtonList.next()) + { + p->setPalette(memPal); + } + + QPalette opPal(KCalcSettings::operationButtonsColor(), bg); + for(p = mOperationButtonList.first(); p; + p=mOperationButtonList.next()) + { + p->setPalette(opPal); + } +} + +void KCalculator::set_precision() +{ + KNumber:: setDefaultFloatPrecision(KCalcSettings::precision()); + UpdateDisplay(false); +} + +bool KCalculator::eventFilter(QObject *o, QEvent *e) +{ + if(e->type() == QEvent::DragEnter) + { + QDragEnterEvent *ev = (QDragEnterEvent *)e; + ev->accept(KColorDrag::canDecode(ev)); + return true; + } + else if(e->type() == QEvent::DragLeave) + { + return true; + } + else if(e->type() == QEvent::Drop) + { + if(!o->isA("KCalcButton")) + return false; + + QColor c; + QDropEvent *ev = (QDropEvent *)e; + if( KColorDrag::decode(ev, c)) + { + QPtrList *list; + int num_but; + if((num_but = NumButtonGroup->id((KCalcButton*)o)) + != -1) + { + QPalette pal(c, palette().active().background()); + + // Was it hex-button or normal digit?? + if (num_but <10) + for(int i=0; i<10; i++) + (NumButtonGroup->find(i))->setPalette(pal); + else + for(int i=10; i<16; i++) + (NumButtonGroup->find(i))->setPalette(pal); + + return true; + } + else if( mFunctionButtonList.findRef((KCalcButton*)o) != -1) + { + list = &mFunctionButtonList; + } + else if( mStatButtonList.findRef((KCalcButton*)o) != -1) + { + list = &mStatButtonList; + } + else if( mMemButtonList.findRef((KCalcButton*)o) != -1) + { + list = &mMemButtonList; + } + else if( mOperationButtonList.findRef((KCalcButton*)o) != -1) + { + list = &mOperationButtonList; + } + else + return false; + + QPalette pal(c, palette().active().background()); + + for(KCalcButton *p = list->first(); p; p=list->next()) + p->setPalette(pal); + } + + return true; + } + else + { + return KMainWindow::eventFilter(o, e); + } +} + + + + +//////////////////////////////////////////////////////////////// +// Include the meta-object code for classes in this file +// + +#include "kcalc.moc" + + +extern "C" KDE_EXPORT int kdemain(int argc, char *argv[]) +{ + KAboutData aboutData( "kcalc", I18N_NOOP("KCalc"), + version, description, KAboutData::License_GPL, + I18N_NOOP("(c) 2003-2005, Klaus Niederkr" "\xc3\xbc" "ger\n" + "(c) 1996-2000, Bernd Johannes Wuebben\n" + "(c) 2000-2005, The KDE Team")); + + /* Klaus Niederkrueger */ + aboutData.addAuthor("Klaus Niederkr" "\xc3\xbc" "ger", 0, "kniederk@math.uni-koeln.de"); + aboutData.addAuthor("Bernd Johannes Wuebben", 0, "wuebben@kde.org"); + aboutData.addAuthor("Evan Teran", 0, "eteran@alum.rit.edu"); + aboutData.addAuthor("Espen Sand", 0, "espen@kde.org"); + aboutData.addAuthor("Chris Howells", 0, "howells@kde.org"); + aboutData.addAuthor("Aaron J. Seigo", 0, "aseigo@olympusproject.org"); + aboutData.addAuthor("Charles Samuels", 0, "charles@altair.dhs.org"); + /* Rene Merou */ + aboutData.addAuthor("Ren" "\xc3\xa9" " M" "\xc3\xa9" "rou", 0, "ochominutosdearco@yahoo.es"); + KCmdLineArgs::init(argc, argv, &aboutData); + + KApplication app; +#if 0 + app->enableSessionManagement(true); + app->setWmCommand(argv[0]); +#endif + + KCalculator *calc = new KCalculator; + app.setTopWidget(calc); + calc->setCaption(QString::null); + calc->show(); + + int exitCode = app.exec(); + + return(exitCode); +} + diff --git a/kcalc/kcalc.desktop b/kcalc/kcalc.desktop new file mode 100644 index 0000000..19ae663 --- /dev/null +++ b/kcalc/kcalc.desktop @@ -0,0 +1,88 @@ +[Desktop Entry] +Name=KCalc +Name[af]=Kcalc +Name[ar]=حاسبة ك +Name[eo]=Kalkulilo +Name[hi]=के-केल्क +Name[lv]=KKalk +Name[ne]=केडीई क्याल्क +Name[pa]=ਕੇਹਿਸਾਬੀ +Name[pl]=Kalkulator +Name[sv]=Kcalc +Name[ta]=கேகணிப்பான் +Name[tg]=KМошинаи ҳисобкунак +Name[th]=เครื่องคิดเลข +Name[uz]=Kalkulyator +Name[uz@cyrillic]=Калкулятор +Name[zh_TW]=KDE 計算機 +Exec=kcalc -caption "%c" %i %m +Icon=kcalc +DocPath=kcalc/index.html +GenericName=Scientific Calculator +GenericName[af]=Wetenskaplike Sakrekenaar +GenericName[ar]=آلة حاسبة علمية +GenericName[bg]=Калкулатор +GenericName[br]=Ur jederez skiantel +GenericName[bs]=Znanstveni kalkulator +GenericName[ca]=Calculadora científica +GenericName[cs]=Vědecká kalkulačka +GenericName[cy]=Cyfrifydd Gwyddonol +GenericName[da]=Videnskabelig regnemaskine +GenericName[de]=Wissenschaftlicher Taschenrechner +GenericName[el]=Επιστημονικό κομπιουτεράκι +GenericName[eo]=Scienca kalkulilo +GenericName[es]=Calculadora científica +GenericName[et]=Teaduslik kalkulaator +GenericName[eu]=Kalkulagailu Zientifikoa +GenericName[fa]=ماشین حساب علمی +GenericName[fi]=Tieteellinen laskin +GenericName[fr]=Une calculatrice scientifique +GenericName[ga]=Áireamhán Eolaíochta +GenericName[he]=מחשבון מדעי +GenericName[hi]=वैज्ञानिक गणक +GenericName[hr]=Znanstveni kalkulator +GenericName[hu]=Számológép +GenericName[is]=Öflug reiknivél +GenericName[it]=Calcolatrice scientifica +GenericName[ja]=科学電卓 +GenericName[ka]=მეცნიერული კალკულატორი +GenericName[kk]=Ғылыми калькулятор +GenericName[km]=ម៉ាស៊ីន​គិត​លេខ​វិទ្យាសាស្ត្រ +GenericName[lt]=Mokslinis skaičiuotuvas +GenericName[lv]=Zinātnisks Kalkulators +GenericName[mk]=Научен калкулатор +GenericName[mt]=Kalkulatriċi xjentifika +GenericName[nb]=Vitenskaplig kalkulator +GenericName[nds]=Wetenschaplich Taschenreekner +GenericName[ne]=वैज्ञानिक गणकयन्त्र +GenericName[nl]=Wetenschappelijke rekenmachine +GenericName[nn]=Vitskapleg kalkulator +GenericName[pa]=ਵਿਗਿਆਨਿਕ ਹਿਸਾਬੀ +GenericName[pl]=Kalkulator naukowy +GenericName[pt]=Calculadora Cientifica +GenericName[pt_BR]=Calculadora Científica +GenericName[ro]=Calculator ştiinţific +GenericName[ru]=Калькулятор +GenericName[sk]=Vedecká kalkulačka +GenericName[sl]=Znanstveni kalkulator +GenericName[sr]=Научни калкулатор +GenericName[sr@Latn]=Naučni kalkulator +GenericName[sv]=Vetenskaplig miniräknare +GenericName[ta]= அறிவியல் சார்ந்த கணிப்பான் +GenericName[tg]=Мошинаи ҳисобкунаки Илмӣ +GenericName[th]=เครื่องคิดเลขแบบวิทยาศาสตร์ +GenericName[tr]=Bilimsel Hesap Makinesi +GenericName[uk]=Калькулятор для науковців +GenericName[uz]=Ilmiy kalkulyator +GenericName[uz@cyrillic]=Илмий калкулятор +GenericName[ven]=Khalikhuleitha ya tshisaintsi +GenericName[vi]=Máy tính khoa học +GenericName[wa]=Carculete syintifike +GenericName[xh]=Umatshini Wokubala Ezenzululwazi +GenericName[zh_CN]=科学计算器 +GenericName[zh_TW]=科學計算機 +GenericName[zu]=Umshini wokubala ezenzululwazi +Terminal=false +Type=Application +X-KDE-StartupNotify=true +Categories=Qt;KDE;Utility;X-KDE-Utilities-Desktop; diff --git a/kcalc/kcalc.h b/kcalc/kcalc.h new file mode 100644 index 0000000..0ede211 --- /dev/null +++ b/kcalc/kcalc.h @@ -0,0 +1,239 @@ +/* + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef KCALC_H +#define KCALC_H + +class QPushButton; +class QRadioButton; +class QButtonGroup; +class QHButtonGroup; +class QWidget; +class DispLogic; +class Constants; +#include + +/* + Kcalc basically consist of a class for the GUI (here), a class for + the display (dlabel.h), and one for the mathematics core + (kcalc_core.h). + + When for example '+' is pressed, one sends the contents of the + Display and the '+' to the core via "core.Plus(DISPLAY_AMOUNT)". + This only updates the core. To bring the changes to the display, + use afterwards "UpdateDisplay(true)". + + "UpdateDisplay(true)" means that the amount to be displayed should + be taken from the core (get the result of some operation that was + performed), "UpdateDisplay(false)" has already the information, what + to be display (e.g. user is typing in a number). Note that in the + last case the core does not know the number typed in until some + operation button is pressed, e.g. "core.Plus(display_number)". + */ + +#include "config.h" + +// IMPORTANT this has to come after ../config.h +#include "kcalc_core.h" +#include "kcalc_button.h" +#include "kcalc_const_button.h" + +class KCalculator : public KMainWindow +{ + Q_OBJECT + +public: + KCalculator(QWidget *parent = 0, const char *name = 0); + ~KCalculator(); + +signals: + void switchInverse(bool); + void switchMode(ButtonModeFlags,bool); + void switchShowAccels(bool); + +private: + virtual bool eventFilter( QObject *o, QEvent *e ); + void updateGeometry(); + void setupMainActions(void); + void setupStatusbar(void); + QWidget *setupNumericKeys(QWidget *parent); + void setupLogicKeys(QWidget *parent); + void setupScientificKeys(QWidget *parent); + void setupStatisticKeys(QWidget *parent); + void setupConstantsKeys(QWidget *parent); + void keyPressEvent(QKeyEvent *e); + void keyReleaseEvent(QKeyEvent *e); + void set_precision(); + void set_style(); + void resetBase(void) { (BaseChooseGroup->find(1))->animateClick();}; + + void UpdateDisplay(bool get_amount_from_core = false, + bool store_result_in_history = false); + +protected slots: + void changeButtonNames(); + void updateSettings(); + void set_colors(); + void EnterEqual(); + void showSettings(); + void slotStatshow(bool toggled); + void slotScientificshow(bool toggled); + void slotLogicshow(bool toggled); + void slotConstantsShow(bool toggled); + void slotShowAll(void); + void slotHideAll(void); + void slotAngleSelected(int number); + void slotBaseSelected(int number); + void slotNumberclicked(int number_clicked); + void slotEEclicked(void); + void slotInvtoggled(bool myboolean); + void slotMemRecallclicked(void); + void slotMemStoreclicked(void); + void slotSinclicked(void); + void slotPlusMinusclicked(void); + void slotMemPlusMinusclicked(void); + void slotCosclicked(void); + void slotReciclicked(void); + void slotTanclicked(void); + void slotFactorialclicked(void); + void slotLogclicked(void); + void slotSquareclicked(void); + void slotLnclicked(void); + void slotPowerclicked(void); + void slotMCclicked(void); + void slotClearclicked(void); + void slotACclicked(void); + void slotParenOpenclicked(void); + void slotParenCloseclicked(void); + void slotANDclicked(void); + void slotXclicked(void); + void slotDivisionclicked(void); + void slotORclicked(void); + void slotXORclicked(void); + void slotPlusclicked(void); + void slotMinusclicked(void); + void slotLeftShiftclicked(void); + void slotRightShiftclicked(void); + void slotPeriodclicked(void); + void slotEqualclicked(void); + void slotPercentclicked(void); + void slotRootclicked(void); + void slotNegateclicked(void); + void slotModclicked(void); + void slotStatNumclicked(void); + void slotStatMeanclicked(void); + void slotStatStdDevclicked(void); + void slotStatMedianclicked(void); + void slotStatDataInputclicked(void); + void slotStatClearDataclicked(void); + void slotHyptoggled(bool flag); + void slotConstclicked(int); + + void slotConstantToDisplay(int constant); + void slotChooseScientificConst0(int option); + void slotChooseScientificConst1(int option); + void slotChooseScientificConst2(int option); + void slotChooseScientificConst3(int option); + void slotChooseScientificConst4(int option); + void slotChooseScientificConst5(int option); + +private: + bool inverse; + bool hyp_mode; + KNumber memory_num; + KNumber setvalue; + + // angle modes for trigonometric values + enum { + DegMode, + RadMode, + GradMode + } _angle_mode; + + +private: + QWidget *mSmallPage; + QWidget *mLargePage; + QWidget *mNumericPage; + + DispLogic* calc_display; // for historic reasons in "dlabel.h" + QRadioButton* pbBaseChoose[4]; + QPushButton* pbAngleChoose; + QDict pbStat; + QDict pbScientific; + QDict pbLogic; + KCalcConstButton* pbConstant[10]; + KCalcButton* pbAC; + KCalcButton* pbAND; + KCalcButton* pbClear; + KCalcButton* pbDivision; + KCalcButton* pbEE; + KCalcButton* pbEqual; + KCalcButton* pbFactorial; + KCalcButton* pbInv; + KCalcButton* pbMC; + KCalcButton* pbMinus; + KCalcButton* pbMod; + KCalcButton* pbMemPlusMinus; + KCalcButton* pbMemRecall; + KCalcButton* pbMemStore; + KCalcButton* pbOR; + KCalcButton* pbParenClose; + KCalcButton* pbParenOpen; + KCalcButton* pbPercent; + KCalcButton* pbPeriod; + KCalcButton* pbPlus; + KCalcButton* pbPlusMinus; + KCalcButton* pbPower; + KCalcButton* pbReci; + KSquareButton* pbRoot; + KCalcButton* pbSquare; + KCalcButton* pbX; + KCalcButton* pbXOR; + + Constants * tmp_const; // this is the dialog for configuring const + // buttons would like to remove this, but + // don't know how + + QHButtonGroup* BaseChooseGroup; + // NumButtonGroup: 0-9 = digits, 0xA-0xF = hex-keys + QButtonGroup* NumButtonGroup; + // ConstButtonGroup C1-C6 + QButtonGroup* ConstButtonGroup; + + KToggleAction *actionStatshow; + KToggleAction *actionScientificshow; + KToggleAction *actionLogicshow; + KToggleAction *actionConstantsShow; + + QPtrList mFunctionButtonList; + QPtrList mStatButtonList; + QPtrList mMemButtonList; + QPtrList mOperationButtonList; + + int mInternalSpacing; + + CalcEngine core; +}; + +#endif // KCALC_H diff --git a/kcalc/kcalc.kcfg b/kcalc/kcalc.kcfg new file mode 100644 index 0000000..e4275b7 --- /dev/null +++ b/kcalc/kcalc.kcfg @@ -0,0 +1,127 @@ + + + kapplication.h + kglobalsettings.h + config.h + + + + + #000000 + + + + #BDFFB4 + + + + QColor defaultButtonColor = kapp->palette().active().background(); + defaultButtonColor + + + + defaultButtonColor + + + + defaultButtonColor + + + + defaultButtonColor + + + + defaultButtonColor + + + + defaultButtonColor + + + + + + QFont(KGlobalSettings::generalFont().family(), 14, QFont::Bold) + + + + + + + KCalc can compute with many more digits than the number that + fits on the display. This setting gives the maximum number of + digits displayed, before KCalc starts using scientific notation, + i.e. notation of the type 2.34e12. + + 12 + 8 + 200 + + + + 2 + + + + false + + + + + + true + + + + false + + + + true + + + + false + + + + false + + + + false + + + + false + + + + + + + C1 + C2 + C3 + C4 + C5 + C6 + + + + + + 0 + 0 + 0 + 0 + 0 + 0 + + + diff --git a/kcalc/kcalc_button.cpp b/kcalc/kcalc_button.cpp new file mode 100644 index 0000000..7021a1a --- /dev/null +++ b/kcalc/kcalc_button.cpp @@ -0,0 +1,168 @@ +/* + kCalculator, a simple scientific calculator for KDE + + Copyright (C) 1996-2000 Bernd Johannes Wuebben + wuebben@kde.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include + + +#include "qdom.h" + +#include "kcalc_button.h" + + +KCalcButton::KCalcButton(QWidget * parent, const char * name) + : KPushButton(parent, name), _show_accel_mode(false), + _mode_flags(ModeNormal) +{ + setAutoDefault(false); +} + +KCalcButton::KCalcButton(const QString &label, QWidget * parent, + const char * name, const QString &tooltip) + : KPushButton(label, parent, name), _show_accel_mode(false), _mode_flags(ModeNormal) +{ + setAutoDefault(false); + addMode(ModeNormal, label, tooltip); +} + +void KCalcButton::addMode(ButtonModeFlags mode, QString label, QString tooltip, bool is_label_richtext) +{ + if (_mode.contains(mode)) _mode.remove(mode); + + _mode[mode] = ButtonMode(label, tooltip, is_label_richtext); + + // Need to put each button into default mode first + if(mode == ModeNormal) slotSetMode(ModeNormal, true); +} + +void KCalcButton::slotSetMode(ButtonModeFlags mode, bool flag) +{ + ButtonModeFlags new_mode; + + if (flag) { // if the specified mode is to be set (i.e. flag = true) + new_mode = ButtonModeFlags(_mode_flags | mode); + } else if (_mode_flags && mode) { // if the specified mode is to be cleared (i.e. flag = false) + new_mode = ButtonModeFlags(_mode_flags - mode); + } else { + return; // nothing to do + } + + if (_mode.contains(new_mode)) { + // save accel, because setting label erases accel + QKeySequence _accel = accel(); + + if(_mode[new_mode].is_label_richtext) + _label = _mode[new_mode].label; + else + setText(_mode[new_mode].label); + QToolTip::remove(this); + QToolTip::add(this, _mode[new_mode].tooltip); + _mode_flags = new_mode; + + // restore accel + setAccel(_accel); + } + + // this is necessary for people pressing CTRL and changing mode at + // the same time... + if (_show_accel_mode) slotSetAccelDisplayMode(true); + + update(); +} + +static QString escape(QString str) +{ + str.replace('&', "&&"); + return str; +} + + +void KCalcButton::slotSetAccelDisplayMode(bool flag) +{ + _show_accel_mode = flag; + + // save accel, because setting label erases accel + QKeySequence _accel = accel(); + + if (flag == true) { + setText(escape(QString(accel()))); + } else { + setText(_mode[_mode_flags].label); + } + + // restore accel + setAccel(_accel); +} + +void KCalcButton::paintLabel(QPainter *paint) +{ + if (_mode[_mode_flags].is_label_richtext) { + QSimpleRichText _text(_label, font()); + _text.draw(paint, width()/2-_text.width()/2, 0, childrenRegion(), colorGroup()); + } else { + KPushButton::drawButtonLabel(paint); + } +} + +void KCalcButton::drawButtonLabel(QPainter *paint) +{ + if (_show_accel_mode) { + KPushButton::drawButtonLabel(paint); + } else if (_mode.contains(_mode_flags)) { + paintLabel(paint); + } +} + + +void KSquareButton::paintLabel(QPainter *paint) +{ + int w = width(); + int w2 = w/2 - 13; + int h = height(); + int h2 = h/2 - 7; + // in some KDE-styles (.NET, Phase,...) we have to set the painter back to the right color + paint->setPen(foregroundColor()); + // these statements are for the improved + // representation of the sqrt function + paint->drawLine(w2, 11 + h2, w2 + 2, 7 + h2); + paint->drawLine(w2 + 2, 7 + h2, w2 + 4, 14 + h2); + paint->drawLine(w2 + 4, 14 + h2, w2 + 6, 1 + h2); + paint->drawLine(w2 + 6, 1 + h2, w2 + 27, 1 + h2); + paint->drawLine(w2 + 27, 1 + h2, w2 + 27, 4 + h2); + // add a three for the cube root + if (_mode_flags & ModeInverse) { + paint->drawText(w2-2, 9 + h2, ""); + } +} + +void KSquareButton::drawButtonLabel(QPainter *paint) +{ + if (_show_accel_mode) { + KPushButton::drawButtonLabel(paint); + } else if (_mode.contains(_mode_flags)) { + paintLabel(paint); + } +} + +#include "kcalc_button.moc" + diff --git a/kcalc/kcalc_button.h b/kcalc/kcalc_button.h new file mode 100644 index 0000000..0998b5f --- /dev/null +++ b/kcalc/kcalc_button.h @@ -0,0 +1,105 @@ +/* + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef _KCALC_BUTTON_H +#define _KCALC_BUTTON_H + +#include + +// The class KCalcButton is an overriden KPushButton. It offers extra +// functionality e.g. labels can be richtext or the accels can be +// shown in the label, but the most important thing is that the button +// may have several modes with corresponding labels. When one switches +// modes, the corresponding label is displayed. + + +enum ButtonModeFlags {ModeNormal = 0, ModeInverse = 1, ModeHyperbolic = 2}; + +class QDomNode; + +// Each kcalc button can be in one of several modes. +// The following class describes label, tooltip etc. for each mode... +class ButtonMode +{ +public: + ButtonMode(void) {}; + ButtonMode(QString &label, QString &tooltip, bool is_label_richtext) + : is_label_richtext(is_label_richtext), tooltip(tooltip) + { + if (is_label_richtext) + this->label = "
" + label + "
"; + else + this->label = label; + }; + + QString label; + bool is_label_richtext; + QString tooltip; +}; + + +class KCalcButton : public KPushButton +{ +Q_OBJECT + +public: + KCalcButton(QWidget *parent, const char * name = 0); + KCalcButton(const QString &label, QWidget *parent, const char * name = 0, + const QString &tooltip = QString()); + + void addMode(ButtonModeFlags mode, QString label, QString tooltip, bool is_label_richtext = false); + +public slots: + void slotSetMode(ButtonModeFlags mode, bool flag); + void slotSetAccelDisplayMode(bool flag); + +protected: + virtual void drawButtonLabel(QPainter *paint); + void paintLabel(QPainter *paint); + +protected: + bool _show_accel_mode; + QString _label; + + ButtonModeFlags _mode_flags; + + QMap _mode; +}; + +class KSquareButton : public KCalcButton +{ +Q_OBJECT + +public: + KSquareButton(QWidget *parent, const char * name = 0) + : KCalcButton(parent, name) { }; + KSquareButton(const QString &label, QWidget *parent, const char * name = 0, + const QString &tooltip = QString()) + : KCalcButton(label, parent, name, tooltip) { }; + +protected: + virtual void drawButtonLabel(QPainter *paint); + void paintLabel(QPainter *paint); +}; + +#endif // _KCALC_BUTTON_H diff --git a/kcalc/kcalc_const_button.cpp b/kcalc/kcalc_const_button.cpp new file mode 100644 index 0000000..e9c4216 --- /dev/null +++ b/kcalc/kcalc_const_button.cpp @@ -0,0 +1,109 @@ +/* + kCalculator, a simple scientific calculator for KDE + + Copyright (C) 2003 Klaus Niederkrueger + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include + + +#include +#include +#include + +#include "kcalc_const_button.h" +#include "kcalc_const_menu.h" +#include "kcalc_settings.h" + + +KCalcConstButton::KCalcConstButton(QWidget *parent, int but_num, const char * name) + : KCalcButton(parent, name), _button_num(but_num) +{ + addMode(ModeInverse, "Store", i18n("Write display data into memory")); + + initPopupMenu(); +} + + +KCalcConstButton::KCalcConstButton(const QString &label, QWidget *parent, int but_num, + const char * name, const QString &tooltip) + : KCalcButton(label, parent, name, tooltip), _button_num(but_num) +{ + addMode(ModeInverse, "Store", i18n("Write display data into memory")); + + initPopupMenu(); +} + +QString KCalcConstButton::constant(void) const +{ + return KCalcSettings::valueConstant(_button_num); +} + +void KCalcConstButton::setLabelAndTooltip(void) +{ + QString new_label = QString("C") + QString().setNum(_button_num + 1); + QString new_tooltip; + + new_label = (KCalcSettings::nameConstant(_button_num).isNull() ? new_label : KCalcSettings::nameConstant(_button_num)); + + new_tooltip = new_label + "=" + KCalcSettings::valueConstant(_button_num); + + addMode(ModeNormal, new_label, new_tooltip); +} + +void KCalcConstButton::initPopupMenu(void) +{ + KCalcConstMenu *tmp_menu = new KCalcConstMenu(this); + + _popup = new KPopupMenu(this, "set const-cutton"); + _popup->insertItem(i18n("Set Name"), 0); + _popup->insertItem(i18n("Choose From List"), tmp_menu, 1); + + connect(_popup, SIGNAL(activated(int)), SLOT(slotConfigureButton(int))); + connect(tmp_menu, SIGNAL(activated(int)), SLOT(slotChooseScientificConst(int))); + + KContextMenuManager::insert(this, _popup); +} + +void KCalcConstButton::slotConfigureButton(int option) +{ + if (option == 0) + { + bool yes_no; + QString input = KInputDialog::text(i18n("New Name for Constant"), i18n("New name:"), + text(), &yes_no, this, "nameUserConstants-Dialog"); + if(yes_no) { + KCalcSettings::setNameConstant(_button_num, input); + setLabelAndTooltip(); + } + } +} + +void KCalcConstButton::slotChooseScientificConst(int option) +{ + KCalcSettings::setValueConstant(_button_num, + KCalcConstMenu::Constants[option].value); + + KCalcSettings::setNameConstant(_button_num, + KCalcConstMenu::Constants[option].label); + + setLabelAndTooltip(); +} + +#include "kcalc_const_button.moc" + diff --git a/kcalc/kcalc_const_button.h b/kcalc/kcalc_const_button.h new file mode 100644 index 0000000..18ebf3e --- /dev/null +++ b/kcalc/kcalc_const_button.h @@ -0,0 +1,58 @@ +/* + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef _KCALC_CONST_BUTTON_H +#define _KCALC_CONST_BUTTON_H + +#include +#include "kcalc_button.h" + + +class KCalcConstButton : public KCalcButton +{ +Q_OBJECT + + public: + + KCalcConstButton(QWidget *parent, int but_num, const char * name = 0); + + KCalcConstButton(const QString &label, QWidget *parent, int but_num, const char * name = 0, + const QString &tooltip = QString()); + + QString constant(void) const; + + void setLabelAndTooltip(void); + + private slots: + void slotConfigureButton(int option); + void slotChooseScientificConst(int option); + + private: + void initPopupMenu(void); + + KPopupMenu* _popup; + int _button_num; +}; + + +#endif // _KCALC_CONST_BUTTON_H diff --git a/kcalc/kcalc_const_menu.cpp b/kcalc/kcalc_const_menu.cpp new file mode 100644 index 0000000..77bb02e --- /dev/null +++ b/kcalc/kcalc_const_menu.cpp @@ -0,0 +1,89 @@ +/* + kCalculator, a simple scientific calculator for KDE + + Copyright (C) 2003 Klaus Niederkrueger + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include + +#include "kcalc_const_menu.h" + +#define NUM_CONST 17 + +const struct science_constant KCalcConstMenu::Constants[] = { + {QString::fromUtf8("π"), I18N_NOOP("Pi"), "", + "3.1415926535897932384626433832795028841971693993751" + "05820974944592307816406286208998628034825342117068", Mathematics}, + {"e", I18N_NOOP("Euler Number"), "", + "2.7182818284590452353602874713526624977572470936999" + "59574966967627724076630353547594571382178525166427", Mathematics}, + {QString::fromUtf8("φ"), I18N_NOOP("Golden Ratio"), "", "1.61803398874989484820458683436563811", Mathematics}, + {"c", I18N_NOOP("Light Speed"), "", "2.99792458e8", Electromagnetic}, + {"h", I18N_NOOP("Planck's Constant"), "", "6.6260693e-34", Nuclear}, + {"G", I18N_NOOP("Constant of Gravitation"), "", "6.6742e-11", Gravitation}, + {"g", I18N_NOOP("Earth Acceleration"), "", "9.80665", Gravitation}, + {"e", I18N_NOOP("Elementary Charge"), "", "1.60217653e-19", ConstantCategory(Electromagnetic|Nuclear)}, + {"Z_0", I18N_NOOP("Impedance of Vacuum"), "", "376.730313461", Electromagnetic}, + {QString::fromUtf8("α"), I18N_NOOP("Fine-Structure Constant"), "", "7.297352568e-3", Nuclear}, + {QString::fromUtf8("μ")+"_0", I18N_NOOP("Permeability of Vacuum"), "", "1.2566370614e-6", Electromagnetic}, + {QString::fromUtf8("ε")+"_0", I18N_NOOP("Permittivity of vacuum"), "", "8.854187817e-12", Electromagnetic}, + {"k", I18N_NOOP("Boltzmann Constant"), "", "1.3806505e-23", Thermodynamics}, + {"1u", I18N_NOOP("Atomic Mass Unit"), "", "1.66053886e-27", Thermodynamics}, + {"R", I18N_NOOP("Molar Gas Constant"), "", "8.314472", Thermodynamics}, + {QString::fromUtf8("σ"), I18N_NOOP("Stefan-Boltzmann Constant"), "", "5.670400e-8", Thermodynamics}, + {"N_A", I18N_NOOP("Avogadro's Number"), "", "6.0221415e23", Thermodynamics} +}; + +KCalcConstMenu::KCalcConstMenu(QWidget * parent, const char * name) + : QPopupMenu(parent, name) +{ + QPopupMenu *math_menu = new QPopupMenu(this, "mathematical constants"); + QPopupMenu *em_menu = new QPopupMenu(this, "electromagnetic constants"); + QPopupMenu *nuclear_menu = new QPopupMenu(this, "nuclear constants"); + QPopupMenu *thermo_menu = new QPopupMenu(this, "thermodynamics constants"); + QPopupMenu *gravitation_menu = new QPopupMenu(this, "gravitation constants"); + + insertItem(i18n("Mathematics"), math_menu); + insertItem(i18n("Electromagnetism"), em_menu); + insertItem(i18n("Atomic && Nuclear"), nuclear_menu); + insertItem(i18n("Thermodynamics"), thermo_menu); + insertItem(i18n("Gravitation"), gravitation_menu); + + connect(math_menu, SIGNAL(activated(int)), this, SLOT(slotPassActivate(int))); + connect(em_menu, SIGNAL(activated(int)), this, SLOT(slotPassActivate(int))); + connect(nuclear_menu, SIGNAL(activated(int)), this, SLOT(slotPassActivate(int))); + connect(thermo_menu, SIGNAL(activated(int)), this, SLOT(slotPassActivate(int))); + connect(gravitation_menu, SIGNAL(activated(int)), this, SLOT(slotPassActivate(int))); + + + for (int i = 0; iinsertItem(i18n(Constants[i].name), i); + if(Constants[i].category & Electromagnetic) + em_menu->insertItem(i18n(Constants[i].name), i); + if(Constants[i].category & Nuclear) + nuclear_menu->insertItem(i18n(Constants[i].name), i); + if(Constants[i].category & Thermodynamics) + thermo_menu->insertItem(i18n(Constants[i].name), i); + if(Constants[i].category & Gravitation) + gravitation_menu->insertItem(i18n(Constants[i].name), i); + } +} + + +#include "kcalc_const_menu.moc" diff --git a/kcalc/kcalc_const_menu.h b/kcalc/kcalc_const_menu.h new file mode 100644 index 0000000..4ae8da3 --- /dev/null +++ b/kcalc/kcalc_const_menu.h @@ -0,0 +1,55 @@ +/* + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 2004 Klaus Niederkruger + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef _KCALC_CONST_MENU_H +#define _KCALC_CONST_MENU_H + +#include +#include + +enum ConstantCategory {Mathematics = 1, Electromagnetic = 2, Nuclear = 4, Thermodynamics = 8, Gravitation = 16}; + +struct science_constant{ + QString label; + const char * name; + QString whatsthis; + QString value; + ConstantCategory category; +}; + +class KCalcConstMenu : public QPopupMenu +{ +Q_OBJECT + + public: + KCalcConstMenu(QWidget * parent = 0, const char * name = 0); + + static const struct science_constant Constants[]; + +public slots: + void slotPassActivate(int item) + { + emit activated(item); + }; +}; + +#endif // _KCALC_CONST_MENU_H diff --git a/kcalc/kcalc_core.cpp b/kcalc/kcalc_core.cpp new file mode 100644 index 0000000..4270895 --- /dev/null +++ b/kcalc/kcalc_core.cpp @@ -0,0 +1,1004 @@ +/* + kCalculator, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + The stack engine contained in this file was take from + Martin Bartlett's xfrmcalc + + portions: Copyright (C) 2003-2006 Klaus Niederkrueger + + portions: Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + portions: Copyright (C) 1995 Martin Bartlett + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#if defined(_ISOC99_SOURCE) + #include + #include + #include + #include + #include + #include + using namespace std; +#else + #include + #include + #include + #include + #include + #include +#endif + +#include +#include "kcalc_core.h" +#include +#include +#include +#include "kcalctype.h" + +#ifndef HAVE_FUNC_ISINF + #ifdef HAVE_IEEEFP_H + #include + #else + #include + #endif + +#undef isinf +int isinf(double x) +{ +#ifdef _HPUX_SOURCE +return !isfinite(x) && x == x; +#else +return !finite(x) && x==x; +#endif +} + +#endif + + +static void fpe_handler(int fpe_parm) +{ + UNUSED(fpe_parm); + // display_error = true; + //tmp_number = 0L; +} + + +static bool _error; + +static KNumber ExecOr(const KNumber & left_op, const KNumber & right_op) +{ + return (left_op | right_op); +} + +static KNumber ExecXor(const KNumber & left_op, const KNumber & right_op) +{ + return (left_op | right_op) - (left_op & right_op); +} + +static KNumber ExecAnd(const KNumber & left_op, const KNumber & right_op) +{ + return (left_op & right_op); +} + +static KNumber ExecLsh(const KNumber & left_op, const KNumber & right_op) +{ + return left_op << right_op; +} + +static KNumber ExecRsh(const KNumber & left_op, const KNumber & right_op) +{ + return left_op >> right_op; +} + +static KNumber ExecAdd(const KNumber & left_op, const KNumber & right_op) +{ + return left_op + right_op; +} + +static KNumber ExecSubtract(const KNumber & left_op, const KNumber & right_op) +{ + return left_op - right_op; +} + +static KNumber ExecMultiply(const KNumber & left_op, const KNumber & right_op) +{ + return left_op * right_op; +} + +static KNumber ExecDivide(const KNumber & left_op, const KNumber & right_op) +{ + return left_op / right_op; +} + +static KNumber ExecMod(const KNumber & left_op, const KNumber & right_op) +{ + return left_op % right_op; +} + +static KNumber ExecIntDiv(const KNumber & left_op, const KNumber & right_op) +{ + return (left_op / right_op).integerPart(); +} + +bool isoddint(const KNumber & input) +{ + if (input.type() != KNumber::IntegerType) return false; + // Routine to check if KNumber is an Odd integer + return ( (input / KNumber(2)).type() == KNumber::IntegerType); +} + +static KNumber ExecPower(const KNumber & left_op, const KNumber & right_op) +{ + return left_op.power(right_op); +} + +static KNumber ExecPwrRoot(const KNumber & left_op, const KNumber & right_op) +{ + return left_op.power(KNumber::One / right_op); +} + +static KNumber ExecAddP(const KNumber & left_op, const KNumber & right_op) +{ + return left_op * (KNumber::One + right_op/KNumber(100)); +} + +static KNumber ExecSubP(const KNumber & left_op, const KNumber & right_op) +{ + return left_op * (KNumber::One - right_op/KNumber(100)); +} + +static KNumber ExecMultiplyP(const KNumber & left_op, const KNumber & right_op) +{ + return left_op * right_op / KNumber(100); +} + +static KNumber ExecDivideP(const KNumber & left_op, const KNumber & right_op) +{ + return left_op * KNumber(100) / right_op; +} + + +// build precedence list +const struct operator_data CalcEngine::Operator[] = { + { 0, NULL, NULL}, // FUNC_EQUAL + { 0, NULL, NULL}, // FUNC_PERCENT + { 0, NULL, NULL}, // FUNC_BRACKET + { 1, ExecOr, NULL}, // FUNC_OR + { 2, ExecXor, NULL}, // FUNC_XOR + { 3, ExecAnd, NULL}, // FUNC_AND + { 4, ExecLsh, NULL}, // FUNC_LSH + { 4, ExecRsh, NULL}, // FUNC_RSH + { 5, ExecAdd, ExecAddP}, // FUNC_ADD + { 5, ExecSubtract, ExecSubP}, // FUNC_SUBTRACT + { 6, ExecMultiply, ExecMultiplyP}, // FUNC_MULTIPLY + { 6, ExecDivide, ExecDivideP}, // FUNC_DIVIDE + { 6, ExecMod, NULL}, // FUNC_MOD + { 6, ExecIntDiv, NULL}, // FUNC_INTDIV + { 7, ExecPower, NULL}, // FUNC_POWER + { 7, ExecPwrRoot, NULL} // FUNC_PWR_ROOT +}; + + +CalcEngine::CalcEngine() + : _percent_mode(false) +{ + // + // Basic initialization involves initializing the calcultion + // stack, and setting up the floating point excetion signal + // handler to trap the errors that the code can/has not been + // written to trap. + // + + struct sigaction fpe_trap; + + sigemptyset(&fpe_trap.sa_mask); + fpe_trap.sa_handler = &fpe_handler; +#ifdef SA_RESTART + fpe_trap.sa_flags = SA_RESTART; +#endif + sigaction(SIGFPE, &fpe_trap, NULL); + + _last_number = KNumber::Zero; + _error = false; +} + +KNumber CalcEngine::lastOutput(bool &error) const +{ + error = _error; + return _last_number; +} + +void CalcEngine::ArcCosDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + + if (input.type() == KNumber::IntegerType) { + if (input == KNumber::One) { + _last_number = KNumber::Zero; + return; + } + if (input == - KNumber::One) { + _last_number = KNumber(180); + return; + } + if (input == KNumber::Zero) { + _last_number = KNumber(90); + return; + } + } + CALCAMNT tmp_num = static_cast(input); + _last_number = Rad2Deg(KNumber(double(ACOS(tmp_num)))); +} + +void CalcEngine::ArcCosRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(ACOS(tmp_num))); +} + +void CalcEngine::ArcCosGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + if (input.type() == KNumber::IntegerType) { + if (input == KNumber::One) { + _last_number = KNumber::Zero; + return; + } + if (input == - KNumber::One) { + _last_number = KNumber(200); + return; + } + if (input == KNumber::Zero) { + _last_number = KNumber(100); + return; + } + } + CALCAMNT tmp_num = static_cast(input); + _last_number = Rad2Gra(KNumber(double(ACOS(tmp_num)))); +} + +void CalcEngine::ArcSinDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + if (input.type() == KNumber::IntegerType) { + if (input == KNumber::One) { + _last_number = KNumber(90); + return; + } + if (input == - KNumber::One) { + _last_number = KNumber(-90); + return; + } + if (input == KNumber::Zero) { + _last_number = KNumber(0); + return; + } + } + CALCAMNT tmp_num = static_cast(input); + _last_number = Rad2Deg(KNumber(double(ASIN(tmp_num)))); +} + +void CalcEngine::ArcSinRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(ASIN(tmp_num))); +} + +void CalcEngine::ArcSinGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType || + input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + if (input.type() == KNumber::IntegerType) { + if (input == KNumber::One) { + _last_number = KNumber(100); + return; + } + if (input == - KNumber::One) { + _last_number = KNumber(-100); + return; + } + if (input == KNumber::Zero) { + _last_number = KNumber(0); + return; + } + } + CALCAMNT tmp_num = static_cast(input); + _last_number = Rad2Gra(KNumber(double(ASIN(tmp_num)))); +} + +void CalcEngine::ArcTangensDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber(90); + if (input == KNumber("-inf")) _last_number = KNumber(-90); + return; + } + + CALCAMNT tmp_num = static_cast(input); + _last_number = Rad2Deg(KNumber(double(ATAN(tmp_num)))); +} + +void CalcEngine::ArcTangensRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) + _last_number = KNumber::Pi/KNumber(2); + if (input == KNumber("-inf")) + _last_number = -KNumber::Pi/KNumber(2); + return; + } + + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(ATAN(tmp_num))); +} + +void CalcEngine::ArcTangensGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber(100); + if (input == KNumber("-inf")) _last_number = KNumber(-100); + return; + } + + CALCAMNT tmp_num = static_cast(input); + _last_number = Rad2Gra(KNumber(double(ATAN(tmp_num)))); +} + +void CalcEngine::AreaCosHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("nan"); + return; + } + + if (input < KNumber::One) { + _last_number = KNumber("nan"); + return; + } + if (input == KNumber::One) { + _last_number = KNumber::Zero; + return; + } + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(ACOSH(tmp_num))); +} + +void CalcEngine::AreaSinHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("-inf"); + return; + } + + if (input == KNumber::Zero) { + _last_number = KNumber::Zero; + return; + } + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(ASINH(tmp_num))); +} + +void CalcEngine::AreaTangensHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + if (input < -KNumber::One || input > KNumber::One) { + _last_number = KNumber("nan"); + return; + } + if (input == KNumber::One) { + _last_number = KNumber("inf"); + return; + } + if (input == - KNumber::One) { + _last_number = KNumber("-inf"); + return; + } + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(ATANH(tmp_num))); +} + +void CalcEngine::Complement(KNumber input) +{ + if (input.type() != KNumber::IntegerType) + { + _last_number = KNumber("nan"); + return; + } + _last_number = - input - KNumber::One; +} + + + +// move a number into the interval [0,360) by adding multiples of 360 +static KNumber const moveIntoDegInterval(KNumber const &num) +{ + KNumber tmp_num = num - (num/KNumber(360)).integerPart() * KNumber(360); + if(tmp_num < KNumber::Zero) + return tmp_num + KNumber(360); + return tmp_num; +} + +// move a number into the interval [0,400) by adding multiples of 400 +static KNumber const moveIntoGradInterval(KNumber const &num) +{ + KNumber tmp_num = num - (num/KNumber(400)).integerPart() * KNumber(400); + if(tmp_num < KNumber::Zero) + return tmp_num + KNumber(400); + return tmp_num; +} + + +void CalcEngine::CosDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + KNumber trunc_input = moveIntoDegInterval(input); + if (trunc_input.type() == KNumber::IntegerType) { + KNumber mult = trunc_input/KNumber(90); + if (mult.type() == KNumber::IntegerType) { + if (mult == KNumber::Zero) + _last_number = 1; + else if (mult == KNumber(1)) + _last_number = 0; + else if (mult == KNumber(2)) + _last_number = -1; + else if (mult == KNumber(3)) + _last_number = 0; + else qDebug("Something wrong in CalcEngine::CosDeg\n"); + return; + } + } + trunc_input = Deg2Rad(trunc_input); + + CALCAMNT tmp_num = static_cast(trunc_input); + _last_number = KNumber(double(COS(tmp_num))); +} + +void CalcEngine::CosRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(COS(tmp_num))); +} + +void CalcEngine::CosGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + KNumber trunc_input = moveIntoGradInterval(input); + if (trunc_input.type() == KNumber::IntegerType) { + KNumber mult = trunc_input/KNumber(100); + if (mult.type() == KNumber::IntegerType) { + if (mult == KNumber::Zero) + _last_number = 1; + else if (mult == KNumber(1)) + _last_number = 0; + else if (mult == KNumber(2)) + _last_number = -1; + else if (mult == KNumber(3)) + _last_number = 0; + else qDebug("Something wrong in CalcEngine::CosGrad\n"); + return; + } + } + trunc_input = Gra2Rad(trunc_input); + + CALCAMNT tmp_num = static_cast(trunc_input); + _last_number = KNumber(double(COS(tmp_num))); +} + +void CalcEngine::CosHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("inf"); + return; + } + + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(COSH(tmp_num))); +} + +void CalcEngine::Cube(KNumber input) +{ + _last_number = input*input*input; +} + +void CalcEngine::CubeRoot(KNumber input) +{ + _last_number = input.cbrt(); +} + +void CalcEngine::Exp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber::Zero; + return; + } + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(EXP(tmp_num))); +} + +void CalcEngine::Exp10(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber::Zero; + return; + } + _last_number = KNumber(10).power(input); +} + + +static KNumber _factorial(KNumber input) +{ + KNumber tmp_amount = input; + + // don't do recursive factorial, + // because large numbers lead to + // stack overflows + while (tmp_amount > KNumber::One) + { + tmp_amount -= KNumber::One; + + input = tmp_amount * input; + + } + + if (tmp_amount < KNumber::One) + return KNumber::One; + return input; +} + + +void CalcEngine::Factorial(KNumber input) +{ + if (input == KNumber("inf")) return; + if (input < KNumber::Zero || input.type() == KNumber::SpecialType) + { + _error = true; + _last_number = KNumber("nan"); + return; + } + KNumber tmp_amount = input.integerPart(); + + _last_number = _factorial(tmp_amount); +} + +void CalcEngine::InvertSign(KNumber input) +{ + _last_number = -input; +} + +void CalcEngine::Ln(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("nan"); + return; + } + if (input < KNumber::Zero) + _last_number = KNumber("nan"); + else if (input == KNumber::Zero) + _last_number = KNumber("-inf"); + else if (input == KNumber::One) + _last_number = 0; + else { + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(LN(tmp_num))); + } +} + +void CalcEngine::Log10(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("nan"); + return; + } + if (input < KNumber::Zero) + _last_number = KNumber("nan"); + else if (input == KNumber::Zero) + _last_number = KNumber("-inf"); + else if (input == KNumber::One) + _last_number = 0; + else { + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(LOG_TEN(tmp_num))); + } +} + +void CalcEngine::ParenClose(KNumber input) +{ + // evaluate stack until corresponding opening bracket + while (!_stack.isEmpty()) + { + _node tmp_node = _stack.pop(); + if (tmp_node.operation == FUNC_BRACKET) + break; + input = evalOperation(tmp_node.number, tmp_node.operation, + input); + } + _last_number = input; + return; +} + +void CalcEngine::ParenOpen(KNumber input) +{ + enterOperation(input, FUNC_BRACKET); +} + +void CalcEngine::Reciprocal(KNumber input) +{ + _last_number = KNumber::One/input; +} + + +void CalcEngine::SinDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + KNumber trunc_input = moveIntoDegInterval(input); + if (trunc_input.type() == KNumber::IntegerType) { + KNumber mult = trunc_input/KNumber(90); + if (mult.type() == KNumber::IntegerType) { + if (mult == KNumber::Zero) + _last_number = 0; + else if (mult == KNumber(1)) + _last_number = 1; + else if (mult == KNumber(2)) + _last_number = 0; + else if (mult == KNumber(3)) + _last_number = -1; + else qDebug("Something wrong in CalcEngine::SinDeg\n"); + return; + } + } + trunc_input = Deg2Rad(trunc_input); + + CALCAMNT tmp_num = static_cast(trunc_input); + _last_number = KNumber(double(SIN(tmp_num))); +} + +void CalcEngine::SinRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(SIN(tmp_num))); +} + +void CalcEngine::SinGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + KNumber trunc_input = moveIntoGradInterval(input); + if (trunc_input.type() == KNumber::IntegerType) { + KNumber mult = trunc_input/KNumber(100); + if (mult.type() == KNumber::IntegerType) { + if (mult == KNumber::Zero) + _last_number = 0; + else if (mult == KNumber(1)) + _last_number = 1; + else if (mult == KNumber(2)) + _last_number = 0; + else if (mult == KNumber(3)) + _last_number = -1; + else qDebug("Something wrong in CalcEngine::SinGrad\n"); + return; + } + } + + trunc_input = Gra2Rad(trunc_input); + + CALCAMNT tmp_num = static_cast(trunc_input); + _last_number = KNumber(double(SIN(tmp_num))); +} + +void CalcEngine::SinHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber("inf"); + if (input == KNumber("-inf")) _last_number = KNumber("-inf"); + return; + } + + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(SINH(tmp_num))); +} + +void CalcEngine::Square(KNumber input) +{ + _last_number = input*input; +} + +void CalcEngine::SquareRoot(KNumber input) +{ + _last_number = input.sqrt(); +} + +void CalcEngine::StatClearAll(KNumber input) +{ + UNUSED(input); + stats.clearAll(); +} + +void CalcEngine::StatCount(KNumber input) +{ + UNUSED(input); + _last_number = KNumber(stats.count()); +} + +void CalcEngine::StatDataNew(KNumber input) +{ + stats.enterData(input); + _last_number = KNumber(stats.count()); +} + +void CalcEngine::StatDataDel(KNumber input) +{ + UNUSED(input); + stats.clearLast(); + _last_number = KNumber::Zero; +} + +void CalcEngine::StatMean(KNumber input) +{ + UNUSED(input); + _last_number = stats.mean(); + + _error = stats.error(); +} + +void CalcEngine::StatMedian(KNumber input) +{ + UNUSED(input); + _last_number = stats.median(); + + _error = stats.error(); +} + +void CalcEngine::StatStdDeviation(KNumber input) +{ + UNUSED(input); + _last_number = stats.std(); + + _error = stats.error(); +} + +void CalcEngine::StatStdSample(KNumber input) +{ + UNUSED(input); + _last_number = stats.sample_std(); + + _error = stats.error(); +} + +void CalcEngine::StatSum(KNumber input) +{ + UNUSED(input); + _last_number = stats.sum(); +} + +void CalcEngine::StatSumSquares(KNumber input) +{ + UNUSED(input); + _last_number = stats.sum_of_squares(); + + _error = stats.error(); +} + +void CalcEngine::TangensDeg(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + SinDeg(input); + KNumber arg1 = _last_number; + CosDeg(input); + KNumber arg2 = _last_number; + _last_number = arg1 / arg2; +} + +void CalcEngine::TangensRad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + SinRad(input); + KNumber arg1 = _last_number; + CosRad(input); + KNumber arg2 = _last_number; + _last_number = arg1 / arg2; +} + +void CalcEngine::TangensGrad(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + _last_number = KNumber("nan"); + return; + } + + SinGrad(input); + KNumber arg1 = _last_number; + CosGrad(input); + KNumber arg2 = _last_number; + _last_number = arg1 / arg2; +} + +void CalcEngine::TangensHyp(KNumber input) +{ + if (input.type() == KNumber::SpecialType) { + if (input == KNumber("nan")) _last_number = KNumber("nan"); + if (input == KNumber("inf")) _last_number = KNumber::One; + if (input == KNumber("-inf")) _last_number = KNumber::MinusOne; + return; + } + + CALCAMNT tmp_num = static_cast(input); + _last_number = KNumber(double(TANH(tmp_num))); +} + +KNumber CalcEngine::evalOperation(KNumber arg1, Operation operation, + KNumber arg2) +{ + if (!_percent_mode || Operator[operation].prcnt_ptr == NULL) + { + return (Operator[operation].arith_ptr)(arg1, arg2); + } else { + _percent_mode = false; + return (Operator[operation].prcnt_ptr)(arg1, arg2); + } +} + +void CalcEngine::enterOperation(KNumber number, Operation func) +{ + _node tmp_node; + + if (func == FUNC_BRACKET) + { + tmp_node.number = 0; + tmp_node.operation = FUNC_BRACKET; + + _stack.push(tmp_node); + + return; + } + + if (func == FUNC_PERCENT) + { + _percent_mode = true; + } + + tmp_node.number = number; + tmp_node.operation = func; + + _stack.push(tmp_node); + + evalStack(); +} + +bool CalcEngine::evalStack(void) +{ + // this should never happen + if (_stack.isEmpty()) KMessageBox::error(0L, i18n("Stack processing error - empty stack")); + + _node tmp_node = _stack.pop(); + + while (! _stack.isEmpty()) + { + _node tmp_node2 = _stack.pop(); + if (Operator[tmp_node.operation].precedence <= + Operator[tmp_node2.operation].precedence) + { + if (tmp_node2.operation == FUNC_BRACKET) continue; + KNumber tmp_result = + evalOperation(tmp_node2.number, tmp_node2.operation, + tmp_node.number); + tmp_node.number = tmp_result; + } + else + { + _stack.push(tmp_node2); + break; + } + + } + + if(tmp_node.operation != FUNC_EQUAL && tmp_node.operation != FUNC_PERCENT) + _stack.push(tmp_node); + + _last_number = tmp_node.number; + return true; +} + +void CalcEngine::Reset() +{ + _error = false; + _last_number = KNumber::Zero; + + _stack.clear(); +} + + diff --git a/kcalc/kcalc_core.h b/kcalc/kcalc_core.h new file mode 100644 index 0000000..edd33f3 --- /dev/null +++ b/kcalc/kcalc_core.h @@ -0,0 +1,181 @@ +/* + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef _KCALC_CORE_H +#define _KCALC_CORE_H + +#include "stats.h" +#include +#include "knumber.h" + +#define POS_ZERO 1e-19L /* What we consider zero is */ +#define NEG_ZERO -1e-19L /* anything between these two */ + + +typedef KNumber (*Arith)(const KNumber &, const KNumber &); +typedef KNumber (*Prcnt)(const KNumber &, const KNumber &); + +#define UNUSED(x) ((void)(x)) + + + +struct operator_data { + int precedence; // priority of operators in " enum Operation" + Arith arith_ptr; + Prcnt prcnt_ptr; +}; + +class CalcEngine +{ + public: + // operations that can be stored in calculation stack + enum Operation { + FUNC_EQUAL, + FUNC_PERCENT, + FUNC_BRACKET, + FUNC_OR, + FUNC_XOR, + FUNC_AND, + FUNC_LSH, + FUNC_RSH, + FUNC_ADD, + FUNC_SUBTRACT, + FUNC_MULTIPLY, + FUNC_DIVIDE, + FUNC_MOD, + FUNC_INTDIV, + FUNC_POWER, + FUNC_PWR_ROOT + }; + + CalcEngine(); + + KNumber lastOutput(bool &error) const; + + void enterOperation(KNumber num, Operation func); + + + void ArcCosDeg(KNumber input); + void ArcCosRad(KNumber input); + void ArcCosGrad(KNumber input); + void ArcSinDeg(KNumber input); + void ArcSinRad(KNumber input); + void ArcSinGrad(KNumber input); + void ArcTangensDeg(KNumber input); + void ArcTangensRad(KNumber input); + void ArcTangensGrad(KNumber input); + void AreaCosHyp(KNumber input); + void AreaSinHyp(KNumber input); + void AreaTangensHyp(KNumber input); + void Complement(KNumber input); + void CosDeg(KNumber input); + void CosRad(KNumber input); + void CosGrad(KNumber input); + void CosHyp(KNumber input); + void Cube(KNumber input); + void CubeRoot(KNumber input); + void Exp(KNumber input); + void Exp10(KNumber input); + void Factorial(KNumber input); + void InvertSign(KNumber input); + void Ln(KNumber input); + void Log10(KNumber input); + void ParenClose(KNumber input); + void ParenOpen(KNumber input); + void Reciprocal(KNumber input); + void SinDeg(KNumber input); + void SinGrad(KNumber input); + void SinRad(KNumber input); + void SinHyp(KNumber input); + void Square(KNumber input); + void SquareRoot(KNumber input); + void StatClearAll(KNumber input); + void StatCount(KNumber input); + void StatDataNew(KNumber input); + void StatDataDel(KNumber input); + void StatMean(KNumber input); + void StatMedian(KNumber input); + void StatStdDeviation(KNumber input); + void StatStdSample(KNumber input); + void StatSum(KNumber input); + void StatSumSquares(KNumber input); + void TangensDeg(KNumber input); + void TangensRad(KNumber input); + void TangensGrad(KNumber input); + void TangensHyp(KNumber input); + + void Reset(); + private: + KStats stats; + + typedef struct { + KNumber number; + Operation operation; + } _node; + + // Stack holds all operations and numbers that have not yet been + // processed, e.g. user types "2+3*", the calculation can not be + // executed, because "*" has a higher precedence than "+", so we + // need to wait for the next number. + // + // In the stack this would be stored as ((2,+),(3,*),...) + // + // "enterOperation": If the introduced Operation has lower priority + // than the preceding operations in the stack, then we can start to + // evaluate the stack (with "evalStack"). Otherwise we append the new + // Operation and number to the stack. + // + // E.g. "2*3+" evaluates to "6+", but "2+3*" can not be evaluated + // yet. + // + // We also take care of brackets, by writing a marker "FUNC_BRACKET" + // into the stack, each time the user opens one. When a bracket is + // closed, everything in the stack is evaluated until the first + // marker "FUNC_BRACKET" found. + QValueStack<_node> _stack; + + KNumber _last_number; + + bool _percent_mode; + + + static const struct operator_data Operator[]; + + bool evalStack(void); + + KNumber evalOperation(KNumber arg1, Operation operation, KNumber arg2); + + const KNumber Deg2Rad(const KNumber &x) const + { return KNumber(2) * KNumber::Pi / KNumber(360) * x; } + const KNumber Gra2Rad(const KNumber &x) const + { return KNumber(2)*KNumber::Pi / KNumber(400) * x; } + const KNumber Rad2Deg(const KNumber &x) const + { return KNumber(360) / (KNumber(2) * KNumber::Pi) * x; } + const KNumber Rad2Gra(const KNumber &x) const + { return KNumber(400) / (KNumber(2)*KNumber::Pi) * x; } + +}; + + +#endif //_KCALC_CORE_H diff --git a/kcalc/kcalc_settings.kcfgc b/kcalc/kcalc_settings.kcfgc new file mode 100644 index 0000000..ac8bd41 --- /dev/null +++ b/kcalc/kcalc_settings.kcfgc @@ -0,0 +1,8 @@ +# Code generation options for kconfig_compiler +File=kcalc.kcfg +ClassName=KCalcSettings +Singleton=true +Mutators=ShowStat,ShowScientific,ShowLogic,ShowConstants,nameConstant,valueConstant +# Inherits=KConfigSkeleton +# IncludeFiles=libkdepim/kpimprefs.h +# MemberVariables=public diff --git a/kcalc/kcalcdisplay.cpp b/kcalc/kcalcdisplay.cpp new file mode 100644 index 0000000..672c363 --- /dev/null +++ b/kcalc/kcalcdisplay.cpp @@ -0,0 +1,608 @@ +/* + $Id$ + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include "kcalc_settings.h" +#include "kcalcdisplay.h" +#include "kcalcdisplay.moc" + + +KCalcDisplay::KCalcDisplay(QWidget *parent, const char *name) + :QLabel(parent,name), _beep(false), _groupdigits(false), _button(0), _lit(false), + _num_base(NB_DECIMAL), _precision(9), + _fixed_precision(-1), _display_amount(0), + selection_timer(new QTimer) +{ + setFrameStyle(QFrame::WinPanel | QFrame::Sunken); + setAlignment(AlignRight | AlignVCenter); + setFocus(); + setFocusPolicy(QWidget::StrongFocus); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, false); + + connect(this, SIGNAL(clicked()), this, SLOT(slotDisplaySelected())); + + connect(selection_timer, SIGNAL(timeout()), + this, SLOT(slotSelectionTimedOut())); + + sendEvent(EventReset); +} + +KCalcDisplay::~KCalcDisplay() +{ + delete selection_timer; +} + +bool KCalcDisplay::sendEvent(Event const event) +{ + switch(event) + { + case EventReset: + _display_amount = 0; + _str_int = "0"; + _str_int_exp = QString::null; + + _eestate = false; + _period = false; + _neg_sign = false; + + updateDisplay(); + + return true; + case EventClear: + return sendEvent(EventReset); + case EventChangeSign: + return changeSign(); + case EventError: + updateDisplay(); + + return true; + default: + return false; + } +} + + +void KCalcDisplay::slotCut(void) +{ + slotCopy(); + sendEvent(EventReset); +} + +void KCalcDisplay::slotCopy(void) +{ + QString txt = QLabel::text(); + if (_num_base == NB_HEX) + txt.prepend( "0x" ); + (QApplication::clipboard())->setText(txt, QClipboard::Clipboard); + (QApplication::clipboard())->setText(txt, QClipboard::Selection); +} + +void KCalcDisplay::slotPaste(bool bClipboard) +{ + QString tmp_str = (QApplication::clipboard())->text(bClipboard ? QClipboard::Clipboard : QClipboard::Selection); + + if (tmp_str.isNull()) + { + if (_beep) KNotifyClient::beep(); + return; + } + + NumBase tmp_num_base = _num_base; + + tmp_str = tmp_str.stripWhiteSpace(); + + if (tmp_str.startsWith("0x", false)) + tmp_num_base = NB_HEX; + + if (tmp_num_base != NB_DECIMAL) + { + bool was_ok; + unsigned long long int tmp_result = tmp_str.toULongLong(& was_ok, tmp_num_base); + + if (!was_ok) + { + setAmount(KNumber::NotDefined); + if(_beep) KNotifyClient::beep(); + return ; + } + + setAmount(KNumber(tmp_result)); + } + else // _num_base == NB_DECIMAL && ! tmp_str.startsWith("0x", false) + { + setAmount(KNumber(tmp_str)); + if (_beep && _display_amount == KNumber::NotDefined) + KNotifyClient::beep(); + } +} + +void KCalcDisplay::slotDisplaySelected(void) +{ + if(_button == LeftButton) { + if(_lit) { + slotCopy(); + selection_timer->start(100); + } else { + selection_timer->stop(); + } + + invertColors(); + } else { + slotPaste(false); // Selection + } +} + +void KCalcDisplay::slotSelectionTimedOut(void) +{ + _lit = false; + invertColors(); + selection_timer->stop(); +} + +void KCalcDisplay::invertColors() +{ + QColor tmp_col(paletteBackgroundColor()); + setPaletteBackgroundColor(paletteForegroundColor()); + setPaletteForegroundColor(tmp_col); +} + + + +void KCalcDisplay::mousePressEvent(QMouseEvent *e) +{ + if(e->button() == LeftButton) { + _lit = !_lit; + _button = LeftButton; + } else { + _button = MidButton; + } + + emit clicked(); +} + +void KCalcDisplay::setPrecision(int precision) +{ + _precision = precision; +} + +void KCalcDisplay::setFixedPrecision(int precision) +{ + if (_fixed_precision > _precision) + _fixed_precision = -1; + else + _fixed_precision = precision; +} + +void KCalcDisplay::setBeep(bool flag) +{ + _beep = flag; +} + +void KCalcDisplay::setGroupDigits(bool flag) +{ + _groupdigits = flag; +} + +KNumber const & KCalcDisplay::getAmount(void) const +{ + return _display_amount; +} + + +bool KCalcDisplay::setAmount(KNumber const & new_amount) +{ + QString display_str; + + _str_int = "0"; + _str_int_exp = QString::null; + _period = false; + _neg_sign = false; + _eestate = false; + + if (_num_base != NB_DECIMAL && new_amount.type() != KNumber::SpecialType) + { + _display_amount = new_amount.integerPart(); + unsigned long long int tmp_workaround = static_cast(_display_amount); + + display_str = QString::number(tmp_workaround, _num_base).upper(); + } + else // _num_base == NB_DECIMAL || new_amount.type() == + // KNumber::SpecialType + { + _display_amount = new_amount; + + display_str = _display_amount.toQString(KCalcSettings::precision(), _fixed_precision); +#if 0 + else if (_display_amount > 1.0e+16) + display_str = QCString().sprintf(PRINT_LONG_BIG, _precision + 1, _display_amount); + else + display_str = QCString().sprintf(PRINT_LONG_BIG, _precision, _display_amount); +#endif + } + + setText(display_str); + return true; + +} + +void KCalcDisplay::setText(QString const &string) +{ + QString localizedString = string; + + // If we aren't in decimal mode, we don't need to modify the string + if (_num_base == NB_DECIMAL && _groupdigits) + // when input ends with "." (because uncomplete), the + // formatNumber-method does not work; fix by hand by + // truncating, formatting and appending again + if (string.endsWith(".")) { + localizedString.truncate(localizedString.length() - 1); + localizedString = KGlobal::locale()->formatNumber(localizedString, false, 0); // Note: rounding happened already above! + localizedString.append(KGlobal::locale()->decimalSymbol()); + } else + localizedString = KGlobal::locale()->formatNumber(string, false, 0); // Note: rounding happened already above! + + QLabel::setText(localizedString); + emit changedText(localizedString); +} + +QString KCalcDisplay::text() const +{ + if (_num_base != NB_DECIMAL) + return QLabel::text(); + QString display_str = _display_amount.toQString(KCalcSettings::precision()); + + return display_str; + // return QCString().sprintf(PRINT_LONG_BIG, 40, _display_amount); +} + +/* change representation of display to new base (i.e. binary, decimal, + octal, hexadecimal). The amount being displayed is changed to this + base, but for now this amount can not be modified anymore (like + being set with "setAmount"). Return value is the new base. */ +int KCalcDisplay::setBase(NumBase new_base) +{ + CALCAMNT tmp_val = static_cast(getAmount()); + + switch(new_base) + { + case NB_HEX: + _num_base = NB_HEX; + _period = false; + break; + case NB_DECIMAL: + _num_base = NB_DECIMAL; + break; + case NB_OCTAL: + _num_base = NB_OCTAL; + _period = false; + break; + case NB_BINARY: + _num_base = NB_BINARY; + _period = false; + break; + default: // we shouldn't ever end up here + _num_base = NB_DECIMAL; + } + + setAmount(static_cast(tmp_val)); + + return _num_base; +} + +void KCalcDisplay::setStatusText(uint i, const QString& text) +{ + if (i < NUM_STATUS_TEXT) + _str_status[i] = text; + update(); +} + +bool KCalcDisplay::updateDisplay(void) +{ + // Put sign in front. + QString tmp_string; + if(_neg_sign == true) + tmp_string = "-" + _str_int; + else + tmp_string = _str_int; + + switch(_num_base) + { + case NB_BINARY: + Q_ASSERT(_period == false && _eestate == false); + setText(tmp_string); + _display_amount = static_cast(STRTOUL(_str_int.latin1(), 0, 2)); + if (_neg_sign) + _display_amount = -_display_amount; + //str_size = cvb(_str_int, boh_work, DSP_SIZE); + break; + + case NB_OCTAL: + Q_ASSERT(_period == false && _eestate == false); + setText(tmp_string); + _display_amount = static_cast(STRTOUL(_str_int.latin1(), 0, 8)); + if (_neg_sign) + _display_amount = -_display_amount; + break; + + case NB_HEX: + Q_ASSERT(_period == false && _eestate == false); + setText(tmp_string); + _display_amount = static_cast(STRTOUL(_str_int.latin1(), 0, 16)); + if (_neg_sign) + _display_amount = -_display_amount; + break; + + case NB_DECIMAL: + if(_eestate == false) + { + setText(tmp_string); + _display_amount = tmp_string; + } + else + { + if(_str_int_exp.isNull()) + { + // add 'e0' to display but not to conversion + _display_amount = tmp_string; + setText(tmp_string + "e0"); + } + else + { + tmp_string += 'e' + _str_int_exp; + setText(tmp_string); + _display_amount = tmp_string; + } + } + break; + + default: + return false; + } + + return true; +} + +void KCalcDisplay::newCharacter(char const new_char) +{ + // test if character is valid + switch(new_char) + { + case 'e': + // EE can be set only once and in decimal mode + if (_num_base != NB_DECIMAL || + _eestate == true) + { + if(_beep) KNotifyClient::beep(); + return; + } + _eestate = true; + break; + + case '.': + // Period can be set only once and only in decimal + // mode, also not in EE-mode + if (_num_base != NB_DECIMAL || + _period == true || + _eestate == true) + { + if(_beep) KNotifyClient::beep(); + return; + } + _period = true; + break; + + case 'F': + case 'E': + case 'D': + case 'C': + case 'B': + case 'A': + if (_num_base == NB_DECIMAL) + { + if(_beep) KNotifyClient::beep(); + return; + } + // no break + case '9': + case '8': + if (_num_base == NB_OCTAL) + { + if(_beep) KNotifyClient::beep(); + return; + } + // no break + case '7': + case '6': + case '5': + case '4': + case '3': + case '2': + if (_num_base == NB_BINARY) + { + if(_beep) KNotifyClient::beep(); + return; + } + // no break + case '1': + case '0': + break; + + default: + if(_beep) KNotifyClient::beep(); + return; + } + + // change exponent or mantissa + if (_eestate) + { + // ignore ',' before 'e'. turn e.g. '123.e' into '123e' + if (new_char == 'e' && _str_int.endsWith( "." )) + { + _str_int.truncate(_str_int.length() - 1); + _period = false; + } + + // 'e' only starts ee_mode, leaves strings unchanged + if (new_char != 'e' && + // do not add '0' if at start of exp + !(_str_int_exp.isNull() && new_char == '0')) + _str_int_exp.append(new_char); + } + else + { + // handle first character + if (_str_int == "0") + { + switch(new_char) + { + case '.': + // display "0." not just "." + _str_int.append(new_char); + break; + case 'e': + // display "0e" not just "e" + // "0e" does not make sense either, but... + _str_int.append(new_char); + break; + default: + // no leading '0's + _str_int[0] = new_char; + } + } + else + _str_int.append(new_char); + } + + updateDisplay(); +} + +void KCalcDisplay::deleteLastDigit(void) +{ + // Only partially implemented !! + if (_eestate) + { + if(_str_int_exp.isNull()) + { + _eestate = false; + } + else + { + int length = _str_int_exp.length(); + if(length > 1) + { + _str_int_exp.truncate(length-1); + } + else + { + _str_int_exp = (char *)0; + } + } + } + else + { + int length = _str_int.length(); + if(length > 1) + { + if (_str_int[length-1] == '.') + _period = false; + _str_int.truncate(length-1); + } + else + { + Q_ASSERT(_period == false); + _str_int[0] = '0'; + } + } + + updateDisplay(); +} + +// change Sign of display. Problem: Only possible here, when in input +// mode. Otherwise return 'false' so that the kcalc_core can handle +// things. +bool KCalcDisplay::changeSign(void) +{ + //stupid way, to see if in input_mode or display_mode + if (_str_int == "0") return false; + + if(_eestate) + { + if(!_str_int_exp.isNull()) + { + if (_str_int_exp[0] != '-') + _str_int_exp.prepend('-'); + else + _str_int_exp.remove('-'); + } + } + else + { + _neg_sign = ! _neg_sign; + } + + updateDisplay(); + + return true; +} + +void KCalcDisplay::drawContents(QPainter *p) +{ + QLabel::drawContents(p); + + // draw the status texts using half of the normal + // font size but not smaller than 7pt + QFont f(font()); + f.setPointSize(QMAX((f.pointSize() / 2), 7)); + p->setFont(f); + QFontMetrics fm(f); + uint w = fm.width("_____"); + uint h = fm.height(); + + for (uint i = 0; i < NUM_STATUS_TEXT; i++) + { + p->drawText(5 + i * w, h, _str_status[i]); + } +} + +// Return the QLabel's normal size hint vertically expanded +// by half the font height to make room for the status texts +QSize KCalcDisplay::sizeHint() const +{ + QFont f(font()); + f.setPointSize(QMAX((f.pointSize() / 2), 7)); + QFontMetrics fm(f); + return QLabel::sizeHint() + QSize(0, fm.height()); +} + diff --git a/kcalc/kcalcdisplay.h b/kcalc/kcalcdisplay.h new file mode 100644 index 0000000..4f72fb7 --- /dev/null +++ b/kcalc/kcalcdisplay.h @@ -0,0 +1,152 @@ +/* + + KCalc + + Copyright (C) Bernd Johannes Wuebben + wuebben@math.cornell.edu + wuebben@kde.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + + +#ifndef _D_KCALCDISPLAY_H_ +#define _D_KCALCDISPLAY_H_ + +#include +#include +#include +#include "knumber.h" +#include "kcalctype.h" + +#if defined HAVE_LONG_DOUBLE && defined HAVE_L_FUNCS + #define PRINT_FLOAT "%.*Lf" + #define PRINT_LONG_BIG "%.*Lg" + #define PRINT_LONG "%Lg" +#else + #define PRINT_FLOAT "%.*f" + #define PRINT_LONG_BIG "%.*g" + #define PRINT_LONG "%g" +#endif + +#ifdef HAVE_LONG_LONG + #define PRINT_OCTAL "%llo" + #define PRINT_HEX "%llX" +#else + #define PRINT_OCTAL "%lo" + #define PRINT_HEX "%lX" +#endif + +#define NUM_STATUS_TEXT 4 + +/* + This class provides a pocket calculator display. The display has + implicitely two major modes: One is for editing and one is purely + for displaying. + + When one uses "setAmount", the given amount is displayed, and the + amount which was possibly typed in before is lost. At the same time + this new value can not be modified. + + On the other hand, "addNewChar" adds a new digit to the amount that + is being typed in. If "setAmount" was used before, the display is + cleared and a new input starts. + + TODO: Check overflows, number of digits and such... +*/ + +enum NumBase { + NB_BINARY = 2, + NB_OCTAL = 8, + NB_DECIMAL = 10, + NB_HEX = 16 +}; + + +class KCalcDisplay : public QLabel +{ +Q_OBJECT + +public: + KCalcDisplay(QWidget *parent=0, const char *name=0); + ~KCalcDisplay(); + +protected: + void mousePressEvent ( QMouseEvent *); + virtual void drawContents(QPainter *p); + +public: + enum Event { + EventReset, // resets display + EventClear, // if no _error reset display + EventError, + EventChangeSign + }; + bool sendEvent(Event const event); + void deleteLastDigit(void); + KNumber const & getAmount(void) const; + void newCharacter(char const new_char); + bool setAmount(KNumber const & new_amount); + int setBase(NumBase new_base); + void setBeep(bool flag); + void setGroupDigits(bool flag); + void setFixedPrecision(int precision); + void setPrecision(int precision); + void setText(QString const &string); + QString text() const; + bool updateDisplay(void); + void setStatusText(uint i, const QString& text); + virtual QSize sizeHint() const; +private: + bool _beep; + bool _groupdigits; + int _button; + bool _lit; + NumBase _num_base; + + int _precision; + int _fixed_precision; // "-1" = no fixed_precision + + KNumber _display_amount; +private: + bool changeSign(void); + void invertColors(void); + + // only used for input of new numbers + bool _eestate; + bool _period; + bool _neg_sign; + QString _str_int; + QString _str_int_exp; + QString _str_status[NUM_STATUS_TEXT]; + + QTimer* selection_timer; + +signals: + void clicked(void); + void changedText(QString const &); + +public slots: + void slotCut(void); + void slotCopy(void); + void slotPaste(bool bClipboard=true); + +private slots: + void slotSelectionTimedOut(void); + void slotDisplaySelected(void); +}; + +#endif // _KCALCDISPLAY_H_ diff --git a/kcalc/kcalcrc.upd b/kcalc/kcalcrc.upd new file mode 100644 index 0000000..463da95 --- /dev/null +++ b/kcalc/kcalcrc.upd @@ -0,0 +1,4 @@ +Id=KDE_3_2_0 +File=kcalcrc +Group=General +Key=style,Statistical diff --git a/kcalc/kcalctype.h b/kcalc/kcalctype.h new file mode 100644 index 0000000..8223e87 --- /dev/null +++ b/kcalc/kcalctype.h @@ -0,0 +1,135 @@ +/* + $Id$ + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifdef HAVE_CONFIG_H + #include "../config.h" +#endif + +#ifndef KCALC_TYPE_H +#define KCALC_TYPE_H + +#include +#include +#include + +#if defined(HAVE_LONG_DOUBLE) && defined(HAVE_L_FUNCS) +/* should be detected by autoconf and defined in config.h + Be carefull when modifying these lines. HAVE_LONG_DOUBLE + is used all over kcalc's sources to determine whether + long double of double is the fundamental data type for kcalc*/ + + + + typedef long double CALCAMNT; +#else + typedef double CALCAMNT; +#endif + + + +#if defined(HAVE_LONG_DOUBLE) && defined(HAVE_L_FUNCS) + #define MODF(X,Y) modfl(X,Y) + #define SIN(X) sinl(X) + #define ASIN(X) asinl(X) + #define SINH(X) sinhl(X) + #define ASINH(X) asinhl(X) + #define COS(X) cosl(X) + #define COSH(X) coshl(X) + #define ACOS(X) acosl(X) + #define ACOSH(X) acoshl(X) + #define TAN(X) tanl(X) + #define TANH(X) tanhl(X) + #define ATAN(X) atanl(X) + #define ATANH(X) atanhl(X) + #define EXP(X) expl(X) + #define POW(X,Y) powl(X,Y) + #define LN(X) logl(X) + #define LOG_TEN(X) log10l(X) + #define SQRT(X) sqrtl(X) + #define CBRT(X) cbrtl(X) + #define ISINF(X) isinfl(X) + #define STRTOD(X,Y) strtold(X,Y) + #define ROUND(X) roundl(X) + #define CALCAMNT_EPSILON LDBL_EPSILON +#else + #define MODF(X,Y) modf(X,Y) + #define SIN(X) sin(X) + #define ASIN(X) asin(X) + #define SINH(X) sinh(X) + #define ASINH(X) asinh(X) + #define COS(X) cos(X) + #define COSH(X) cosh(X) + #define ACOS(X) acos(X) + #define ACOSH(X) acosh(X) + #define TAN(X) tan(X) + #define TANH(X) tanh(X) + #define ATAN(X) atan(X) + #define ATANH(X) atanh(X) + #define EXP(X) exp(X) + #define POW(X,Y) pow(X,Y) + #define LN(X) log(X) + #define LOG_TEN(X) log10(X) + #define SQRT(X) sqrt(X) + #define CBRT(X) cbrt(X) + #define ISINF(X) isinf(X) + #define STRTOD(X,Y) strtod(X,Y) + #define ROUND(X) round(X) + #define CALCAMNT_EPSILON DBL_EPSILON +#endif + +#if !defined(HAVE_FUNC_ROUND) && !defined(HAVE_FUNC_ROUNDL) + #undef ROUND + #define ROUND(X) rint(X) +#endif + +#undef HAVE_LONG_LONG +#if defined(LLONG_MAX) && defined(HAVE_LONG_DOUBLE) +#define KCALC_LONG_MIN LLONG_MIN +#define KCALC_LONG_MAX LLONG_MAX +#define KCALC_ULONG_MAX ULLONG_MAX +#define KCALC_LONG long long +#define HAVE_LONG_LONG +#define STRTOUL strtoull +#else +#if defined(LONG_LONG_MAX) && defined(HAVE_LONG_DOUBLE) +#define KCALC_LONG_MIN LONG_LONG_MIN +#define KCALC_LONG_MAX LONG_LONG_MAX +#define KCALC_ULONG_MAX ULONG_LONG_MAX +#define KCALC_LONG long long +#define HAVE_LONG_LONG +#ifdef _HPUX_SOURCE +#define STRTOUL strtoul +#else +#define STRTOUL strtoull +#endif +#else +#define KCALC_LONG_MIN LONG_MIN +#define KCALC_LONG_MAX LONG_MAX +#define KCALC_ULONG_MAX ULONG_MAX +#define KCALC_LONG long +#define STRTOUL strtoul +#endif +#endif +#endif diff --git a/kcalc/kcalcui.rc b/kcalc/kcalcui.rc new file mode 100644 index 0000000..e79c350 --- /dev/null +++ b/kcalc/kcalcui.rc @@ -0,0 +1,17 @@ + + + + &Settings + + + + + + + + + + + + + diff --git a/kcalc/knumber/Makefile.am b/kcalc/knumber/Makefile.am new file mode 100644 index 0000000..6e5673b --- /dev/null +++ b/kcalc/knumber/Makefile.am @@ -0,0 +1,16 @@ +AM_CPPFLAGS=-D_GNU_SOURCE -D_ISOC99_SOURCE $(all_includes) + +SUBDIRS = tests + +bin_PROGRAMS = +lib_LTLIBRARIES = +noinst_LTLIBRARIES = libknumber.la + +libknumber_la_SOURCES = knumber.cpp knumber_priv.cpp +libknumber_la_LIBADD = $(LIBGMP) -lm + +METASOURCES = AUTO + +noinst_HEADERS = knumber.h knumber_priv.h + +include ../../admin/Doxyfile.am diff --git a/kcalc/knumber/configure.in.in b/kcalc/knumber/configure.in.in new file mode 100644 index 0000000..8ef670b --- /dev/null +++ b/kcalc/knumber/configure.in.in @@ -0,0 +1,73 @@ +AC_DEFUN([KDE_C_LONG_DOUBLE], +[ + AC_CACHE_CHECK(for long double, ac_cv_c_long_double, + [ + ac_save_LIBS="$LIBS" + LIBS="-lm $LIBS" + AC_TRY_RUN( + [ +#define _ISOC99_SOURCE 1 +#define _GNU_SOURCE 1 +#include +#include +#include +#include + +int main() { +/* The Stardent Vistra knows sizeof(long double), but does not support it. */ +long double foo = 1.0; +char buffer[10]; +/* On Ultrix 4.3 cc, long double is 4 and double is 8. */ +int result = (sizeof(long double) <= sizeof(double)); +/* the following is needed for a broken printf in glibc2 */ +if (!result) { + foo = foo * 3; + sprintf(buffer,"%0.0Lf",foo); + result = strcmp(buffer, "3"); +/* and now something mean ;-) */ + foo = powl(fabsl(foo), 1); +} +exit(result); } + ], + ac_cv_c_long_double=yes, ac_cv_c_long_double=no, + ac_cv_c_long_double=no + ) + LIBS="$ac_save_LIBS" + ]) + if test $ac_cv_c_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have support for long double in printf]) + fi +]) +KDE_C_LONG_DOUBLE + +have_l_funcs=yes +AC_CHECK_LIB(m, sqrtl,,have_l_funcs=no) + +if test "xyes" = "x$have_l_funcs" ; then + AC_DEFINE(HAVE_L_FUNCS,1,[Define if you have *l math functions (absl, ...)]) +fi + +LIBGMP= +KDE_CHECK_HEADER([gmp.h], [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + kde_save_LIBS=$LIBS + LIBS="$all_libraries -lgmp" + AC_TRY_LINK(dnl + [ + #include + ], + [ + mpz_t _mpz; + mpz_init_set_si(_mpz, 0); + ], + [LIBGMP="-lgmp"], + [ + DO_NOT_COMPILE="$DO_NOT_COMPILE kcalc" + ]) + LIBS=$kde_save_LIBS + AC_LANG_RESTORE + +]) +AC_SUBST(LIBGMP) diff --git a/kcalc/knumber/knumber.cpp b/kcalc/knumber/knumber.cpp new file mode 100644 index 0000000..d282b26 --- /dev/null +++ b/kcalc/knumber/knumber.cpp @@ -0,0 +1,693 @@ +// -*- c-basic-offset: 2 -*- +/* This file is part of the KDE libraries + Copyright (c) 2005 Klaus Niederkrueger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include + +#include + +#include +#include + +#include "knumber.h" + +KNumber const KNumber::Zero(0); +KNumber const KNumber::One(1); +KNumber const KNumber::MinusOne(-1); +KNumber const KNumber::Pi("3.141592653589793238462643383279502884197169" + "39937510582097494459230781640628620899862803" + "4825342117068"); +KNumber const KNumber::Euler("2.718281828459045235360287471352662497757" + "24709369995957496696762772407663035354759" + "4571382178525166427"); +KNumber const KNumber::NotDefined("nan"); + +bool KNumber::_float_output = false; +bool KNumber::_fraction_input = false; +bool KNumber::_splitoffinteger_output = false; + +KNumber::KNumber(signed int num) +{ + _num = new _knuminteger(num); +} + +KNumber::KNumber(unsigned int num) +{ + _num = new _knuminteger(num); +} + +KNumber::KNumber(signed long int num) +{ + _num = new _knuminteger(num); +} + +KNumber::KNumber(unsigned long int num) +{ + _num = new _knuminteger(num); +} + +KNumber::KNumber(unsigned long long int num) +{ + _num = new _knuminteger(num); +} + +KNumber::KNumber(double num) +{ + if ( isinf(num) ) _num = new _knumerror( _knumber::Infinity ); + else if ( isnan(num) ) _num = new _knumerror( _knumber::UndefinedNumber ); + else _num = new _knumfloat(num); + +} + +KNumber::KNumber(KNumber const & num) +{ + switch(num.type()) { + case SpecialType: + _num = new _knumerror(*(num._num)); + return; + case IntegerType: + _num = new _knuminteger(*(num._num)); + return; + case FractionType: + _num = new _knumfraction(*(num._num)); + return; + case FloatType: + _num = new _knumfloat(*(num._num)); + return; + }; +} + + +KNumber::KNumber(QString const & num) +{ + if (QRegExp("^(inf|-inf|nan)$").exactMatch(num)) + _num = new _knumerror(num); + else if (QRegExp("^[+-]?\\d+$").exactMatch(num)) + _num = new _knuminteger(num); + else if (QRegExp("^[+-]?\\d+/\\d+$").exactMatch(num)) { + _num = new _knumfraction(num); + simplifyRational(); + } + else if (QRegExp("^[+-]?\\d+(\\.\\d*)?(e[+-]?\\d+)?$").exactMatch(num)) + if (_fraction_input == true) { + _num = new _knumfraction(num); + simplifyRational(); + } else + _num = new _knumfloat(num); + else + _num = new _knumerror("nan"); +} + +KNumber::NumType KNumber::type(void) const +{ + if(dynamic_cast<_knumerror *>(_num)) + return SpecialType; + if(dynamic_cast<_knuminteger *>(_num)) + return IntegerType; + if(dynamic_cast<_knumfraction *>(_num)) + return FractionType; + if(dynamic_cast<_knumfloat *>(_num)) + return FloatType; + + return SpecialType; +} + +// This method converts a fraction to an integer, whenever possible, +// i.e. 5/1 --> 5 +// This method should be called, whenever such a inproper fraction can occur, +// e.g. when adding 4/3 + 2/3.... +void KNumber::simplifyRational(void) +{ + if (type() != FractionType) + return; + + _knumfraction *tmp_num = dynamic_cast<_knumfraction *>(_num); + + if (tmp_num->isInteger()) { + _knumber *tmp_num2 = tmp_num->intPart(); + delete tmp_num; + _num = tmp_num2; + } + +} + + +KNumber const & KNumber::operator=(KNumber const & num) +{ + if (this == & num) + return *this; + + delete _num; + + switch(num.type()) { + case SpecialType: + _num = new _knumerror(); + break; + case IntegerType: + _num = new _knuminteger(); + break; + case FractionType: + _num = new _knumfraction(); + break; + case FloatType: + _num = new _knumfloat(); + break; + }; + + _num->copy(*(num._num)); + + return *this; +} + +KNumber & KNumber::operator +=(KNumber const &arg) +{ + KNumber tmp_num = *this + arg; + + delete _num; + + switch(tmp_num.type()) { + case SpecialType: + _num = new _knumerror(); + break; + case IntegerType: + _num = new _knuminteger(); + break; + case FractionType: + _num = new _knumfraction(); + break; + case FloatType: + _num = new _knumfloat(); + break; + }; + + _num->copy(*(tmp_num._num)); + + return *this; +} + +KNumber & KNumber::operator -=(KNumber const &arg) +{ + KNumber tmp_num = *this - arg; + + delete _num; + + switch(tmp_num.type()) { + case SpecialType: + _num = new _knumerror(); + break; + case IntegerType: + _num = new _knuminteger(); + break; + case FractionType: + _num = new _knumfraction(); + break; + case FloatType: + _num = new _knumfloat(); + break; + }; + + _num->copy(*(tmp_num._num)); + + return *this; +} + +// increase the digit at 'position' by one +static void _inc_by_one(QString &str, int position) +{ + for (int i = position; i >= 0; i--) + { + char last_char = str[i].latin1(); + switch(last_char) + { + case '0': + str[i] = '1'; + break; + case '1': + str[i] = '2'; + break; + case '2': + str[i] = '3'; + break; + case '3': + str[i] = '4'; + break; + case '4': + str[i] = '5'; + break; + case '5': + str[i] = '6'; + break; + case '6': + str[i] = '7'; + break; + case '7': + str[i] = '8'; + break; + case '8': + str[i] = '9'; + break; + case '9': + str[i] = '0'; + if (i == 0) str.prepend('1'); + continue; + case '.': + continue; + } + break; + } +} + +// Cut off if more digits in fractional part than 'precision' +static void _round(QString &str, int precision) +{ + int decimalSymbolPos = str.find('.'); + + if (decimalSymbolPos == -1) + if (precision == 0) return; + else if (precision > 0) // add dot if missing (and needed) + { + str.append('.'); + decimalSymbolPos = str.length() - 1; + } + + // fill up with more than enough zeroes (in case fractional part too short) + str.append(QString().fill('0', precision)); + + // Now decide whether to round up or down + char last_char = str[decimalSymbolPos + precision + 1].latin1(); + switch (last_char) + { + case '0': + case '1': + case '2': + case '3': + case '4': + // nothing to do, rounding down + break; + case '5': + case '6': + case '7': + case '8': + case '9': + // rounding up + _inc_by_one(str, decimalSymbolPos + precision); + break; + default: + break; + } + + decimalSymbolPos = str.find('.'); + str.truncate(decimalSymbolPos + precision + 1); + + // if precision == 0 delete also '.' + if (precision == 0) str = str.section('.', 0, 0); +} + +static QString roundNumber(const QString &numStr, int precision) +{ + QString tmpString = numStr; + if (precision < 0 || + ! QRegExp("^[+-]?\\d+(\\.\\d+)*(e[+-]?\\d+)?$").exactMatch(tmpString)) + return numStr; + + + // Skip the sign (for now) + bool neg = (tmpString[0] == '-'); + if (neg || tmpString[0] == '+') tmpString.remove(0, 1); + + + // Split off exponential part (including 'e'-symbol) + QString mantString = tmpString.section('e', 0, 0, + QString::SectionCaseInsensitiveSeps); + QString expString = tmpString.section('e', 1, 1, + QString::SectionCaseInsensitiveSeps | + QString::SectionIncludeLeadingSep); + if (expString.length() == 1) expString = QString(); + + + _round(mantString, precision); + + if(neg) mantString.prepend('-'); + + return mantString + expString; +} + + +QString const KNumber::toQString(int width, int prec) const +{ + QString tmp_str; + + if (*this == Zero) // important to avoid infinite loops below + return "0"; + switch (type()) { + case IntegerType: + if (width > 0) { //result needs to be cut-off + bool tmp_bool = _fraction_input; // stupid work-around + _fraction_input = false; + tmp_str = (KNumber("1.0")*(*this)).toQString(width, -1); + _fraction_input = tmp_bool; + } else + tmp_str = QString(_num->ascii()); + break; + case FractionType: + if (_float_output) { + bool tmp_bool = _fraction_input; // stupid work-around + _fraction_input = false; + tmp_str = (KNumber("1.0")*(*this)).toQString(width, -1); + _fraction_input = tmp_bool; + } else { // _float_output == false + if(_splitoffinteger_output) { + // split off integer part + KNumber int_part = this->integerPart(); + if (int_part == Zero) + tmp_str = QString(_num->ascii()); + else if (int_part < Zero) + tmp_str = int_part.toQString() + " " + (int_part - *this)._num->ascii(); + else + tmp_str = int_part.toQString() + " " + (*this - int_part)._num->ascii(); + } else + tmp_str = QString(_num->ascii()); + + if (width > 0 && tmp_str.length() > width) { + //result needs to be cut-off + bool tmp_bool = _fraction_input; // stupid work-around + _fraction_input = false; + tmp_str = (KNumber("1.0")*(*this)).toQString(width, -1); + _fraction_input = tmp_bool; + } + } + + break; + case FloatType: + if (width > 0) + tmp_str = QString(_num->ascii(width)); + else + // rough estimate for maximal decimal precision (10^3 = 2^10) + tmp_str = QString(_num->ascii(3*mpf_get_default_prec()/10)); + break; + default: + return QString(_num->ascii()); + } + + if (prec >= 0) + return roundNumber(tmp_str, prec); + else + return tmp_str; +} + +void KNumber::setDefaultFloatOutput(bool flag) +{ + _float_output = flag; +} + +void KNumber::setDefaultFractionalInput(bool flag) +{ + _fraction_input = flag; +} + +void KNumber::setSplitoffIntegerForFractionOutput(bool flag) +{ + _splitoffinteger_output = flag; +} + +void KNumber::setDefaultFloatPrecision(unsigned int prec) +{ + // Need to transform decimal digits into binary digits + unsigned long int bin_prec = static_cast + (double(prec) * M_LN10 / M_LN2 + 1); + + mpf_set_default_prec(bin_prec); +} + +KNumber const KNumber::abs(void) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->abs(); + + return tmp_num; +} + +KNumber const KNumber::cbrt(void) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->cbrt(); + + return tmp_num; +} + +KNumber const KNumber::sqrt(void) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->sqrt(); + + return tmp_num; +} + +KNumber const KNumber::integerPart(void) const +{ + KNumber tmp_num; + delete tmp_num._num; + tmp_num._num = _num->intPart(); + + return tmp_num; +} + +KNumber const KNumber::power(KNumber const &exp) const +{ + if (*this == Zero) { + if(exp == Zero) + return KNumber("nan"); // 0^0 not defined + else if (exp < Zero) + return KNumber("inf"); + else + return KNumber(0); + } + + if (exp == Zero) { + if (*this != Zero) + return One; + else + return KNumber("nan"); + } + else if (exp < Zero) { + KNumber tmp_num; + KNumber tmp_num2 = -exp; + delete tmp_num._num; + tmp_num._num = _num->power(*(tmp_num2._num)); + + return One/tmp_num; + } + else { + KNumber tmp_num; + delete tmp_num._num; + tmp_num._num = _num->power(*(exp._num)); + + return tmp_num; + } + +} + +KNumber const KNumber::operator-(void) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->change_sign(); + + return tmp_num; +} + +KNumber const KNumber::operator+(KNumber const & arg2) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->add(*arg2._num); + + tmp_num.simplifyRational(); + + return tmp_num; +} + +KNumber const KNumber::operator-(KNumber const & arg2) const +{ + return *this + (-arg2); +} + +KNumber const KNumber::operator*(KNumber const & arg2) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->multiply(*arg2._num); + + tmp_num.simplifyRational(); + + return tmp_num; +} + +KNumber const KNumber::operator/(KNumber const & arg2) const +{ + KNumber tmp_num; + delete tmp_num._num; + + tmp_num._num = _num->divide(*arg2._num); + + tmp_num.simplifyRational(); + + return tmp_num; +} + + +KNumber const KNumber::operator%(KNumber const & arg2) const +{ + if (type() != IntegerType || arg2.type() != IntegerType) + return Zero; + + KNumber tmp_num; + delete tmp_num._num; + + _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num); + _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num); + + tmp_num._num = tmp_arg1->mod(*tmp_arg2); + + return tmp_num; +} + +KNumber const KNumber::operator&(KNumber const & arg2) const +{ + if (type() != IntegerType || arg2.type() != IntegerType) + return Zero; + + KNumber tmp_num; + delete tmp_num._num; + + _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num); + _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num); + + tmp_num._num = tmp_arg1->intAnd(*tmp_arg2); + + return tmp_num; + +} + +KNumber const KNumber::operator|(KNumber const & arg2) const +{ + if (type() != IntegerType || arg2.type() != IntegerType) + return Zero; + + KNumber tmp_num; + delete tmp_num._num; + + _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num); + _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num); + + tmp_num._num = tmp_arg1->intOr(*tmp_arg2); + + return tmp_num; +} + + +KNumber const KNumber::operator<<(KNumber const & arg2) const +{ + if (type() != IntegerType || arg2.type() != IntegerType) + return KNumber("nan"); + + _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num); + _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(arg2._num); + + KNumber tmp_num; + delete tmp_num._num; + tmp_num._num = tmp_arg1->shift(*tmp_arg2); + + return tmp_num; +} + +KNumber const KNumber::operator>>(KNumber const & arg2) const +{ + if (type() != IntegerType || arg2.type() != IntegerType) + return KNumber("nan"); + + KNumber tmp_num = -arg2; + + _knuminteger const *tmp_arg1 = dynamic_cast<_knuminteger const *>(_num); + _knuminteger const *tmp_arg2 = dynamic_cast<_knuminteger const *>(tmp_num._num); + + KNumber tmp_num2; + delete tmp_num2._num; + tmp_num2._num = tmp_arg1->shift(*tmp_arg2); + + return tmp_num2; +} + + + +KNumber::operator bool(void) const +{ + if (*this == Zero) + return false; + return true; +} + +KNumber::operator signed long int(void) const +{ + return static_cast(*_num); +} + +KNumber::operator unsigned long int(void) const +{ + return static_cast(*_num); +} + +KNumber::operator unsigned long long int(void) const +{ +#if SIZEOF_UNSIGNED_LONG == 8 + return static_cast(*this); +#elif SIZEOF_UNSIGNED_LONG == 4 + KNumber tmp_num1 = this->abs().integerPart(); + unsigned long long int tmp_num2 = static_cast(tmp_num1) + + (static_cast( + static_cast(tmp_num1 >> KNumber("32"))) << 32) ; + +#warning the cast operator from KNumber to unsigned long long int is probably buggy, when a sign is involved + if (*this > KNumber(0)) + return tmp_num2; + else + return static_cast (- static_cast(tmp_num2)); +#else +#error "SIZEOF_UNSIGNED_LONG is a unhandled case" +#endif +} + +KNumber::operator double(void) const +{ + return static_cast(*_num); +} + +int const KNumber::compare(KNumber const & arg2) const +{ + return _num->compare(*arg2._num); +} diff --git a/kcalc/knumber/knumber.h b/kcalc/knumber/knumber.h new file mode 100644 index 0000000..489a579 --- /dev/null +++ b/kcalc/knumber/knumber.h @@ -0,0 +1,289 @@ +// -*- c-basic-offset: 2 -*- +/* This file is part of the KDE libraries + Copyright (C) 2005 Klaus Niederkrueger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef _KNUMBER_H +#define _KNUMBER_H + +#include + +#include "knumber_priv.h" + +class QString; + +/** + * + * @short Class that provides arbitrary precision numbers + * + * KNumber provides access to arbitrary precision numbers from within + * KDE. + * + * KNumber is based on the GMP (GNU Multiprecision) library and + * provides transparent support to integer, fractional and floating + * point number. It contains rudimentary error handling, and also + * includes methods for converting the numbers to QStrings for + * output, and to read QStrings to obtain a KNumber. + * + * The different types of numbers that can be represented by objects + * of this class will be described below: + * + * @li @p NumType::SpecialType - This type represents an error that + * has occurred, e.g. trying to divide 1 by 0 gives an object that + * represents infinity. + * + * @li @p NumType::IntegerType - The number is an integer. It can be + * arbitrarily large (restricted by the memory of the system). + * + * @li @p NumType::FractionType - A fraction is a number of the form + * denominator divided by nominator, where both denominator and + * nominator are integers of arbitrary size. + * + * @li @p NumType::FloatType - The number is of floating point + * type. These numbers are usually rounded, so that they do not + * represent precise values. + * + * + * @author Klaus Niederkrueger + */ +class KDE_EXPORT KNumber +{ + public: + static KNumber const Zero; + static KNumber const One; + static KNumber const MinusOne; + static KNumber const Pi; + static KNumber const Euler; + static KNumber const NotDefined; + + /** + * KNumber tries to provide transparent access to the following type + * of numbers: + * + * @li @p NumType::SpecialType - Some type of error has occurred, + * further inspection with @p KNumber::ErrorType + * + * @li @p NumType::IntegerType - the number is an integer + * + * @li @p NumType::FractionType - the number is a fraction + * + * @li @p NumType::FloatType - the number is of floating point type + * + */ + enum NumType {SpecialType, IntegerType, FractionType, FloatType}; + + /** + * A KNumber that represents an error, i.e. that is of type @p + * NumType::SpecialType can further distinguished: + * + * @li @p ErrorType::UndefinedNumber - This is e.g. the result of + * taking the square root of a negative number or computing + * \f$ \infty - \infty \f$. + * + * @li @p ErrorType::Infinity - Such a number can be e.g. obtained + * by dividing 1 by 0. Some further calculations are still allowed, + * e.g. \f$ \infty + 5 \f$ still gives \f$\infty\f$. + * + * @li @p ErrorType::MinusInfinity - MinusInfinity behaves similarly + * to infinity above. It can be obtained by changing the sign of + * infinity. + * + */ + enum ErrorType {UndefinedNumber, Infinity, MinusInfinity}; + + KNumber(signed int num = 0); + KNumber(unsigned int num); + KNumber(signed long int num); + KNumber(unsigned long int num); + KNumber(unsigned long long int num); + + KNumber(double num); + + KNumber(KNumber const & num); + + KNumber(QString const & num); + + ~KNumber() + { + delete _num; + } + + KNumber const & operator=(KNumber const & num); + + /** + * Returns the type of the number, as explained in @p KNumber::NumType. + */ + NumType type(void) const; + + /** + * Set whether the output of numbers (with KNumber::toQString) + * should happen as floating point numbers or not. This method has + * in fact only an effect on numbers of type @p + * NumType::FractionType, which can be either displayed as fractions + * or in decimal notation. + * + * The default behavior is not to display fractions in floating + * point notation. + */ + static void setDefaultFloatOutput(bool flag); + + /** + * Set whether a number constructed from a QString should be + * initialized as a fraction or as a float, e.g. "1.01" would be + * treated as 101/100, if this flag is set to true. + * + * The default setting is false. + */ + static void setDefaultFractionalInput(bool flag); + + /** + * Set the default precision to be *at least* @p prec (decimal) + * digits. All subsequent initialized floats will use at least this + * precision, but previously initialized variables are unaffected. + */ + static void setDefaultFloatPrecision(unsigned int prec); + + /** + * What a terrible method name!! When displaying a fraction, the + * default mode gives @p "nomin/denom". With this method one can + * choose to display a fraction as @p "integer nomin/denom". + * + * Examples: Default representation mode is 47/17, but if @p flag is + * @p true, then the result is 2 13/17. + */ + static void setSplitoffIntegerForFractionOutput(bool flag); + + /** + * Return a QString representing the KNumber. + * + * @param width This number specifies the maximal length of the + * output, before the method switches to exponential notation and + * does rounding. For negative numbers, this option is ignored. + * + * @param prec This parameter controls the number of digits + * following the decimal point. For negative numbers, this option + * is ignored. + * + */ + QString const toQString(int width = -1, int prec = -1) const; + + /** + * Compute the absolute value, i.e. @p x.abs() returns the value + * + * \f[ \left\{\begin{array}{cl} x, & x \ge 0 \\ -x, & x < + * 0\end{array}\right.\f] + * This method works for \f$ x = \infty \f$ and \f$ x = -\infty \f$. + */ + KNumber const abs(void) const; + + /** + * Compute the square root. If \f$ x < 0 \f$ (including \f$ + * x=-\infty \f$), then @p x.sqrt() returns @p + * ErrorType::UndefinedNumber. + * + * If @p x is an integer or a fraction, then @p x.sqrt() tries to + * compute the exact square root. If the square root is not a + * fraction, then a float with the default precision is returned. + * + * This method works for \f$ x = \infty \f$ giving \f$ \infty \f$. + */ + KNumber const sqrt(void) const; + + /** + * Compute the cube root. + * + * If @p x is an integer or a fraction, then @p x.cbrt() tries to + * compute the exact cube root. If the cube root is not a fraction, + * then a float is returned, but + * + * WARNING: A float cube root is computed as a standard @p double + * that is later transformed back into a @p KNumber. + * + * This method works for \f$ x = \infty \f$ giving \f$ \infty \f$, + * and for \f$ x = -\infty \f$ giving \f$ -\infty \f$. + */ + KNumber const cbrt(void) const; + + /** + * Truncates a @p KNumber to its integer type returning a number of + * type @p NumType::IntegerType. + * + * If \f$ x = \pm\infty \f$, integerPart leaves the value unchanged, + * i.e. it returns \f$ \pm\infty \f$. + */ + KNumber const integerPart(void) const; + + KNumber const power(KNumber const &exp) const; + + KNumber const operator+(KNumber const & arg2) const; + KNumber const operator -(void) const; + KNumber const operator-(KNumber const & arg2) const; + KNumber const operator*(KNumber const & arg2) const; + KNumber const operator/(KNumber const & arg2) const; + KNumber const operator%(KNumber const & arg2) const; + + KNumber const operator&(KNumber const & arg2) const; + KNumber const operator|(KNumber const & arg2) const; + KNumber const operator<<(KNumber const & arg2) const; + KNumber const operator>>(KNumber const & arg2) const; + + operator bool(void) const; + operator signed long int(void) const; + operator unsigned long int(void) const; + operator unsigned long long int(void) const; + operator double(void) const; + + bool const operator==(KNumber const & arg2) const + { return (compare(arg2) == 0); } + + bool const operator!=(KNumber const & arg2) const + { return (compare(arg2) != 0); } + + bool const operator>(KNumber const & arg2) const + { return (compare(arg2) > 0); } + + bool const operator<(KNumber const & arg2) const + { return (compare(arg2) < 0); } + + bool const operator>=(KNumber const & arg2) const + { return (compare(arg2) >= 0); } + + bool const operator<=(KNumber const & arg2) const + { return (compare(arg2) <= 0); } + + KNumber & operator +=(KNumber const &arg); + KNumber & operator -=(KNumber const &arg); + + + //KNumber const toFloat(void) const; + + + + + private: + void simplifyRational(void); + int const compare(KNumber const & arg2) const; + + _knumber *_num; + static bool _float_output; + static bool _fraction_input; + static bool _splitoffinteger_output; +}; + + + +#endif // _KNUMBER_H diff --git a/kcalc/knumber/knumber_priv.cpp b/kcalc/knumber/knumber_priv.cpp new file mode 100644 index 0000000..1326d44 --- /dev/null +++ b/kcalc/knumber/knumber_priv.cpp @@ -0,0 +1,1083 @@ +/* This file is part of the KDE libraries + Copyright (c) 2005 Klaus Niederkrueger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +#include "knumber_priv.h" + +_knumerror::_knumerror(_knumber const & num) +{ + switch(num.type()) { + case SpecialType: + _error = dynamic_cast<_knumerror const &>(num)._error; + break; + case IntegerType: + case FractionType: + case FloatType: + // What should I do here? + break; + } +} + + + +_knuminteger::_knuminteger(unsigned long long int num) +{ + mpz_init(_mpz); +#if SIZEOF_UNSIGNED_LONG == 8 + mpz_init_set_ui(_mpz, static_cast(num)); +#elif SIZEOF_UNSIGNED_LONG == 4 + mpz_set_ui(_mpz, static_cast(num >> 32)); + mpz_mul_2exp(_mpz, _mpz, 32); + mpz_add_ui(_mpz, _mpz, static_cast(num)); +#else +#error "SIZEOF_UNSIGNED_LONG is a unhandled case" +#endif +} + + +_knuminteger::_knuminteger(_knumber const & num) +{ + mpz_init(_mpz); + + switch(num.type()) { + case IntegerType: + mpz_set(_mpz, dynamic_cast<_knuminteger const &>(num)._mpz); + break; + case FractionType: + case FloatType: + case SpecialType: + // What should I do here? + break; + } +} + +_knumfraction::_knumfraction(_knumber const & num) +{ + mpq_init(_mpq); + + switch(num.type()) { + case IntegerType: + mpq_set_z(_mpq, dynamic_cast<_knuminteger const &>(num)._mpz); + break; + case FractionType: + mpq_set(_mpq, dynamic_cast<_knumfraction const &>(num)._mpq); + break; + case FloatType: + case SpecialType: + // What should I do here? + break; + } +} + +_knumfloat::_knumfloat(_knumber const & num) +{ + mpf_init(_mpf); + + switch(num.type()) { + case IntegerType: + mpf_set_z(_mpf, dynamic_cast<_knuminteger const &>(num)._mpz); + break; + case FractionType: + mpf_set_q(_mpf, dynamic_cast<_knumfraction const &>(num)._mpq); + break; + case FloatType: + mpf_set(_mpf, dynamic_cast<_knumfloat const &>(num)._mpf); + break; + case SpecialType: + // What should I do here? + break; + } +} + + + +_knumerror::_knumerror(QString const & num) +{ + if (num == "nan") + _error = UndefinedNumber; + else if (num == "inf") + _error = Infinity; + else if (num == "-inf") + _error = MinusInfinity; +} + +_knuminteger::_knuminteger(QString const & num) +{ + mpz_init(_mpz); + mpz_set_str(_mpz, num.ascii(), 10); +} + +_knumfraction::_knumfraction(QString const & num) +{ + mpq_init(_mpq); + if (QRegExp("^[+-]?\\d+(\\.\\d*)?(e[+-]?\\d+)?$").exactMatch(num)) { + // my hand-made conversion is terrible + // first me convert the mantissa + unsigned long int digits_after_dot = ((num.section( '.', 1, 1)).section('e', 0, 0)).length(); + QString tmp_num = num.section('e', 0, 0).remove('.'); + mpq_set_str(_mpq, tmp_num.ascii(), 10); + mpz_t tmp_int; + mpz_init(tmp_int); + mpz_ui_pow_ui (tmp_int, 10, digits_after_dot); + mpz_mul(mpq_denref(_mpq), mpq_denref(_mpq), tmp_int); + // now we take care of the exponent + if (! (tmp_num = num.section('e', 1, 1)).isEmpty()) { + long int tmp_exp = tmp_num.toLong(); + if (tmp_exp > 0) { + mpz_ui_pow_ui (tmp_int, 10, + static_cast(tmp_exp)); + mpz_mul(mpq_numref(_mpq), mpq_numref(_mpq), tmp_int); + } else { + mpz_ui_pow_ui (tmp_int, 10, + static_cast(-tmp_exp)); + mpz_mul(mpq_denref(_mpq), mpq_denref(_mpq), tmp_int); + } + } + mpz_clear(tmp_int); + } else + mpq_set_str(_mpq, num.ascii(), 10); + mpq_canonicalize(_mpq); +} + +_knumfloat::_knumfloat(QString const & num) +{ + mpf_init(_mpf); + mpf_set_str(_mpf, num.ascii(), 10); +} + +_knuminteger const & _knuminteger::operator = (_knuminteger const & num) +{ + if (this == &num) + return *this; + + mpz_set(_mpz, num._mpz); + return *this; +} + +QString const _knumerror::ascii(int prec) const +{ + static_cast(prec); + + switch(_error) { + case UndefinedNumber: + return QString("nan"); + case Infinity: + return QString("inf"); + case MinusInfinity: + return QString("-inf"); + default: + return QString::null; + } +} + +QString const _knuminteger::ascii(int prec) const +{ + static_cast(prec); + char *tmp_ptr; + + gmp_asprintf(&tmp_ptr, "%Zd", _mpz); + QString ret_str = tmp_ptr; + + free(tmp_ptr); + return ret_str; +} + +QString const _knumfraction::ascii(int prec) const +{ + static_cast(prec); + char *tmp_ptr = mpq_get_str(0, 10, _mpq); + QString ret_str = tmp_ptr; + + free(tmp_ptr); + + return ret_str; +} + +QString const _knumfloat::ascii(int prec) const +{ + QString ret_str; + char *tmp_ptr; + if (prec > 0) + gmp_asprintf(&tmp_ptr, ("%." + QString().setNum(prec) + "Fg").ascii(), _mpf); + else + gmp_asprintf(&tmp_ptr, "%Fg", _mpf); + + ret_str = tmp_ptr; + + free(tmp_ptr); + + return ret_str; +} + + +bool _knumfraction::isInteger(void) const +{ + if (mpz_cmp_ui(mpq_denref(_mpq), 1) == 0) + return true; + else + return false; +} + + +_knumber * _knumerror::abs(void) const +{ + _knumerror * tmp_num = new _knumerror(*this); + + if(_error == MinusInfinity) tmp_num->_error = Infinity; + + return tmp_num; +} + +_knumber * _knuminteger::abs(void) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_abs(tmp_num->_mpz, _mpz); + + return tmp_num; +} + +_knumber * _knumfraction::abs(void) const +{ + _knumfraction * tmp_num = new _knumfraction(); + + mpq_abs(tmp_num->_mpq, _mpq); + + return tmp_num; +} + +_knumber * _knumfloat::abs(void) const +{ + _knumfloat * tmp_num = new _knumfloat(); + + mpf_abs(tmp_num->_mpf, _mpf); + + return tmp_num; +} + + + +_knumber * _knumerror::intPart(void) const +{ + return new _knumerror(*this); +} + +_knumber * _knuminteger::intPart(void) const +{ + _knuminteger *tmp_num = new _knuminteger(); + mpz_set(tmp_num->_mpz, _mpz); + return tmp_num; +} + +_knumber * _knumfraction::intPart(void) const +{ + _knuminteger *tmp_num = new _knuminteger(); + + mpz_set_q(tmp_num->_mpz, _mpq); + + return tmp_num; +} + +_knumber * _knumfloat::intPart(void) const +{ + _knuminteger *tmp_num = new _knuminteger(); + + mpz_set_f(tmp_num->_mpz, _mpf); + + return tmp_num; +} + + + + +int _knumerror::sign(void) const +{ + switch(_error) { + case Infinity: + return 1; + case MinusInfinity: + return -1; + default: + return 0; + } +} + +int _knuminteger::sign(void) const +{ + return mpz_sgn(_mpz); +} + +int _knumfraction::sign(void) const +{ + return mpq_sgn(_mpq); +} + +int _knumfloat::sign(void) const +{ + return mpf_sgn(_mpf); +} + + + +#warning _cbrt for now this is a stupid work around +static void _cbrt(mpf_t &num) +{ + double tmp_num = cbrt(mpf_get_d(num)); + mpf_init_set_d(num, tmp_num); +} + + +_knumber * _knumerror::cbrt(void) const +{ + // infty ^3 = infty; -infty^3 = -infty + _knumerror *tmp_num = new _knumerror(*this); + + return tmp_num; +} + +_knumber * _knuminteger::cbrt(void) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + if(mpz_root(tmp_num->_mpz, _mpz, 3)) + return tmp_num; // root is perfect + + delete tmp_num; // root was not perfect, result will be float + + _knumfloat * tmp_num2 = new _knumfloat(); + mpf_set_z(tmp_num2->_mpf, _mpz); + + _cbrt(tmp_num2->_mpf); + + return tmp_num2; +} + +_knumber * _knumfraction::cbrt(void) const +{ + _knumfraction * tmp_num = new _knumfraction(); + if (mpz_root(mpq_numref(tmp_num->_mpq), mpq_numref(_mpq), 3) + && mpz_root(mpq_denref(tmp_num->_mpq), mpq_denref(_mpq), 3)) + return tmp_num; // root is perfect + + delete tmp_num; // root was not perfect, result will be float + + _knumfloat * tmp_num2 = new _knumfloat(); + mpf_set_q(tmp_num2->_mpf, _mpq); + + _cbrt(tmp_num2->_mpf); + + return tmp_num2; +} + +_knumber * _knumfloat::cbrt(void) const +{ + _knumfloat * tmp_num = new _knumfloat(*this); + + _cbrt(tmp_num->_mpf); + + return tmp_num; +} + + + + +_knumber * _knumerror::sqrt(void) const +{ + _knumerror *tmp_num = new _knumerror(*this); + + if(_error == MinusInfinity) tmp_num->_error = UndefinedNumber; + + return tmp_num; +} + +_knumber * _knuminteger::sqrt(void) const +{ + if (mpz_sgn(_mpz) < 0) { + _knumerror *tmp_num = new _knumerror(UndefinedNumber); + return tmp_num; + } + if (mpz_perfect_square_p(_mpz)) { + _knuminteger * tmp_num = new _knuminteger(); + + mpz_sqrt(tmp_num->_mpz, _mpz); + + return tmp_num; + } else { + _knumfloat * tmp_num = new _knumfloat(); + mpf_set_z(tmp_num->_mpf, _mpz); + mpf_sqrt(tmp_num->_mpf, tmp_num->_mpf); + + return tmp_num; + } +} + +_knumber * _knumfraction::sqrt(void) const +{ + if (mpq_sgn(_mpq) < 0) { + _knumerror *tmp_num = new _knumerror(UndefinedNumber); + return tmp_num; + } + if (mpz_perfect_square_p(mpq_numref(_mpq)) + && mpz_perfect_square_p(mpq_denref(_mpq))) { + _knumfraction * tmp_num = new _knumfraction(); + mpq_set(tmp_num->_mpq, _mpq); + mpz_sqrt(mpq_numref(tmp_num->_mpq), mpq_numref(tmp_num->_mpq)); + mpz_sqrt(mpq_denref(tmp_num->_mpq), mpq_denref(tmp_num->_mpq)); + + return tmp_num; + } else { + _knumfloat * tmp_num = new _knumfloat(); + mpf_set_q(tmp_num->_mpf, _mpq); + mpf_sqrt(tmp_num->_mpf, tmp_num->_mpf); + + return tmp_num; + } + + _knumfraction * tmp_num = new _knumfraction(); + + return tmp_num; +} + +_knumber * _knumfloat::sqrt(void) const +{ + if (mpf_sgn(_mpf) < 0) { + _knumerror *tmp_num = new _knumerror(UndefinedNumber); + return tmp_num; + } + _knumfloat * tmp_num = new _knumfloat(); + + mpf_sqrt(tmp_num->_mpf, _mpf); + + return tmp_num; +} + + + +_knumber * _knumerror::change_sign(void) const +{ + _knumerror * tmp_num = new _knumerror(); + + if(_error == Infinity) tmp_num->_error = MinusInfinity; + if(_error == MinusInfinity) tmp_num->_error = Infinity; + + return tmp_num; +} + +_knumber * _knuminteger::change_sign(void) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_neg(tmp_num->_mpz, _mpz); + + return tmp_num; +} + +_knumber * _knumfraction::change_sign(void) const +{ + _knumfraction * tmp_num = new _knumfraction(); + + mpq_neg(tmp_num->_mpq, _mpq); + + return tmp_num; +} + +_knumber *_knumfloat::change_sign(void) const +{ + _knumfloat * tmp_num = new _knumfloat(); + + mpf_neg(tmp_num->_mpf, _mpf); + + return tmp_num; +} + + +_knumber * _knumerror::reciprocal(void) const +{ + switch(_error) { + case Infinity: + case MinusInfinity: + return new _knuminteger(0); + case UndefinedNumber: + default: + return new _knumerror(UndefinedNumber); + } +} + +_knumber * _knuminteger::reciprocal(void) const +{ + if(mpz_cmp_si(_mpz, 0) == 0) return new _knumerror(Infinity); + + _knumfraction * tmp_num = new _knumfraction(*this); + + mpq_inv(tmp_num->_mpq, tmp_num->_mpq); + + return tmp_num; +} + +_knumber * _knumfraction::reciprocal() const +{ + if(mpq_cmp_si(_mpq, 0, 1) == 0) return new _knumerror(Infinity); + + _knumfraction * tmp_num = new _knumfraction(); + + mpq_inv(tmp_num->_mpq, _mpq); + + return tmp_num; +} + +_knumber *_knumfloat::reciprocal(void) const +{ + if(mpf_cmp_si(_mpf, 0) == 0) return new _knumerror(Infinity); + + _knumfloat * tmp_num = new _knumfloat(); + + mpf_div(tmp_num->_mpf, _knumfloat("1.0")._mpf, _mpf); + + return tmp_num; +} + + + +_knumber * _knumerror::add(_knumber const & arg2) const +{ + if (arg2.type() != SpecialType) + return new _knumerror(_error); + + _knumerror const & tmp_arg2 = dynamic_cast<_knumerror const &>(arg2); + + if (_error == UndefinedNumber + || tmp_arg2._error == UndefinedNumber + || (_error == Infinity && tmp_arg2._error == MinusInfinity) + || (_error == MinusInfinity && tmp_arg2._error == Infinity) + ) + return new _knumerror(UndefinedNumber); + + return new _knumerror(_error); +} + +_knumber * _knuminteger::add(_knumber const & arg2) const +{ + if (arg2.type() != IntegerType) + return arg2.add(*this); + + _knuminteger * tmp_num = new _knuminteger(); + + mpz_add(tmp_num->_mpz, _mpz, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + + return tmp_num; +} + +_knumber * _knumfraction::add(_knumber const & arg2) const +{ + if (arg2.type() == IntegerType) { + // need to cast arg2 to fraction + _knumfraction tmp_num(arg2); + return tmp_num.add(*this); + } + + + if (arg2.type() == FloatType || arg2.type() == SpecialType) + return arg2.add(*this); + + _knumfraction * tmp_num = new _knumfraction(); + + mpq_add(tmp_num->_mpq, _mpq, + dynamic_cast<_knumfraction const &>(arg2)._mpq); + + return tmp_num; +} + +_knumber *_knumfloat::add(_knumber const & arg2) const +{ + if (arg2.type() == SpecialType) + return arg2.add(*this); + + if (arg2.type() != FloatType) { + // need to cast arg2 to float + _knumfloat tmp_num(arg2); + return tmp_num.add(*this); + } + + _knumfloat * tmp_num = new _knumfloat(); + + mpf_add(tmp_num->_mpf, _mpf, + dynamic_cast<_knumfloat const &>(arg2)._mpf); + + return tmp_num; +} + + +_knumber * _knumerror::multiply(_knumber const & arg2) const +{ + //improve this + switch(arg2.type()) { + case SpecialType: + { + _knumerror const & tmp_arg2 = dynamic_cast<_knumerror const &>(arg2); + if (_error == UndefinedNumber || tmp_arg2._error == UndefinedNumber) + return new _knumerror(UndefinedNumber); + if ( this->sign() * arg2.sign() > 0) + return new _knumerror(Infinity); + else + return new _knumerror(MinusInfinity); + } + case IntegerType: + case FractionType: + case FloatType: + { + int sign_arg2 = arg2.sign(); + if (_error == UndefinedNumber || sign_arg2 == 0) + return new _knumerror(UndefinedNumber); + if ( (_error == Infinity && sign_arg2 > 0) || + (_error == MinusInfinity && sign_arg2 < 0) ) + return new _knumerror(Infinity); + + return new _knumerror(MinusInfinity); + } + } + + return new _knumerror(_error); +} + + +_knumber * _knuminteger::multiply(_knumber const & arg2) const +{ + if (arg2.type() != IntegerType) + return arg2.multiply(*this); + + _knuminteger * tmp_num = new _knuminteger(); + + mpz_mul(tmp_num->_mpz, _mpz, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + + return tmp_num; +} + +_knumber * _knumfraction::multiply(_knumber const & arg2) const +{ + if (arg2.type() == IntegerType) { + // need to cast arg2 to fraction + _knumfraction tmp_num(arg2); + return tmp_num.multiply(*this); + } + + + if (arg2.type() == FloatType || arg2.type() == SpecialType) + return arg2.multiply(*this); + + _knumfraction * tmp_num = new _knumfraction(); + + mpq_mul(tmp_num->_mpq, _mpq, + dynamic_cast<_knumfraction const &>(arg2)._mpq); + + return tmp_num; +} + +_knumber *_knumfloat::multiply(_knumber const & arg2) const +{ + if (arg2.type() == SpecialType) + return arg2.multiply(*this); + if (arg2.type() == IntegerType && + mpz_cmp_si(dynamic_cast<_knuminteger const &>(arg2)._mpz,0) == 0) + // if arg2 == 0 return integer 0!! + return new _knuminteger(0); + + if (arg2.type() != FloatType) { + // need to cast arg2 to float + _knumfloat tmp_num(arg2); + return tmp_num.multiply(*this); + } + + _knumfloat * tmp_num = new _knumfloat(); + + mpf_mul(tmp_num->_mpf, _mpf, + dynamic_cast<_knumfloat const &>(arg2)._mpf); + + return tmp_num; +} + + + + + +_knumber * _knumber::divide(_knumber const & arg2) const +{ + _knumber * tmp_num = arg2.reciprocal(); + _knumber * rslt_num = this->multiply(*tmp_num); + + delete tmp_num; + + return rslt_num; +} + +_knumber *_knumfloat::divide(_knumber const & arg2) const +{ + if(mpf_cmp_si(_mpf, 0) == 0) return new _knumerror(Infinity); + + // automatically casts arg2 to float + _knumfloat * tmp_num = new _knumfloat(arg2); + + mpf_div(tmp_num->_mpf, _mpf, tmp_num->_mpf); + + return tmp_num; +} + + + + +_knumber * _knumerror::power(_knumber const & exponent) const +{ + static_cast(exponent); + return new _knumerror(UndefinedNumber); +} + +_knumber * _knuminteger::power(_knumber const & exponent) const +{ + if (exponent.type() == IntegerType) { + + mpz_t tmp_mpz; + mpz_init_set(tmp_mpz, + dynamic_cast<_knuminteger const &>(exponent)._mpz); + + if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so + // use floats + mpz_clear(tmp_mpz); + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + + unsigned long int tmp_int = mpz_get_ui(tmp_mpz); + mpz_clear(tmp_mpz); + + _knuminteger * tmp_num = new _knuminteger(); + mpz_pow_ui(tmp_num->_mpz, _mpz, tmp_int); + return tmp_num; + } + if (exponent.type() == FractionType) { + if (mpz_sgn(_mpz) < 0) + return new _knumerror(UndefinedNumber); + // GMP only supports few root functions, so we need to convert + // into signed long int + mpz_t tmp_mpz; + mpz_init_set(tmp_mpz, + mpq_denref(dynamic_cast<_knumfraction const &>(exponent)._mpq)); + + if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so + // use floats + mpz_clear(tmp_mpz); + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + + unsigned long int tmp_int = mpz_get_ui(tmp_mpz); + mpz_clear(tmp_mpz); + + // first check if result will be an integer + _knuminteger * tmp_num = new _knuminteger(); + int flag = mpz_root(tmp_num->_mpz, _mpz, tmp_int); + if (flag == 0) { // result is not exact + delete tmp_num; + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + + // result is exact + + mpz_init_set(tmp_mpz, + mpq_numref(dynamic_cast<_knumfraction const &>(exponent)._mpq)); + + if (! mpz_fits_ulong_p(tmp_mpz)) { // conversion wouldn't work, so + // use floats + mpz_clear(tmp_mpz); + // need to cast everything to float + _knumfloat tmp_num1(*this), tmp_num2(exponent); + return tmp_num1.power(tmp_num2); + } + tmp_int = mpz_get_ui(tmp_mpz); + mpz_clear(tmp_mpz); + + mpz_pow_ui(tmp_num->_mpz, tmp_num->_mpz, tmp_int); + + return tmp_num; + } + if (exponent.type() == FloatType) { + // need to cast everything to float + _knumfloat tmp_num(*this); + return tmp_num.power(exponent); + } + + return new _knumerror(Infinity); +} + +_knumber * _knumfraction::power(_knumber const & exponent) const +{ + _knuminteger tmp_num = _knuminteger(); + + mpz_set(tmp_num._mpz, mpq_numref(_mpq)); + _knumber *numer = tmp_num.power(exponent); + + mpz_set(tmp_num._mpz, mpq_denref(_mpq)); + _knumber *denom = tmp_num.power(exponent); + + _knumber *result = numer->divide(*denom); + delete numer; + delete denom; + return result; +} + +_knumber * _knumfloat::power(_knumber const & exponent) const +{ + return new _knumfloat(pow(static_cast(*this), + static_cast(exponent))); +} + + +int _knumerror::compare(_knumber const &arg2) const +{ + if (arg2.type() != SpecialType) { + switch(_error) { + case Infinity: + return 1; + case MinusInfinity: + return -1; + default: + return 1; // Not really o.k., but what should I return + } + } + + switch(_error) { + case Infinity: + if (dynamic_cast<_knumerror const &>(arg2)._error == Infinity) + // Infinity is larger than anything else, but itself + return 0; + return 1; + case MinusInfinity: + if (dynamic_cast<_knumerror const &>(arg2)._error == MinusInfinity) + // MinusInfinity is smaller than anything else, but itself + return 0; + return -1; + default: + if (dynamic_cast<_knumerror const &>(arg2)._error == UndefinedNumber) + // Undefined only equal to itself + return 0; + return -arg2.compare(*this); + } +} + +int _knuminteger::compare(_knumber const &arg2) const +{ + if (arg2.type() != IntegerType) + return - arg2.compare(*this); + + return mpz_cmp(_mpz, dynamic_cast<_knuminteger const &>(arg2)._mpz); +} + +int _knumfraction::compare(_knumber const &arg2) const +{ + if (arg2.type() != FractionType) { + if (arg2.type() == IntegerType) { + mpq_t tmp_frac; + mpq_init(tmp_frac); + mpq_set_z(tmp_frac, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + int cmp_result = mpq_cmp(_mpq, tmp_frac); + mpq_clear(tmp_frac); + return cmp_result; + } else + return - arg2.compare(*this); + } + + return mpq_cmp(_mpq, dynamic_cast<_knumfraction const &>(arg2)._mpq); +} + +int _knumfloat::compare(_knumber const &arg2) const +{ + if (arg2.type() != FloatType) { + mpf_t tmp_float; + if (arg2.type() == IntegerType) { + mpf_init(tmp_float); + mpf_set_z(tmp_float, + dynamic_cast<_knuminteger const &>(arg2)._mpz); + } else if (arg2.type() == FractionType) { + mpf_init(tmp_float); + mpf_set_q(tmp_float, + dynamic_cast<_knumfraction const &>(arg2)._mpq); + } else + return - arg2.compare(*this); + + int cmp_result = mpf_cmp(_mpf, tmp_float); + mpf_clear(tmp_float); + return cmp_result; + } + + return mpf_cmp(_mpf, dynamic_cast<_knumfloat const &>(arg2)._mpf); +} + + + +_knumerror::operator signed long int (void) const +{ + // what would be the correct return values here? + if (_error == Infinity) + return 0; + if (_error == MinusInfinity) + return 0; + else // if (_error == UndefinedNumber) + return 0; +} + +_knumerror::operator unsigned long int (void) const +{ + // what would be the correct return values here? + if (_error == Infinity) + return 0; + if (_error == MinusInfinity) + return 0; + else // if (_error == UndefinedNumber) + return 0; +} + + +_knuminteger::operator signed long int (void) const +{ + return mpz_get_si(_mpz); +} + +_knumfraction::operator signed long int (void) const +{ + return static_cast(mpq_get_d(_mpq)); +} + +_knumfloat::operator signed long int (void) const +{ + return mpf_get_si(_mpf); +} + +_knuminteger::operator unsigned long int (void) const +{ + return mpz_get_ui(_mpz); +} + +_knumfraction::operator unsigned long int (void) const +{ + return static_cast(mpq_get_d(_mpq)); +} + +_knumfloat::operator unsigned long int (void) const +{ + return mpf_get_ui(_mpf); +} + + + +_knumerror::operator double (void) const +{ + if (_error == Infinity) + return INFINITY; + if (_error == MinusInfinity) + return -INFINITY; + else // if (_error == UndefinedNumber) + return NAN; +} + +_knuminteger::operator double (void) const +{ + return mpz_get_d(_mpz); +} + +_knumfraction::operator double (void) const +{ + return mpq_get_d(_mpq); +} + +_knumfloat::operator double (void) const +{ + return mpf_get_d(_mpf); +} + + + + +_knuminteger * _knuminteger::intAnd(_knuminteger const &arg2) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_and(tmp_num->_mpz, _mpz, arg2._mpz); + + return tmp_num; +} + +_knuminteger * _knuminteger::intOr(_knuminteger const &arg2) const +{ + _knuminteger * tmp_num = new _knuminteger(); + + mpz_ior(tmp_num->_mpz, _mpz, arg2._mpz); + + return tmp_num; +} + +_knumber * _knuminteger::mod(_knuminteger const &arg2) const +{ + if(mpz_cmp_si(arg2._mpz, 0) == 0) return new _knumerror(UndefinedNumber); + + _knuminteger * tmp_num = new _knuminteger(); + + mpz_mod(tmp_num->_mpz, _mpz, arg2._mpz); + + return tmp_num; +} + +_knumber * _knuminteger::shift(_knuminteger const &arg2) const +{ + mpz_t tmp_mpz; + + mpz_init_set (tmp_mpz, arg2._mpz); + + if (! mpz_fits_slong_p(tmp_mpz)) { + mpz_clear(tmp_mpz); + return new _knumerror(UndefinedNumber); + } + + signed long int tmp_arg2 = mpz_get_si(tmp_mpz); + mpz_clear(tmp_mpz); + + + _knuminteger * tmp_num = new _knuminteger(); + + if (tmp_arg2 > 0) // left shift + mpz_mul_2exp(tmp_num->_mpz, _mpz, tmp_arg2); + else // right shift + mpz_tdiv_q_2exp(tmp_num->_mpz, _mpz, -tmp_arg2); + + + return tmp_num; +} + diff --git a/kcalc/knumber/knumber_priv.h b/kcalc/knumber/knumber_priv.h new file mode 100644 index 0000000..7dd58a6 --- /dev/null +++ b/kcalc/knumber/knumber_priv.h @@ -0,0 +1,313 @@ +/* This file is part of the KDE libraries + Copyright (C) 2005 Klaus Niederkrueger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef _KNUMBER_PRIV_H +#define _KNUMBER_PRIV_H + +class QString; + +#include +#include + +// work-around for pre-C99-libs +#ifndef INFINITY +#define INFINITY HUGE_VAL +#endif +// this is really ugly +#ifndef NAN +#define NAN (atof("nan")) +#endif + +class _knumber +{ + public: + enum NumType {SpecialType, IntegerType, FractionType, FloatType}; + enum ErrorType {UndefinedNumber, Infinity, MinusInfinity}; + + _knumber() {} + + virtual ~_knumber() {} + + virtual void copy(_knumber const & num) = 0; + + virtual NumType type(void) const = 0; + + virtual QString const ascii(int prec = -1) const = 0; + + virtual _knumber * abs(void) const = 0; + virtual _knumber * intPart(void) const = 0; + virtual int sign(void) const = 0; + virtual _knumber * sqrt(void) const = 0; + virtual _knumber * cbrt(void) const = 0; + virtual _knumber * change_sign(void) const = 0; + virtual _knumber * reciprocal(void) const = 0; + virtual _knumber * add(_knumber const & arg2) const = 0; + virtual _knumber * multiply(_knumber const & arg2) const = 0; + _knumber * divide(_knumber const & arg2) const; + + virtual _knumber * power(_knumber const & exponent) const = 0; + + virtual int compare(_knumber const &arg2) const = 0; + + virtual operator signed long int (void) const = 0; + virtual operator unsigned long int (void) const = 0; + virtual operator double (void) const = 0; +}; + + + +class _knumerror : public _knumber +{ + public: + _knumerror(ErrorType error = UndefinedNumber) + : _error(error) { } + + _knumerror(_knumber const & num); + + _knumerror(const QString & num); + + //virtual ~_knumerror() { } + + _knumerror const & operator = (_knumerror const & num); + + virtual void copy(_knumber const & num) + { + _error = dynamic_cast<_knumerror const &>(num)._error; + } + + virtual NumType type(void) const {return SpecialType;} + + virtual QString const ascii(int prec = -1) const; + + virtual _knumber * abs(void) const; + virtual _knumber * intPart(void) const; + virtual int sign(void) const; + virtual _knumber * cbrt(void) const; + virtual _knumber * sqrt(void) const; + virtual _knumber * change_sign(void) const; + virtual _knumber * reciprocal(void) const; + virtual _knumber * add(_knumber const & arg2) const; + virtual _knumber * multiply(_knumber const & arg2) const; + + virtual _knumber * power(_knumber const & exponent) const; + + virtual int compare(_knumber const &arg2) const; + + virtual operator signed long int (void) const; + virtual operator unsigned long int (void) const; + virtual operator double (void) const; + + private: + + ErrorType _error; + + friend class _knuminteger; + friend class _knumfraction; + friend class _knumfloat; +}; + + + +class _knuminteger : public _knumber +{ + public: + _knuminteger(signed int num = 0) + { + mpz_init_set_si(_mpz, num); + } + + _knuminteger(unsigned int num) + { + mpz_init_set_ui(_mpz, num); + } + + _knuminteger(signed long int num) + { + mpz_init_set_si(_mpz, num); + } + + _knuminteger(unsigned long int num) + { + mpz_init_set_ui(_mpz, num); + } + + _knuminteger(unsigned long long int num); + + _knuminteger(_knumber const & num); + + _knuminteger(const QString & num); + + virtual ~_knuminteger() + { + mpz_clear(_mpz); + } + + _knuminteger const & operator = (_knuminteger const & num); + + virtual void copy(_knumber const & num) + { + mpz_set(_mpz, dynamic_cast<_knuminteger const &>(num)._mpz); + } + + virtual NumType type(void) const {return IntegerType;} + + virtual QString const ascii(int prec = -1) const; + + virtual _knumber * abs(void) const; + virtual _knumber * intPart(void) const; + virtual int sign(void) const; + virtual _knumber * cbrt(void) const; + virtual _knumber * sqrt(void) const; + virtual _knumber * change_sign(void) const; + virtual _knumber * reciprocal(void) const; + virtual _knumber * add(_knumber const & arg2) const; + virtual _knumber * multiply(_knumber const & arg2) const; + + virtual int compare(_knumber const &arg2) const; + + virtual _knumber * power(_knumber const & exponent) const; + + virtual operator signed long int (void) const; + virtual operator unsigned long int (void) const; + virtual operator double (void) const; + + _knuminteger * intAnd(_knuminteger const &arg2) const; + _knuminteger * intOr(_knuminteger const &arg2) const; + _knumber * mod(_knuminteger const &arg2) const; + _knumber * shift(_knuminteger const &arg2) const; + + private: + mpz_t _mpz; + + friend class _knumfraction; + friend class _knumfloat; +}; + + + +class _knumfraction : public _knumber +{ + public: + + _knumfraction(signed long int nom = 0, signed long int denom = 1) + { + mpq_init(_mpq); + mpq_set_si(_mpq, nom, denom); + mpq_canonicalize(_mpq); + } + + _knumfraction(_knumber const & num); + + _knumfraction(QString const & num); + + virtual ~_knumfraction() + { + mpq_clear(_mpq); + } + + virtual void copy(_knumber const & num) + { + mpq_set(_mpq, dynamic_cast<_knumfraction const &>(num)._mpq); + } + + virtual NumType type(void) const {return FractionType;} + + virtual QString const ascii(int prec = -1) const; + + bool isInteger(void) const; + + virtual _knumber * abs(void) const; + virtual _knumber * intPart(void) const; + virtual int sign(void) const; + virtual _knumber * cbrt(void) const; + virtual _knumber * sqrt(void) const; + virtual _knumber * change_sign(void) const; + virtual _knumber * reciprocal(void) const; + virtual _knumber * add(_knumber const & arg2) const; + virtual _knumber * multiply(_knumber const & arg2) const; + + virtual _knumber * power(_knumber const & exponent) const; + + virtual int compare(_knumber const &arg2) const; + + virtual operator signed long int (void) const; + virtual operator unsigned long int (void) const; + virtual operator double (void) const; + + private: + mpq_t _mpq; + + friend class _knuminteger; + friend class _knumfloat; +}; + +class _knumfloat : public _knumber +{ + public: + _knumfloat(double num = 1.0) + { + mpf_init(_mpf); + mpf_set_d(_mpf, num); + } + + _knumfloat(_knumber const & num); + + _knumfloat(QString const & num); + + virtual ~_knumfloat() + { + mpf_clear(_mpf); + } + + virtual void copy(_knumber const & num) + { + mpf_set(_mpf, dynamic_cast<_knumfloat const &>(num)._mpf); + } + + virtual NumType type(void) const {return FloatType;} + + virtual QString const ascii(int prec = -1) const; + + virtual _knumber * abs(void) const; + virtual _knumber * intPart(void) const; + virtual int sign(void) const; + virtual _knumber * cbrt(void) const; + virtual _knumber * sqrt(void) const; + virtual _knumber * change_sign(void) const; + virtual _knumber * reciprocal(void) const; + virtual _knumber * add(_knumber const & arg2) const; + virtual _knumber * multiply(_knumber const & arg2) const; + virtual _knumber * divide(_knumber const & arg2) const; + + virtual _knumber * power(_knumber const & exponent) const; + + virtual int compare(_knumber const &arg2) const; + + virtual operator signed long int (void) const; + virtual operator unsigned long int (void) const; + virtual operator double (void) const; + + private: + mpf_t _mpf; + + friend class _knuminteger; + friend class _knumfraction; +}; + + +#endif // _KNUMBER_PRIV_H diff --git a/kcalc/knumber/tests/Makefile.am b/kcalc/knumber/tests/Makefile.am new file mode 100644 index 0000000..73b0600 --- /dev/null +++ b/kcalc/knumber/tests/Makefile.am @@ -0,0 +1,32 @@ +# This file is part of the KDE libraries +# Copyright (C) 1996-1997 Matthias Kalle Dalheimer (kalle@kde.org) +# (C) 1997-1998 Stephan Kulow (coolo@kde.org) + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +INCLUDES = -I$(top_srcdir)/kcalc/knumber $(all_includes) + +check_PROGRAMS = knumbertest + +TESTS = knumbertest + +noinst_HEADERS = knumbertest.h + +METASOURCES = AUTO + +knumbertest_SOURCES = knumbertest.cpp +knumbertest_LDADD = ../libknumber.la $(LIB_QT) $(LIBGMP) +knumbertest_LDFLAGS = $(all_libraries) $(KDE_RPATH) diff --git a/kcalc/knumber/tests/knumbertest.cpp b/kcalc/knumber/tests/knumbertest.cpp new file mode 100644 index 0000000..814410e --- /dev/null +++ b/kcalc/knumber/tests/knumbertest.cpp @@ -0,0 +1,582 @@ +// +// Author: Klaus Niederkrueger +// + +#include +#include + +#include +#include + +#include "knumbertest.h" + +QString const numtypeToString(KNumber::NumType arg) +{ + switch(arg) { + case KNumber::SpecialType: + return QString("Special"); + case KNumber::IntegerType: + return QString("Integer"); + case KNumber::FractionType: + return QString("Fraction"); + case KNumber::FloatType: + return QString("Float"); + default: + return QString("Unknown:") + QString::number(static_cast(arg)); + + } +} + +void checkResult(QString const &string, KNumber const & result, + QString const & desired_string, KNumber::NumType desired) +{ + std::cout << "Testing result of: " << string.ascii() << + " should give " << desired_string.ascii() << " and gives " << + result.toQString(8).ascii() << "....\n"; + std::cout << "The type of the result should be " << + numtypeToString(desired).ascii() << " and gives " << + numtypeToString(result.type()).ascii() << ".... "; + + if (result.type() == desired && + result.toQString(8) == desired_string) { + std::cout << "OK\n"; + return; + } + + std::cout << "Failed\n"; + exit(1); +} + +void checkTruth(QString const &string, bool computation, + bool desired_result) +{ + std::cout << "Testing truth of: " << string.ascii() << + " should be " << desired_result << " and is " << + computation << "....\n"; + + if (computation == desired_result) { + std::cout << "OK\n"; + return; + } + + std::cout << "Failed\n"; + exit(1); +} + + +void checkType(QString const &string, KNumber::NumType test_arg, + KNumber::NumType desired) +{ + std::cout << "Testing type of: " << string.ascii() << " should give " << + numtypeToString(desired).ascii() << " and gives " << + numtypeToString(test_arg).ascii() << "...."; + + if (test_arg == desired) { + std::cout << "OK\n"; + return; + } + + std::cout << "Failed\n"; + exit(1); + +} + + +void testingCompare(void) +{ + std::cout << "\n\nTesting Compare:\n"; + + checkTruth("KNumber(5) == KNumber(2)", KNumber(5) == KNumber(2), false); + checkTruth("KNumber(5) > KNumber(2)", KNumber(5) > KNumber(2), true); + checkTruth("KNumber(5) < KNumber(2)", KNumber(5) < KNumber(2), false); + checkTruth("KNumber(5) < KNumber(0)", KNumber(5) < KNumber(0), false); + checkTruth("KNumber(-5) < KNumber(0)", KNumber(-5) < KNumber(0), true); + checkTruth("KNumber(5) >= KNumber(2)", KNumber(5) >= KNumber(2), true); + checkTruth("KNumber(5) <= KNumber(2)", KNumber(5) <= KNumber(2), false); + checkTruth("KNumber(5) != KNumber(2)", KNumber(5) != KNumber(2), true); + + checkTruth("KNumber(2) == KNumber(2)", KNumber(2) == KNumber(2), true); + checkTruth("KNumber(2) > KNumber(2)", KNumber(2) > KNumber(2), false); + checkTruth("KNumber(2) < KNumber(2)", KNumber(2) < KNumber(2), false); + checkTruth("KNumber(2) >= KNumber(2)", KNumber(2) >= KNumber(2), true); + checkTruth("KNumber(2) <= KNumber(2)", KNumber(2) <= KNumber(2), true); + checkTruth("KNumber(2) != KNumber(2)", KNumber(2) != KNumber(2), false); + + checkTruth("KNumber(5) == KNumber(\"1/2\")", KNumber(5) == KNumber("1/2"), false); + checkTruth("KNumber(5) > KNumber(\"1/2\")", KNumber(5) > KNumber("1/2"), true); + checkTruth("KNumber(5) < KNumber(\"1/2\")", KNumber(5) < KNumber("1/2"), false); + checkTruth("KNumber(5) >= KNumber(\"1/2\")", KNumber(5) >= KNumber("1/2"), true); + checkTruth("KNumber(5) <= KNumber(\"1/2\")", KNumber(5) <= KNumber("1/2"), false); + checkTruth("KNumber(5) != KNumber(\"1/2\")", KNumber(5) != KNumber("1/2"), true); + + checkTruth("KNumber(\"1/2\") == KNumber(\"1/2\")", KNumber("1/2") == KNumber("1/2"), true); + checkTruth("KNumber(\"1/2\") > KNumber(\"1/2\")", KNumber("1/2") > KNumber("1/2"), false); + checkTruth("KNumber(\"1/2\") < KNumber(\"1/2\")", KNumber("1/2") < KNumber("1/2"), false); + checkTruth("KNumber(\"1/2\") >= KNumber(\"1/2\")", KNumber("1/2") >= KNumber("1/2"), true); + checkTruth("KNumber(\"1/2\") <= KNumber(\"1/2\")", KNumber("1/2") <= KNumber("1/2"), true); + checkTruth("KNumber(\"1/2\") != KNumber(\"1/2\")", KNumber("1/2") != KNumber("1/2"), false); + + checkTruth("KNumber(\"3/2\") == KNumber(\"1/2\")", KNumber("3/2") == KNumber("1/2"), false); + checkTruth("KNumber(\"3/2\") > KNumber(\"1/2\")", KNumber("3/2") > KNumber("1/2"), true); + checkTruth("KNumber(\"3/2\") < KNumber(\"1/2\")", KNumber("3/2") < KNumber("1/2"), false); + checkTruth("KNumber(\"3/2\") >= KNumber(\"1/2\")", KNumber("3/2") >= KNumber("1/2"), true); + checkTruth("KNumber(\"3/2\") <= KNumber(\"1/2\")", KNumber("3/2") <= KNumber("1/2"), false); + checkTruth("KNumber(\"3/2\") != KNumber(\"1/2\")", KNumber("3/2") != KNumber("1/2"), true); + +} + + +void testingAdditions(void) +{ + std::cout << "\n\nTesting additions:\n"; + + checkResult("KNumber(5) + KNumber(2)", KNumber(5) + KNumber(2), "7", KNumber::IntegerType); + checkResult("KNumber(5) + KNumber(\"2/3\")", KNumber(5) + KNumber("2/3"), "17/3", KNumber::FractionType); + checkResult("KNumber(5) + KNumber(\"2.3\")", KNumber(5) + KNumber("2.3"), "7.3", KNumber::FloatType); + + checkResult("KNumber(\"5/3\") + KNumber(2)", KNumber("5/3") + KNumber(2), "11/3", KNumber::FractionType); + checkResult("KNumber(\"5/3\") + KNumber(\"2/3\")", KNumber("5/3") + KNumber("2/3"), "7/3", KNumber::FractionType); + checkResult("KNumber(\"5/3\") + KNumber(\"1/3\")", KNumber("5/3") + KNumber("1/3"), "2", KNumber::IntegerType); + checkResult("KNumber(\"5/3\") + KNumber(\"-26/3\")", KNumber("5/3") + KNumber("-26/3"), "-7", KNumber::IntegerType); + checkResult("KNumber(\"5/2\") + KNumber(2.3)", KNumber("5/2") + KNumber(2.3), "4.8", KNumber::FloatType); + + checkResult("KNumber(5.3) + KNumber(2)", KNumber(5.3) + KNumber(2), "7.3", KNumber::FloatType); + checkResult("KNumber(5.3) + KNumber(\"2/4\")", KNumber(5.3) + KNumber("2/4"), "5.8", KNumber::FloatType); + checkResult("KNumber(5.3) + KNumber(2.3)", KNumber(5.3) + KNumber(2.3), "7.6", KNumber::FloatType); + +} + +void testingSubtractions(void) +{ + std::cout << "\n\nTesting subtractions:\n"; + + checkResult("KNumber(5) - KNumber(2)", KNumber(5) - KNumber(2), "3", KNumber::IntegerType); + checkResult("KNumber(5) - KNumber(\"2/3\")", KNumber(5) - KNumber("2/3"), "13/3", KNumber::FractionType); + checkResult("KNumber(5) - KNumber(2.3)", KNumber(5) - KNumber(2.3), "2.7", KNumber::FloatType); + + checkResult("KNumber(\"5/3\") - KNumber(2)", KNumber("5/3") - KNumber(2), "-1/3", KNumber::FractionType); + checkResult("KNumber(\"5/3\") - KNumber(\"1/3\")", KNumber("5/3") - KNumber("1/3"), "4/3", KNumber::FractionType); + checkResult("KNumber(\"5/3\") - KNumber(\"2/3\")", KNumber("5/3") - KNumber("2/3"), "1", KNumber::IntegerType); + checkResult("KNumber(\"-5/3\") - KNumber(\"4/3\")", KNumber("-5/3") - KNumber("4/3"), "-3", KNumber::IntegerType); + checkResult("KNumber(\"5/4\") - KNumber(2.2)", KNumber("5/4") - KNumber(2.2), "-0.95", KNumber::FloatType); + + checkResult("KNumber(5.3) - KNumber(2)", KNumber(5.3) - KNumber(2), "3.3", KNumber::FloatType); + checkResult("KNumber(5.3) - KNumber(\"3/4\")", KNumber(5.3) - KNumber("3/4"), "4.55", KNumber::FloatType); + checkResult("KNumber(5.3) - KNumber(2.3)", KNumber(5.3) - KNumber(2.3), "3", KNumber::FloatType); + +} + + +void testingMultiplications(void) +{ + std::cout << "\n\nTesting multiplications:\n"; + + checkResult("KNumber(5) * KNumber(2)", KNumber(5) * KNumber(2), "10", KNumber::IntegerType); + checkResult("KNumber(5) * KNumber(\"2/3\")", KNumber(5) * KNumber("2/3"), "10/3", KNumber::FractionType); + checkResult("KNumber(5) * KNumber(\"2/5\")", KNumber(5) * KNumber("2/5"), "2", KNumber::IntegerType); + checkResult("KNumber(5) * KNumber(2.3)", KNumber(5) * KNumber(2.3), "11.5", KNumber::FloatType); + checkResult("KNumber(0) * KNumber(\"2/5\")", KNumber(0) * KNumber("2/5"), "0", KNumber::IntegerType); + checkResult("KNumber(0) * KNumber(2.3)", KNumber(0) * KNumber(2.3), "0", KNumber::IntegerType); + + checkResult("KNumber(\"5/3\") * KNumber(2)", KNumber("5/3") * KNumber(2), "10/3", KNumber::FractionType); + checkResult("KNumber(\"5/3\") * KNumber(0)", KNumber("5/3") * KNumber(0), "0", KNumber::IntegerType); + checkResult("KNumber(\"5/3\") * KNumber(\"2/3\")", KNumber("5/3") * KNumber("2/3"), "10/9", KNumber::FractionType); + checkResult("KNumber(\"25/6\") * KNumber(\"12/5\")", KNumber("25/6") * KNumber("12/5"), "10", KNumber::IntegerType); + checkResult("KNumber(\"5/2\") * KNumber(2.3)", KNumber("5/2") * KNumber(2.3), "5.75",KNumber::FloatType); + + checkResult("KNumber(5.3) * KNumber(2)", KNumber(5.3) * KNumber(2), "10.6", KNumber::FloatType); + checkResult("KNumber(5.3) * KNumber(0)", KNumber(5.3) * KNumber(0), "0", KNumber::IntegerType); + checkResult("KNumber(5.3) * KNumber(\"1/2\")", KNumber(5.3) * KNumber("1/2"), "2.65", KNumber::FloatType); + checkResult("KNumber(5.3) * KNumber(2.3)", KNumber(5.3) * KNumber(2.3), "12.19", KNumber::FloatType); + +} + +void testingDivisions(void) +{ + std::cout << "\n\nTesting divisions:\n"; + + checkResult("KNumber(5) / KNumber(2)", KNumber(5) / KNumber(2), "5/2", KNumber::FractionType); + checkResult("KNumber(122) / KNumber(2)", KNumber(122) / KNumber(2), "61", KNumber::IntegerType); + checkResult("KNumber(12) / KNumber(0)", KNumber(12) / KNumber(0), "inf", KNumber::SpecialType); + checkResult("KNumber(-12) / KNumber(0)", KNumber(-12) / KNumber(0), "-inf", KNumber::SpecialType); + checkResult("KNumber(5) / KNumber(\"2/3\")", KNumber(5) / KNumber("2/3"), "15/2", KNumber::FractionType); + checkResult("KNumber(6) / KNumber(\"2/3\")", KNumber(6) / KNumber("2/3"), "9", KNumber::IntegerType); + checkResult("KNumber(5) / KNumber(2.5)", KNumber(5) / KNumber(2.5), "2", KNumber::FloatType); + checkResult("KNumber(5) / KNumber(0.0)", KNumber(5) / KNumber(0.0), "inf", KNumber::SpecialType); + checkResult("KNumber(-5) / KNumber(0.0)", KNumber(-5) / KNumber(0.0), "-inf", KNumber::SpecialType); + + checkResult("KNumber(\"5/3\") / KNumber(2)", KNumber("5/3") / KNumber(2), "5/6", KNumber::FractionType); + checkResult("KNumber(\"5/3\") / KNumber(0)", KNumber("5/3") / KNumber(0), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") / KNumber(0)", KNumber("-5/3") / KNumber(0), "-inf", KNumber::SpecialType); + checkResult("KNumber(\"5/3\") / KNumber(\"2/3\")", KNumber("5/3") / KNumber("2/3"), "5/2", KNumber::FractionType); + checkResult("KNumber(\"49/3\") / KNumber(\"7/9\")", KNumber("49/3") / KNumber("7/9"), "21", KNumber::IntegerType); + checkResult("KNumber(\"5/2\") / KNumber(2.5)", KNumber("5/2") / KNumber(2.5), "1", KNumber::FloatType); + checkResult("KNumber(\"5/2\") / KNumber(0.0)", KNumber("5/2") / KNumber(0.0), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/2\") / KNumber(0.0)", KNumber("-5/2") / KNumber(0.0), "-inf", KNumber::SpecialType); + + checkResult("KNumber(5.3) / KNumber(2)", KNumber(5.3) / KNumber(2), "2.65", KNumber::FloatType); + checkResult("KNumber(5.3) / KNumber(0)", KNumber(5.3) / KNumber(0), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.3) / KNumber(0)", KNumber(-5.3) / KNumber(0), "-inf", KNumber::SpecialType); + checkResult("KNumber(5.3) / KNumber(\"2/3\")", KNumber(5.3) / KNumber("2/3"), "7.95", KNumber::FloatType); + checkResult("KNumber(5.5) / KNumber(2.5)", KNumber(5.5) / KNumber(2.5), "2.2", KNumber::FloatType); + checkResult("KNumber(5.5) / KNumber(0.0)", KNumber(5.5) / KNumber(0.0), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.5) / KNumber(0.0)", KNumber(-5.5) / KNumber(0.0), "-inf", KNumber::SpecialType); +} + +void testingModulus(void) +{ + std::cout << "\n\nTesting modulus:\n"; + + checkResult("KNumber(23) % KNumber(4)", KNumber(23) % KNumber(4), "3", KNumber::IntegerType); + checkResult("KNumber(12) % KNumber(-5)", KNumber(12) % KNumber(-5), "2", KNumber::IntegerType); + checkResult("KNumber(-12) % KNumber(5)", KNumber(-12) % KNumber(5), "3", KNumber::IntegerType); + checkResult("KNumber(12) % KNumber(0)", KNumber(-12) % KNumber(0), "nan", KNumber::SpecialType); + checkResult("KNumber(-12) % KNumber(0)", KNumber(-12) % KNumber(0), "nan", KNumber::SpecialType); + +#warning test for other types + +} + +void testingAndOr(void) +{ + std::cout << "\n\nTesting And/Or:\n"; + + checkResult("KNumber(17) & KNumber(9)", KNumber(17) & KNumber(9), "1", KNumber::IntegerType); + checkResult("KNumber(17) | KNumber(9)", KNumber(17) | KNumber(9), "25", KNumber::IntegerType); + checkResult("KNumber(1023) & KNumber(255)", KNumber(1023) & KNumber(255), "255", KNumber::IntegerType); + checkResult("KNumber(1023) | KNumber(255)", KNumber(1023) | KNumber(255), "1023", KNumber::IntegerType); + +#warning test for other types + +} + + +void testingAbs(void) +{ + std::cout << "\n\nTesting absolute value:\n"; + + checkResult("KNumber(5).abs()", KNumber(5).abs(), "5", KNumber::IntegerType); + checkResult("KNumber(\"2/3\").abs()", KNumber("2/3").abs(), "2/3", KNumber::FractionType); + checkResult("KNumber(\"2.3\").abs()", KNumber("2.3").abs(), "2.3", KNumber::FloatType); + + checkResult("KNumber(-5).abs()", KNumber(-5).abs(), "5", KNumber::IntegerType); + checkResult("KNumber(\"-2/3\").abs()", KNumber("-2/3").abs(), "2/3", KNumber::FractionType); + checkResult("KNumber(\"-2.3\").abs()", KNumber("-2.3").abs(), "2.3", KNumber::FloatType); +} + +void testingTruncateToInteger(void) +{ + std::cout << "\n\nTesting truncate to an integer:\n"; + + checkResult("KNumber(16).integerPart()", KNumber(16).integerPart(), "16", KNumber::IntegerType); + checkResult("KNumber(\"43/9\").integerPart()", KNumber("43/9").integerPart(), "4", KNumber::IntegerType); + checkResult("KNumber(\"-43/9\").integerPart()", KNumber("-43/9").integerPart(), "-4", KNumber::IntegerType); + checkResult("KNumber(\"5.25\").integerPart()", KNumber("5.25").integerPart(), "5", KNumber::IntegerType); + checkResult("KNumber(\"-5.25\").integerPart()", KNumber("-5.25").integerPart(), "-5", KNumber::IntegerType); +} + + +void testingSqrt(void) +{ + std::cout << "\n\nTesting square root, cubic root:\n"; + + checkResult("KNumber(16).sqrt()", KNumber(16).sqrt(), "4", KNumber::IntegerType); + checkResult("KNumber(-16).sqrt()", KNumber(-16).sqrt(), "nan", KNumber::SpecialType); + checkResult("KNumber(\"16/9\").sqrt()", KNumber("16/9").sqrt(), "4/3", KNumber::FractionType); + checkResult("KNumber(\"-16/9\").sqrt()", KNumber("-16/9").sqrt(), "nan", KNumber::SpecialType); + checkResult("KNumber(2).sqrt()", KNumber(2).sqrt(), "1.4142136", KNumber::FloatType); + checkResult("KNumber(\"2/3\").sqrt()", KNumber("2/3").sqrt(), "0.81649658", KNumber::FloatType); + checkResult("KNumber(\"0.25\").sqrt()", KNumber("0.25").sqrt(), "0.5", KNumber::FloatType); + checkResult("KNumber(\"-0.25\").sqrt()", KNumber("-0.25").sqrt(), "nan", KNumber::SpecialType); + + + checkResult("KNumber(27).cbrt()", KNumber(27).cbrt(), "3", KNumber::IntegerType); + checkResult("KNumber(-27).cbrt()", KNumber(-27).cbrt(), "-3", KNumber::IntegerType); + checkResult("KNumber(\"27/8\").cbrt()", KNumber("27/8").cbrt(), "3/2", KNumber::FractionType); + checkResult("KNumber(\"-8/27\").cbrt()", KNumber("-8/27").cbrt(), "-2/3", KNumber::FractionType); +#warning need to check non-perfect cube roots + // checkResult("KNumber(2).cbrt()", KNumber(2).cbrt(), "1.4142136", KNumber::FloatType); + // checkResult("KNumber(\"2/3\").cbrt()", KNumber("2/3").cbrt(), "0.81649658", KNumber::FloatType); + // checkResult("KNumber(\"0.25\").cbrt()", KNumber("0.25").cbrt(), "0.5", KNumber::FloatType); + // checkResult("KNumber(\"-0.25\").cbrt()", KNumber("-0.25").cbrt(), "nan", KNumber::SpecialType); + +} + +void testingShifts(void) +{ + std::cout << "\n\nTesting left/right shift:\n"; + + checkResult("KNumber(16) << KNumber(2)", KNumber(16) << KNumber(2), "64", KNumber::IntegerType); + checkResult("KNumber(16) >> KNumber(2)", KNumber(16) >> KNumber(2), "4", KNumber::IntegerType); + +} + +void testingPower(void) +{ + std::cout << "\n\nTesting Power:\n"; + + checkResult("KNumber(0) ^ KNumber(-4)", KNumber(0).power(KNumber(-4)), "inf", KNumber::SpecialType); + checkResult("KNumber(5) ^ KNumber(4)", KNumber(5).power(KNumber(4)), "625", KNumber::IntegerType); + checkResult("KNumber(122) ^ KNumber(0)", KNumber(122).power(KNumber(0)), "1", KNumber::IntegerType); + checkResult("KNumber(-5) ^ KNumber(0)", KNumber(-5).power(KNumber(0)), "nan", KNumber::SpecialType); + checkResult("KNumber(-2) ^ KNumber(3)", KNumber(-2).power(KNumber(3)), "-8", KNumber::IntegerType); + checkResult("KNumber(-2) ^ KNumber(4)", KNumber(-2).power(KNumber(4)), "16", KNumber::IntegerType); + checkResult("KNumber(5) ^ KNumber(-2)", KNumber(5).power(KNumber(-2)), "1/25", KNumber::FractionType); + checkResult("KNumber(8) ^ KNumber(\"2/3\")", KNumber(8).power(KNumber("2/3")), "4", KNumber::IntegerType); + checkResult("KNumber(8) ^ KNumber(\"-2/3\")", KNumber(8).power(KNumber("-2/3")), "1/4", KNumber::FractionType); + checkResult("KNumber(-16) ^ KNumber(\"1/4\")", KNumber(-16).power(KNumber("1/4")), "nan", KNumber::SpecialType); + checkResult("KNumber(-8) ^ KNumber(\"1/3\")", KNumber(-8).power(KNumber("1/3")), "nan", KNumber::SpecialType); + checkResult("KNumber(5) ^ KNumber(0.0)", KNumber(5).power(KNumber(0.0)), "1", KNumber::IntegerType); + checkResult("KNumber(-5) ^ KNumber(0.0)", KNumber(-5).power(KNumber(0.0)), "nan", KNumber::SpecialType); + + checkResult("KNumber(\"5/3\") ^ KNumber(2)", KNumber("5/3").power(KNumber(2)), "25/9", KNumber::FractionType); + checkResult("KNumber(\"5/3\") ^ KNumber(0)", KNumber("5/3").power(KNumber(0)), "1", KNumber::IntegerType); + checkResult("KNumber(\"-5/3\") ^ KNumber(0)", KNumber("-5/3").power(KNumber(0)), "nan", KNumber::SpecialType); + checkResult("KNumber(\"8/27\") ^ KNumber(\"2/3\")", KNumber("8/27").power(KNumber("2/3")), "4/9", KNumber::FractionType); + checkResult("KNumber(\"49/3\") ^ KNumber(\"7/9\")", KNumber("49/3").power(KNumber("7/9")), "21", KNumber::IntegerType); + checkResult("KNumber(\"5/2\") ^ KNumber(2.5)", KNumber("5/2").power(KNumber(2.5)), "1", KNumber::FloatType); + checkResult("KNumber(\"5/2\") ^ KNumber(0.0)", KNumber("5/2").power(KNumber(0.0)), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/2\") ^ KNumber(0.0)", KNumber("-5/2").power(KNumber(0.0)), "-inf", KNumber::SpecialType); + + checkResult("KNumber(5.3) ^ KNumber(2)", KNumber(5.3).power(KNumber(2)), "2.65", KNumber::FloatType); + checkResult("KNumber(5.3) ^ KNumber(0)", KNumber(5.3).power(KNumber(0)), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.3) ^ KNumber(0)", KNumber(-5.3).power(KNumber(0)), "-inf", KNumber::SpecialType); + checkResult("KNumber(5.3) ^ KNumber(\"2/3\")", KNumber(5.3).power(KNumber("2/3")), "7.95", KNumber::FloatType); + checkResult("KNumber(5.5) ^ KNumber(2.5)", KNumber(5.5).power(KNumber(2.5)), "2.2", KNumber::FloatType); + checkResult("KNumber(5.5) ^ KNumber(0.0)", KNumber(5.5).power(KNumber(0.0)), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.5) ^ KNumber(0.0)", KNumber(-5.5).power(KNumber(0.0)), "-inf", KNumber::SpecialType); +} + +void testingInfArithmetic(void) +{ + std::cout << "\n\nTesting inf/nan-arithmetics:\n"; + + KNumber tmp_inf = KNumber("inf"); + KNumber tmp_mininf = KNumber("-inf"); + KNumber tmp_nan = KNumber("nan"); + + checkResult("inf + KNumber(2)", tmp_inf + KNumber(2), "inf", KNumber::SpecialType); + checkResult("KNumber(-5) + inf", KNumber(-5) + tmp_inf, "inf", KNumber::SpecialType); + checkResult("inf + KNumber(\"1/2\")", tmp_inf + KNumber("1/2"), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") + inf", KNumber("-5/3") + tmp_inf, "inf", KNumber::SpecialType); + checkResult("inf + KNumber(2.01)", tmp_inf + KNumber(2.01), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) + inf", KNumber(-5.4) + tmp_inf, "inf", KNumber::SpecialType); + checkResult("mininf + KNumber(2)", tmp_mininf + KNumber(2), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5) + mininf", KNumber(-5) + tmp_mininf, "-inf", KNumber::SpecialType); + checkResult("mininf + KNumber(\"1/2\")", tmp_mininf + KNumber("1/2"), "-inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") + mininf", KNumber("-5/3") + tmp_mininf, "-inf", KNumber::SpecialType); + checkResult("mininf + KNumber(2.01)", tmp_mininf + KNumber(2.01), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) + mininf", KNumber(-5.4) + tmp_mininf, "-inf", KNumber::SpecialType); + checkResult("nan + KNumber(2)", tmp_nan + KNumber(2), "nan", KNumber::SpecialType); + checkResult("KNumber(-5) + nan", KNumber(-5) + tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan + KNumber(\"1/2\")", tmp_nan + KNumber("1/2"), "nan", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") + nan", KNumber("-5/3") + tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan + KNumber(2.01)", tmp_nan + KNumber(2.01), "nan", KNumber::SpecialType); + checkResult("KNumber(-5.4) + nan", KNumber(-5.4) + tmp_nan, "nan", KNumber::SpecialType); + checkResult("inf + inf", tmp_inf + tmp_inf, "inf", KNumber::SpecialType); + checkResult("inf + mininf", tmp_inf + tmp_mininf, "nan", KNumber::SpecialType); + checkResult("mininf + inf", tmp_mininf + tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf + mininf", tmp_mininf + tmp_mininf, "-inf", KNumber::SpecialType); + checkResult("inf + nan", tmp_inf + tmp_nan, "nan", KNumber::SpecialType); + checkResult("mininf + nan", tmp_mininf + tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan + inf", tmp_nan + tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf + nan", tmp_mininf + tmp_nan, "nan", KNumber::SpecialType); + + + checkResult("inf - KNumber(2)", tmp_inf - KNumber(2), "inf", KNumber::SpecialType); + checkResult("KNumber(-5) - inf", KNumber(-5) - tmp_inf, "-inf", KNumber::SpecialType); + checkResult("inf - KNumber(\"1/2\")", tmp_inf - KNumber("1/2"), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") - inf", KNumber("-5/3") - tmp_inf, "-inf", KNumber::SpecialType); + checkResult("inf - KNumber(2.01)", tmp_inf - KNumber(2.01), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) - inf", KNumber(-5.4) - tmp_inf, "-inf", KNumber::SpecialType); + checkResult("mininf - KNumber(2)", tmp_mininf - KNumber(2), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5) - mininf", KNumber(-5) - tmp_mininf, "inf", KNumber::SpecialType); + checkResult("mininf - KNumber(\"1/2\")", tmp_mininf - KNumber("1/2"), "-inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") - mininf", KNumber("-5/3") - tmp_mininf, "inf", KNumber::SpecialType); + checkResult("mininf - KNumber(2.01)", tmp_mininf - KNumber(2.01), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) - mininf", KNumber(-5.4) - tmp_mininf, "inf", KNumber::SpecialType); + checkResult("nan - KNumber(2)", tmp_nan - KNumber(2), "nan", KNumber::SpecialType); + checkResult("KNumber(-5) - nan", KNumber(-5) - tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan - KNumber(\"1/2\")", tmp_nan - KNumber("1/2"), "nan", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") - nan", KNumber("-5/3") - tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan - KNumber(2.01)", tmp_nan - KNumber(2.01), "nan", KNumber::SpecialType); + checkResult("KNumber(-5.4) - nan", KNumber(-5.4) - tmp_nan, "nan", KNumber::SpecialType); + checkResult("inf - inf", tmp_inf - tmp_inf, "nan", KNumber::SpecialType); + checkResult("inf - mininf", tmp_inf - tmp_mininf, "inf", KNumber::SpecialType); + checkResult("mininf - inf", tmp_mininf - tmp_inf, "-inf", KNumber::SpecialType); + checkResult("mininf - mininf", tmp_mininf - tmp_mininf, "nan", KNumber::SpecialType); + checkResult("inf - nan", tmp_inf - tmp_nan, "nan", KNumber::SpecialType); + checkResult("mininf - nan", tmp_mininf - tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan - inf", tmp_nan - tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf - nan", tmp_mininf - tmp_nan, "nan", KNumber::SpecialType); + + + checkResult("inf * KNumber(2)", tmp_inf * KNumber(2), "inf", KNumber::SpecialType); + checkResult("KNumber(-5) * inf", KNumber(-5) * tmp_inf, "-inf", KNumber::SpecialType); + checkResult("inf * KNumber(\"1/2\")", tmp_inf * KNumber("1/2"), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") * inf", KNumber("-5/3") * tmp_inf, "-inf", KNumber::SpecialType); + checkResult("inf * KNumber(2.01)", tmp_inf * KNumber(2.01), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) * inf", KNumber(-5.4) * tmp_inf, "-inf", KNumber::SpecialType); + checkResult("mininf * KNumber(2)", tmp_mininf * KNumber(2), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5) * mininf", KNumber(-5) * tmp_mininf, "inf", KNumber::SpecialType); + checkResult("mininf * KNumber(\"1/2\")", tmp_mininf * KNumber("1/2"), "-inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") * mininf", KNumber("-5/3") * tmp_mininf, "inf", KNumber::SpecialType); + checkResult("mininf * KNumber(2.01)", tmp_mininf * KNumber(2.01), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) * mininf", KNumber(-5.4) * tmp_mininf, "inf", KNumber::SpecialType); + checkResult("nan * KNumber(2)", tmp_nan * KNumber(2), "nan", KNumber::SpecialType); + checkResult("KNumber(-5) * nan", KNumber(-5) * tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan * KNumber(\"1/2\")", tmp_nan * KNumber("1/2"), "nan", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") * nan", KNumber("-5/3") * tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan * KNumber(2.01)", tmp_nan * KNumber(2.01), "nan", KNumber::SpecialType); + checkResult("KNumber(-5.4) * nan", KNumber(-5.4) * tmp_nan, "nan", KNumber::SpecialType); + checkResult("inf * inf", tmp_inf * tmp_inf, "inf", KNumber::SpecialType); + checkResult("inf * mininf", tmp_inf * tmp_mininf, "-inf", KNumber::SpecialType); + checkResult("mininf * inf", tmp_mininf * tmp_inf, "-inf", KNumber::SpecialType); + checkResult("mininf * mininf", tmp_mininf * tmp_mininf, "inf", KNumber::SpecialType); + checkResult("inf * nan", tmp_inf * tmp_nan, "nan", KNumber::SpecialType); + checkResult("mininf * nan", tmp_mininf * tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan * inf", tmp_nan * tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf * nan", tmp_mininf * tmp_nan, "nan", KNumber::SpecialType); + checkResult("KNumber(0) * inf", KNumber(0) * tmp_inf, "nan", KNumber::SpecialType); + checkResult("KNumber(0) * mininf", KNumber(0) * tmp_mininf, "nan", KNumber::SpecialType); + checkResult("inf * KNumber(0)", tmp_inf * KNumber(0), "nan", KNumber::SpecialType); + checkResult("mininf * KNumber(0)", tmp_mininf * KNumber(0), "nan", KNumber::SpecialType); + checkResult("KNumber(0.0) * inf", KNumber(0.0) * tmp_inf, "nan", KNumber::SpecialType); + checkResult("KNumber(0.0) * mininf", KNumber(0.0) * tmp_mininf, "nan", KNumber::SpecialType); + checkResult("inf * KNumber(0.0)", tmp_inf * KNumber(0.0), "nan", KNumber::SpecialType); + checkResult("mininf * KNumber(0.0)", tmp_mininf * KNumber(0.0), "nan", KNumber::SpecialType); + + + checkResult("inf / KNumber(2)", tmp_inf / KNumber(2), "inf", KNumber::SpecialType); + checkResult("KNumber(-5) / inf", KNumber(-5) / tmp_inf, "0", KNumber::IntegerType); + checkResult("inf / KNumber(\"1/2\")", tmp_inf / KNumber("1/2"), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") / inf", KNumber("-5/3") / tmp_inf, "0", KNumber::IntegerType); + checkResult("inf / KNumber(2.01)", tmp_inf / KNumber(2.01), "inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) / inf", KNumber(-5.4) / tmp_inf, "0", KNumber::IntegerType); + checkResult("mininf / KNumber(2)", tmp_mininf / KNumber(2), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5) / mininf", KNumber(-5) / tmp_mininf, "0", KNumber::IntegerType); + checkResult("mininf / KNumber(\"1/2\")", tmp_mininf / KNumber("1/2"), "-inf", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") / mininf", KNumber("-5/3") / tmp_mininf, "0", KNumber::IntegerType); + checkResult("mininf / KNumber(2.01)", tmp_mininf / KNumber(2.01), "-inf", KNumber::SpecialType); + checkResult("KNumber(-5.4) / mininf", KNumber(-5.4) / tmp_mininf, "0", KNumber::IntegerType); + checkResult("nan / KNumber(2)", tmp_nan / KNumber(2), "nan", KNumber::SpecialType); + checkResult("KNumber(-5) / nan", KNumber(-5) / tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan / KNumber(\"1/2\")", tmp_nan / KNumber("1/2"), "nan", KNumber::SpecialType); + checkResult("KNumber(\"-5/3\") / nan", KNumber("-5/3") / tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan / KNumber(2.01)", tmp_nan / KNumber(2.01), "nan", KNumber::SpecialType); + checkResult("KNumber(-5.4) / nan", KNumber(-5.4) / tmp_nan, "nan", KNumber::SpecialType); + checkResult("inf / inf", tmp_inf / tmp_inf, "nan", KNumber::SpecialType); + checkResult("inf / mininf", tmp_inf / tmp_mininf, "nan", KNumber::SpecialType); + checkResult("mininf / inf", tmp_mininf / tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf / mininf", tmp_mininf / tmp_mininf, "nan", KNumber::SpecialType); + checkResult("inf / nan", tmp_inf / tmp_nan, "nan", KNumber::SpecialType); + checkResult("mininf / nan", tmp_mininf / tmp_nan, "nan", KNumber::SpecialType); + checkResult("nan / inf", tmp_nan / tmp_inf, "nan", KNumber::SpecialType); + checkResult("mininf / nan", tmp_mininf / tmp_nan, "nan", KNumber::SpecialType); + checkResult("KNumber(0) / inf", KNumber(0) / tmp_inf, "0", KNumber::IntegerType); + checkResult("KNumber(0) / mininf", KNumber(0) / tmp_mininf, "0", KNumber::IntegerType); + checkResult("inf / KNumber(0)", tmp_inf / KNumber(0), "inf", KNumber::SpecialType); + checkResult("mininf / KNumber(0)", tmp_mininf / KNumber(0), "-inf", KNumber::SpecialType); + checkResult("KNumber(0.0) / inf", KNumber(0.0) / tmp_inf, "0", KNumber::IntegerType); + checkResult("KNumber(0.0) / mininf", KNumber(0.0) / tmp_mininf, "0", KNumber::IntegerType); + checkResult("inf / KNumber(0.0)", tmp_inf / KNumber(0.0), "inf", KNumber::SpecialType); + checkResult("mininf / KNumber(0.0)", tmp_mininf / KNumber(0.0), "-inf", KNumber::SpecialType); +} + +void testingFloatPrecision(void) +{ + KNumber::setDefaultFloatPrecision(100); + checkResult("Precision >= 100: (KNumber(1) + KNumber(\"1e-80\")) - KNumber(1)", + (KNumber(1) + KNumber("1e-80")) - KNumber(1), "1e-80", KNumber::FloatType); + checkResult("Precision >= 100: (KNumber(1) + KNumber(\"1e-980\")) - KNumber(1)", + (KNumber(1) + KNumber("1e-980")) - KNumber(1), "0", KNumber::FloatType); + + KNumber::setDefaultFloatPrecision(1000); + checkResult("Precision >= 1000: (KNumber(1) + KNumber(\"1e-980\")) - KNumber(1)", + (KNumber(1) + KNumber("1e-980")) - KNumber(1), "1e-980", KNumber::FloatType); + +} + +void testingOutput(void) +{ + KNumber::setDefaultFloatOutput(false); + checkResult("Fractional output: KNumber(\"1/4\")", KNumber("1/4"), "1/4", KNumber::FractionType); + KNumber::setDefaultFloatOutput(true); + checkResult("Float: KNumber(\"1/4\")", KNumber("1/4"), "0.25", KNumber::FractionType); + KNumber::setDefaultFloatOutput(false); + KNumber::setSplitoffIntegerForFractionOutput(true); + checkResult("Fractional output: KNumber(\"1/4\")", KNumber("1/4"), "1/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"-1/4\")", KNumber("-1/4"), "-1/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"21/4\")", KNumber("21/4"), "5 1/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"-21/4\")", KNumber("-21/4"), "-5 1/4", KNumber::FractionType); + KNumber::setSplitoffIntegerForFractionOutput(false); + checkResult("Fractional output: KNumber(\"1/4\")", KNumber("1/4"), "1/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"-1/4\")", KNumber("-1/4"), "-1/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"21/4\")", KNumber("21/4"), "21/4", KNumber::FractionType); + checkResult("Fractional output: KNumber(\"-21/4\")", KNumber("-21/4"), "-21/4", KNumber::FractionType); +} + + +int main(void) +{ + std::cout << "Testing Constructors:\n"; + + checkResult("KNumber(5)", KNumber(5), "5", KNumber::IntegerType); + checkType("KNumber(5.3)", KNumber(5.3).type(), KNumber::FloatType); + checkType("KNumber(0.0)", KNumber(0.0).type(), KNumber::FloatType); + + checkResult("KNumber(\"5\")", KNumber("5"), "5", KNumber::IntegerType); + checkResult("KNumber(\"5/3\")", KNumber("5/3"), "5/3", KNumber::FractionType); + checkResult("KNumber(\"5/1\")", KNumber("5/1"), "5", KNumber::IntegerType); + checkResult("KNumber(\"0/12\")", KNumber("0/12"), "0", KNumber::IntegerType); + KNumber::setDefaultFractionalInput(true); + std::cout << "Read decimals as fractions:\n"; + checkResult("KNumber(\"5\")", KNumber("5"), "5", KNumber::IntegerType); + checkResult("KNumber(\"1.2\")", KNumber("1.2"), "6/5", KNumber::FractionType); + checkResult("KNumber(\"-0.02\")", KNumber("-0.02"), "-1/50", KNumber::FractionType); + checkResult("KNumber(\"5e-2\")", KNumber("5e-2"), "1/20", KNumber::FractionType); + checkResult("KNumber(\"1.2e3\")", KNumber("1.2e3"), "1200", KNumber::IntegerType); + checkResult("KNumber(\"0.02e+1\")", KNumber("0.02e+1"), "1/5", KNumber::FractionType); + + KNumber::setDefaultFractionalInput(false); + std::cout << "Read decimals as floats:\n"; + checkResult("KNumber(\"5.3\")", KNumber("5.3"), "5.3", KNumber::FloatType); + + checkResult("KNumber(\"nan\")", KNumber("nan"), "nan", KNumber::SpecialType); + checkResult("KNumber(\"inf\")", KNumber("inf"), "inf", KNumber::SpecialType); + checkResult("KNumber(\"-inf\")", KNumber("-inf"), "-inf", KNumber::SpecialType); + + std::cout << "\n\nConstants:\n"; + + checkType("KNumber::Zero", KNumber::Zero.type(), KNumber::IntegerType); + checkType("KNumber::One", KNumber::One.type(), KNumber::IntegerType); + checkType("KNumber::MinusOne", KNumber::MinusOne.type(), KNumber::IntegerType); + checkType("KNumber::Pi", KNumber::Pi.type(), KNumber::FloatType); + + testingCompare(); + + testingAdditions(); + testingSubtractions(); + testingMultiplications(); + testingDivisions(); + + testingAndOr(); + testingModulus(); + + testingAbs(); + testingSqrt(); + //testingPower(); + testingTruncateToInteger(); + + testingShifts(); + + testingInfArithmetic(); + + testingFloatPrecision(); + + testingOutput(); + + return 0; +} + + diff --git a/kcalc/knumber/tests/knumbertest.h b/kcalc/knumber/tests/knumbertest.h new file mode 100644 index 0000000..b93dc4a --- /dev/null +++ b/kcalc/knumber/tests/knumbertest.h @@ -0,0 +1,9 @@ +#ifndef KNUMBERTEST_H +#define KNUMBERTEST_H + +#include "knumber.h" + +/** test: a small test program for KNumber + */ + +#endif // KNUMBERTEST_H diff --git a/kcalc/stats.cpp b/kcalc/stats.cpp new file mode 100644 index 0000000..909bed6 --- /dev/null +++ b/kcalc/stats.cpp @@ -0,0 +1,196 @@ +/* + $Id$ + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#include "stats.h" +#ifdef DEBUG_STATS + #include +#endif + +KStats::KStats() { + error_flag = false; +} + +KStats::~KStats() { +} + +void KStats::clearAll() { + mData.clear(); +} + +void KStats::enterData(KNumber const & _data) { + + mData.push_back(_data); +#ifdef DEBUG_STATS + printf("Added %Lg\n", _data); + printf("count %d\n", mData.size()); +#endif + +} + + +void KStats::clearLast(void) { + + mData.pop_back(); +#ifdef DEBUG_STATS + printf("count %d\n",mData.size()); +#endif + + +} + +KNumber KStats::sum(void) { + + KNumber result = 0; + QValueVector::iterator p; + + for(p = mData.begin(); p != mData.end(); ++p) { + result += *p; + } + +#ifdef DEBUG_STATS + printf("Sum %Lg\n", result); +#endif + + return result; +} + +KNumber KStats::median(void) { + + KNumber result = 0; + unsigned int bound; + size_t index; + + bound = count(); + + if (bound == 0){ + error_flag = true; + return 0; + } + + if (bound == 1) + return mData.at(0); + + // need to copy mData-list, because sorting afterwards + QValueVector tmp_mData(mData); + qHeapSort(tmp_mData); + + if( bound & 1) { // odd + index = (bound - 1 ) / 2 + 1; + result = tmp_mData.at(index - 1); + } else { // even + index = bound / 2; + result = ((tmp_mData.at(index - 1)) + (tmp_mData.at(index))) / KNumber(2); + } + + return result; +} + + +KNumber KStats::std_kernel(void) +{ + KNumber result = KNumber::Zero; + KNumber _mean; + QValueVector::iterator p; + + _mean = mean(); + + for(p = mData.begin(); p != mData.end(); ++p) { + result += (*p - _mean) * (*p - _mean); + } + + return result; +} + + +KNumber KStats::sum_of_squares() { + + KNumber result = 0; + QValueVector::iterator p; + + for(p = mData.begin(); p != mData.end(); ++p) { + result += ((*p) * (*p)); + } + + return result; +} + + +KNumber KStats::mean(void) +{ + if(count() == 0){ + error_flag = true; + return 0; + } + + return (sum() / KNumber(count())); +} + + +KNumber KStats::std(void) +{ + if(count() == 0){ + error_flag = true; + return KNumber::Zero; + } + + return (std_kernel() / KNumber(count())).sqrt(); +} + + +KNumber KStats::sample_std(void) { + KNumber result = 0; + + if(count() < 2 ){ + error_flag = true; + return KNumber::Zero; + } + + result = (std_kernel() / KNumber(count() - 1)).sqrt(); + + // result = result/(count() - 1); +#ifdef DEBUG_STATS + printf("sample std: %Lg\n",result); +#endif + + return result; +} + + +int KStats::count(void) const +{ + return static_cast(mData.size()); +} + + +bool KStats::error() { + + bool value = error_flag; + error_flag = false; + return value; +} + + + diff --git a/kcalc/stats.h b/kcalc/stats.h new file mode 100644 index 0000000..48b7ddc --- /dev/null +++ b/kcalc/stats.h @@ -0,0 +1,60 @@ +/* + $Id$ + + KCalc, a scientific calculator for the X window system using the + Qt widget libraries, available at no cost at http://www.troll.no + + Copyright (C) 1996 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef KSTATS_H +#define KSTATS_H + +#include +#include "knumber.h" + +class KStats { + +public: + KStats(); + ~KStats(); + +public: + void clearAll(); + void enterData(const KNumber & data); + void clearLast(); + KNumber sum(); + KNumber sum_of_squares(); + KNumber mean(); + KNumber median(); + KNumber std_kernel(); + KNumber std(); + KNumber sample_std(); + int count() const; + bool error(); + +private: + QValueVector mData; + bool error_flag; + +}; + + +#endif /*KSTATS_H*/ + diff --git a/kcalc/version.h b/kcalc/version.h new file mode 100644 index 0000000..9a591f3 --- /dev/null +++ b/kcalc/version.h @@ -0,0 +1 @@ +#define KCALCVERSION "2.0.6" diff --git a/kcharselect/KCharSelect.desktop b/kcharselect/KCharSelect.desktop new file mode 100644 index 0000000..f51d579 --- /dev/null +++ b/kcharselect/KCharSelect.desktop @@ -0,0 +1,98 @@ +[Desktop Entry] +GenericName=Character Selector +GenericName[af]=Karakter Kiesser +GenericName[ar]=أداة اختيار الرموز +GenericName[az]=Xarakter Seçici +GenericName[bg]=Избор на знаци +GenericName[br]=Dibaber arouezenn +GenericName[bs]=Izbor znakova +GenericName[ca]=Selector de caràcters +GenericName[cs]=Vyběr znaků +GenericName[cy]=Dewisydd Nod +GenericName[da]=Tegnvælger +GenericName[de]=Tabelle zur Zeichenauswahl +GenericName[el]=Επιλογέας χαρακτήρων +GenericName[eo]=Elektilo por signoj +GenericName[es]=Selector de caracteres +GenericName[et]=Sümbolite valija +GenericName[eu]=Karaktere Hautatzailea +GenericName[fa]=گزینندۀ نویسه +GenericName[fi]=Valitse merkki leikepöydälle +GenericName[fr]=Sélecteur de caractères +GenericName[ga]=Roghnóir Carachtar +GenericName[gl]=Selector de Caracteres +GenericName[he]=בוחר תווים +GenericName[hi]=अक्षर चयनक +GenericName[hr]=Izbor znakova +GenericName[hu]=Karakterválasztó +GenericName[id]=Pemilih Karakter +GenericName[is]=Stafaval +GenericName[it]=Selettore di caratteri +GenericName[ja]=文字の選択 +GenericName[ka]=სიმბოლოთა შემრჩეველი +GenericName[kk]=Таңба тергіш +GenericName[km]=កម្មវិធី​ជ្រើស​តួអក្សរ +GenericName[ko]=글자 고르기 +GenericName[lt]=Simbolių parinkimas +GenericName[lv]=Simbolu Selektors +GenericName[mk]=Избирач на знаци +GenericName[mt]=Agħżel Karattri +GenericName[nb]=Tegnvelger +GenericName[nds]=Tekenutwähler +GenericName[ne]=क्यारेक्टर चयनकर्ता +GenericName[nl]=Speciale tekens +GenericName[nn]=Teiknveljar +GenericName[pa]=ਅੱਖਰ ਚੋਣਕਾਰ +GenericName[pl]=Wybór pojedynczego znaku +GenericName[pt]=Selector de Caracteres +GenericName[pt_BR]=Seletor de Caracteres +GenericName[ro]=Selector de caractere +GenericName[ru]=Выбор символов +GenericName[sk]=Volič znakov +GenericName[sl]=Izbiranje znakov +GenericName[sr]=Бирач знакова +GenericName[sr@Latn]=Birač znakova +GenericName[sv]=Teckenväljare +GenericName[ta]= எழுத்து தேர்ந்தெடுப்பான் +GenericName[tg]=Интихобгари Аломатҳо +GenericName[th]=เครื่องมือเลือกอักขระ +GenericName[tr]=Karakter Seçici +GenericName[uk]=Таблиця символів +GenericName[uz]=Harf tanlagich +GenericName[uz@cyrillic]=Ҳарф танлагич +GenericName[ven]=Munangi wa muanewa +GenericName[vi]=Trình chọn kí tự +GenericName[wa]=Tchoezixheu di caracteres +GenericName[xh]=Umkhethi womsebenzi +GenericName[zh_CN]=字符选择器 +GenericName[zh_TW]=字元選擇器 +GenericName[zu]=Umkhethi Womsebenzi +Exec=kcharselect -caption "%c" %i %m +Icon=kcharselect +Path= +Type=Application +Terminal=false +DocPath=kcharselect/index.html +Name=KCharSelect +Name[af]=Kcharselect +Name[cy]=KDewisNod +Name[eo]=Signoelektilo +Name[hi]=के-चर-सलेक्ट +Name[ne]=केडीई क्यारेक्टर चयन +Name[nl]=Speciale tekens +Name[pa]=ਕਅੱਖਰਚੋਣਕਾਰ +Name[pl]=Wybór znaków +Name[pt_BR]=Seletor de caracteres +Name[sr]=KChartSelect +Name[sr@Latn]=KChartSelect +Name[sv]=Kcharselect +Name[ta]= கேஎழுத்துதேர்வு +Name[tg]=KИнтихобгари Аломатҳо +Name[th]=เลือกอักขระ +Name[tr]=Karakter Seçici +Name[ven]=U nanga muanewa wa K +Name[xh]=Itshati yokukheta i K +Name[zh_TW]=KDE 字元選擇 +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Utility;X-KDE-More; diff --git a/kcharselect/Makefile.am b/kcharselect/Makefile.am new file mode 100644 index 0000000..622920e --- /dev/null +++ b/kcharselect/Makefile.am @@ -0,0 +1,21 @@ +INCLUDES = $(all_includes) +LDADD = $(LIB_KFILE) +bin_PROGRAMS = kcharselect + +kcharselect_SOURCES = kcharselectdia.cc main.cc +kcharselect_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kcharselect_METASOURCES = kcharselectdia.moc + +updatedir = $(kde_datadir)/kconf_update +update_DATA = kcharselect.upd + +KDE_ICON = kcharselect + +xdg_apps_DATA = KCharSelect.desktop + +rcdir = $(kde_datadir)/kcharselect +rc_DATA = kcharselectui.rc + +messages: rc.cpp + $(XGETTEXT) *.cc *.cpp -o $(podir)/kcharselect.pot + diff --git a/kcharselect/TODO b/kcharselect/TODO new file mode 100644 index 0000000..261f1ab --- /dev/null +++ b/kcharselect/TODO @@ -0,0 +1,6 @@ +o Mark which glyphs are subsitutes (requires QT support). +o Gridview refresh bug -- sometimes trash appears the empty space when + resized. +o Don't use the grid layout class - it's more trouble than it's worth. +o Should remove the useless "What's this?" widget from title bar. +o Use a horizontal layout for "Clear", "To Clipboard", and the line edit. diff --git a/kcharselect/hi16-app-kcharselect.png b/kcharselect/hi16-app-kcharselect.png new file mode 100644 index 0000000..8e0f8d6 Binary files /dev/null and b/kcharselect/hi16-app-kcharselect.png differ diff --git a/kcharselect/hi32-app-kcharselect.png b/kcharselect/hi32-app-kcharselect.png new file mode 100644 index 0000000..19611e5 Binary files /dev/null and b/kcharselect/hi32-app-kcharselect.png differ diff --git a/kcharselect/hi48-app-kcharselect.png b/kcharselect/hi48-app-kcharselect.png new file mode 100644 index 0000000..c806cdc Binary files /dev/null and b/kcharselect/hi48-app-kcharselect.png differ diff --git a/kcharselect/kcharselect.upd b/kcharselect/kcharselect.upd new file mode 100644 index 0000000..a6a186b --- /dev/null +++ b/kcharselect/kcharselect.upd @@ -0,0 +1,5 @@ +Id=1 +File=kcharselectrc +Group=General +Key=font,selectedFont +RemoveKey=font diff --git a/kcharselect/kcharselectdia.cc b/kcharselect/kcharselectdia.cc new file mode 100644 index 0000000..43e13b0 --- /dev/null +++ b/kcharselect/kcharselectdia.cc @@ -0,0 +1,289 @@ +/******************************************************************/ +/* KCharSelectDia - (c) by Reginald Stadlbauer 1999 */ +/* Author: Reginald Stadlbauer */ +/* E-Mail: reggie@kde.org */ +/* RTL support by Bryce Nesbitt */ +/******************************************************************/ + +#include "kcharselectdia.moc" + +#include + +#include +#include +#include +#include +#include +#include + +/******************************************************************/ +/* class KCharSelectDia */ +/******************************************************************/ + +//================================================================== +KCharSelectDia::KCharSelectDia(QWidget *parent,const char *name, + const QChar &_chr,const QString &_font, + int _tableNum, bool direction) + : KMainWindow(parent,name), vChr(_chr), vFont(_font) +{ + setCaption(QString::null); // Standard caption + + QWidget *mainWidget = new QWidget(this); + setCentralWidget(mainWidget); + + grid = new QGridLayout( mainWidget, 3, 4, KDialog::marginHint(), KDialog::spacingHint() ); + + // Add character selection widget from library kdeui + charSelect = new KCharSelect(mainWidget,"",vFont,vChr,_tableNum); + charSelect->resize(charSelect->sizeHint()); + connect(charSelect,SIGNAL(highlighted(const QChar &)), + SLOT(charChanged(const QChar &))); + connect(charSelect,SIGNAL(activated(const QChar &)), + SLOT(add(const QChar &))); + connect(charSelect,SIGNAL(fontChanged(const QString &)), + SLOT(fontSelected(const QString &))); + grid->addMultiCellWidget(charSelect, 0, 0, 0, 3); + + // Build line editor + lined = new QLineEdit(mainWidget); + lined->resize(lined->sizeHint()); + + QFont font = lined->font(); + font.setFamily( vFont ); + lined->setFont( font ); + + connect(lined,SIGNAL(textChanged(const QString &)), + SLOT(lineEditChanged())); + grid->addMultiCellWidget(lined, 1, 1, 0, 3); + + // Build some buttons + bHelp = new KPushButton( KStdGuiItem::help(), mainWidget ); + connect(bHelp,SIGNAL(clicked()),this,SLOT(help())); + bHelp->setFixedSize( bHelp->sizeHint() ); + grid->addWidget( bHelp, 2, 0 ); + + QSpacerItem *space = new QSpacerItem( 20, 20, QSizePolicy::Expanding ); + grid->addItem( space, 2, 1 ); + + bClear = new KPushButton( KStdGuiItem::clear(), mainWidget ); + connect(bClear,SIGNAL(clicked()),this,SLOT(clear())); + bClear->setFixedSize( bClear->sizeHint() ); + grid->addWidget( bClear, 2, 2 ); + + bClip = new KPushButton( KGuiItem( i18n( "&To Clipboard" ), + "editcopy" ), mainWidget ); + bClip->setFixedSize( bClip->sizeHint() ); + connect(bClip,SIGNAL(clicked()),this,SLOT(toClip())); + grid->addWidget( bClip, 2, 3 ); + + // Build menu + KStdAction::quit( this, SLOT(_exit()), actionCollection() ); + + new KAction(i18n("&To Clipboard"), "editcopy", + KStdAccel::shortcut(KStdAccel::Copy), this, SLOT(toClip()), actionCollection(), "copy_clip" ); + + (void)new KAction(i18n("To Clipboard &UTF-8"), 0, this, + SLOT(toClipUTF8()), actionCollection(), "copy_utf_8" ); + (void)new KAction(i18n("To Clipboard &HTML"), 0, this, + SLOT(toClipHTML()), actionCollection(), "copy_html" ); + + new KAction(i18n("&From Clipboard"), "editpaste", + KStdAccel::shortcut(KStdAccel::Paste), this, SLOT(fromClip()), actionCollection(), "from_clip" ); + (void)new KAction(i18n("From Clipboard UTF-8"), 0, this, + SLOT(fromClipUTF8()), actionCollection(), "from_clip_utf8" ); + + i18n("From Clipboard HTML"); // Intended for future use + + KStdAction::clear(this, SLOT(clear()), actionCollection(), "clear"); + (void)new KAction(i18n("&Flip"), 0, this, + SLOT(flipText()), actionCollection(), "flip" ); + (void)new KAction(i18n("&Alignment"), 0, this, + SLOT(toggleEntryDirection()), actionCollection(), "alignment" ); + + charSelect->setFocus(); + + entryDirection = direction; + if( entryDirection ) + lined->setAlignment( Qt::AlignRight ); + else + lined->setAlignment( Qt::AlignLeft ); + + setupGUI(Keys|StatusBar|Save|Create); +} + +//================================================================== +void KCharSelectDia::charChanged(const QChar &_chr) +{ + vChr = _chr; +} + +//================================================================== +void KCharSelectDia::fontSelected(const QString &_font) +{ + charSelect->setFont(_font); + + QFont font = lined->font(); + font.setFamily( _font ); + lined->setFont( font ); + + vFont = _font; +} + +//================================================================== +void KCharSelectDia::add(const QChar &_chr) +{ + QString str; + int cursorPos; + + charChanged(_chr); + + str = lined->text(); + cursorPos = lined->cursorPosition(); + str.insert( cursorPos, vChr ); + lined->setText(str); + cursorPos++; + lined->setCursorPosition( cursorPos ); +} + +//================================================================== +void KCharSelectDia::toClip() +{ + QClipboard *cb = QApplication::clipboard(); + cb->setSelectionMode( true ); + cb->setText(lined->text()); + cb->setSelectionMode( false ); + cb->setText(lined->text()); +} + +//================================================================== +// UTF-8 is rapidly becoming the favored 8-bit encoding for +// Unicode (iso10646-1). +// +void KCharSelectDia::toClipUTF8() +{ + QClipboard *cb = QApplication::clipboard(); + QString str = lined->text(); + cb->setText(str.utf8()); +} + +//================================================================== +// Put valid HTML 4.0 into the clipboard. Valid ISO-8859-1 Latin 1 +// characters are left undisturbed. Everything else, including the +// "c0 control characters" often used by Windows, are clipped +// as a HTML entity. +// +void KCharSelectDia::toClipHTML() +{ + QClipboard *cb = QApplication::clipboard(); + QString input; + QString html; + QString tempstring; + QChar tempchar; + uint i; + + input = lined->text(); + for(i=0; i< input.length(); i++ ) + { + tempchar = input.at(i); + if( tempchar.latin1() && ((tempchar.unicode() < 128) || (tempchar.unicode() >= 128+32)) ) + { + html.append(input.at(i)); + } + else + { + html.append(tempstring.sprintf("&#x%x;", tempchar.unicode())); + } + } + cb->setText(html); +} + +//================================================================== +// +void KCharSelectDia::fromClip() +{ + QClipboard *cb = QApplication::clipboard(); + lined->setText( cb->text() ); +} + +//================================================================== +// UTF-8 is rapidly becoming the favored 8-bit encoding for +// Unicode (iso10646-1). This function is handy for decoding +// UTF-8 found in legacy applications, consoles, filenames, webpages, +// etc. +// +void KCharSelectDia::fromClipUTF8() +{ + QClipboard *cb = QApplication::clipboard(); + QString str = cb->text(); + + lined->setText( str.fromUtf8( str.latin1() ) ); +} + +//================================================================== +// Reverse the text held in the line edit buffer. This is crucial +// for dealing with visual vs. logical representations of +// right to left languages, and handy for working around all +// manner of legacy character order issues. +// +void KCharSelectDia::flipText() +{ + QString input; + QString output; + uint i; + + input = lined->text(); + for(i=0; i< input.length(); i++ ) + { + output.prepend( input.at(i) ); + } + lined->setText(output); +} + +//================================================================== +void KCharSelectDia::toggleEntryDirection() +{ + entryDirection ^= 1; + if( entryDirection ) + lined->setAlignment( Qt::AlignRight ); + else + lined->setAlignment( Qt::AlignLeft ); +} + +//================================================================== +void KCharSelectDia::lineEditChanged() +{ + if( entryDirection ) + { + if(lined->cursorPosition()) + lined->setCursorPosition( lined->cursorPosition() - 1 ); + } +} + +//================================================================== +void KCharSelectDia::_exit() +{ + KConfig *config = kapp->config(); + + config->setGroup("General"); + config->writeEntry("selectedFont",vFont); + config->writeEntry("char",static_cast(vChr.unicode())); + config->writeEntry("table",charSelect->tableNum()); + config->writeEntry("entryDirection",entryDirection); + config->sync(); + + delete this; + exit(0); +} + +//================================================================== +void KCharSelectDia::clear() +{ + lined->clear(); +} + +//================================================================== +void KCharSelectDia::help() +{ + kapp->invokeHelp(); +} + diff --git a/kcharselect/kcharselectdia.h b/kcharselect/kcharselectdia.h new file mode 100644 index 0000000..a3a0ea1 --- /dev/null +++ b/kcharselect/kcharselectdia.h @@ -0,0 +1,71 @@ +/******************************************************************/ +/* KCharSelectDia - (c) by Reginald Stadlbauer 1999 */ +/* Author: Reginald Stadlbauer */ +/* E-Mail: reggie@kde.org */ +/******************************************************************/ + +#ifndef kcharselectdia_h +#define kcharselectdia_h + + +#include +#include +#include + +#include +#include +#include + +static const char *version = "v1.1"; + +/******************************************************************/ +/* class KCharSelectDia */ +/******************************************************************/ + +class KCharSelectDia : public KMainWindow +{ + Q_OBJECT + +public: + KCharSelectDia(QWidget *parent,const char *name,const QChar &_chr,const QString &_font,int _tableNum, bool direction); + + static bool selectChar(QString &_font,QChar &_chr,int _tableNum); + + int chr() { return vChr; } + QString font() { return vFont; } + +protected: + void closeEvent(QCloseEvent *) { _exit(); } + + QGridLayout *grid; + KCharSelect *charSelect; + QLineEdit *lined; + KPushButton *bClip,*bClear; + KPushButton *bHelp; + + QChar vChr; + QString vFont; + int pointSize; + bool entryDirection; + +protected slots: + void charChanged(const QChar &_chr); + void fontSelected(const QString &_font); + void add() + { add(vChr); } + void add(const QChar &_chr); + void toClip(); + void toClipUTF8(); + void toClipHTML(); + void fromClip(); + void fromClipUTF8(); + void flipText(); + void toggleEntryDirection(); + void lineEditChanged(); + void _exit(); + void clear(); + void help(); + +}; + +#endif diff --git a/kcharselect/kcharselectui.rc b/kcharselect/kcharselectui.rc new file mode 100644 index 0000000..7768293 --- /dev/null +++ b/kcharselect/kcharselectui.rc @@ -0,0 +1,16 @@ + + + + &Edit + + + + + + + + + + + + diff --git a/kcharselect/main.cc b/kcharselect/main.cc new file mode 100644 index 0000000..b3477cc --- /dev/null +++ b/kcharselect/main.cc @@ -0,0 +1,49 @@ +/******************************************************************/ +/* KCharSelectDia - (c) by Reginald Stadlbauer 1999 */ +/* Author: Reginald Stadlbauer */ +/* E-Mail: reggie@kde.org */ +/******************************************************************/ + +#include "kcharselectdia.h" + +#include +#include +#include +#include +#include + +static const char description[] = + I18N_NOOP("KDE character selection utility"); + +/*================================================================*/ +int main(int argc, char **argv) +{ + KAboutData aboutData( "kcharselect", I18N_NOOP("KCharSelect"), + version, description, KAboutData::License_GPL, + "(c) 1999, Reginald Stadlbauer"); + aboutData.addAuthor("Reginald Stadlbauer",0, "reggie@kde.org"); + aboutData.addCredit( "Nadeem Hasan", I18N_NOOP( "GUI cleanup and fixes" ), + "nhasan@kde.org" ); + aboutData.addCredit( "Ryan Cumming", I18N_NOOP( "GUI cleanup and fixes" ), + "bodnar42@phalynx.dhs.org" ); + aboutData.addCredit("Benjamin C. Meyer",I18N_NOOP("XMLUI conversion"),"ben+kcharselect@meyerhome.net"); + KCmdLineArgs::init( argc, argv, &aboutData ); + + KApplication app; + + KConfig *config = kapp->config(); + + config->setGroup("General"); + QString font(config->readEntry("selectedFont", KGlobalSettings::generalFont().family())); + QChar c = QChar(static_cast(config->readNumEntry("char",33))); + int tn = config->readNumEntry("table",0); + bool direction = config->readNumEntry("entryDirection",0); + + KCharSelectDia *dia = new KCharSelectDia(0L,"",c,font,tn,direction); + + app.setMainWidget(dia); + dia->show(); + + return app.exec(); +} + diff --git a/kdelirc/AUTHORS b/kdelirc/AUTHORS new file mode 100644 index 0000000..c6474a8 --- /dev/null +++ b/kdelirc/AUTHORS @@ -0,0 +1,3 @@ +Code mostly by Gav Wood +LIRC interface code adapted from Noatun/Infrared by Malte Starostik. + diff --git a/kdelirc/COPYING b/kdelirc/COPYING new file mode 100644 index 0000000..c13faf0 --- /dev/null +++ b/kdelirc/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/kdelirc/ChangeLog b/kdelirc/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/kdelirc/Makefile.am b/kdelirc/Makefile.am new file mode 100644 index 0000000..bb18f1c --- /dev/null +++ b/kdelirc/Makefile.am @@ -0,0 +1,3 @@ + +SUBDIRS = icons kdelirc irkick kcmlirc profiles remotes + diff --git a/kdelirc/README b/kdelirc/README new file mode 100644 index 0000000..31af5d0 --- /dev/null +++ b/kdelirc/README @@ -0,0 +1,55 @@ +kdelirc +------- + +KDELIRC is a KDE frontend for the Linux Infrared Remote Control system. It has +two aims: + +1. Provide a control center module for configuration of: + a) Application bindings to remote control buttons. + b) Actual remote controls installed (i.e. lirc configuration). + +2. Provide a system-tray applet to act as a proxy between the LIRC system and + KDE (applications), in order to launch DCOP requests (and potentially + other IPC signals) to applications (and potentially collect/display + results). + +INSTALLATION + +Nothing but the normal ./configure && make && su -c "make install". + +SETUP + +For the KDELirc system to work properly, you *must* have lircd configured and +running. If you have already had a Lirc program running, then you most likely +have Lirc set up properly. If not, be sure that you have a correct kernel module +loaded for your IR receiver (1) and that the lircd program is running (2). + +You must also have some remote controls configured in "/etc/lircd.conf". Go to +the lircd website (www.lirc.org) for more information on this. + +(1) /sbin/lsmod | grep lirc +If you see some output, you have a lirc kernel module loaded (that's not to say +it's the right module for your hardware). + +(2) ps aux | grep -v grep | grep lircd +If you see some output, you have the lircd program running. This is good. + +DESIGN + +The design of the system is really quite simple---a control center module +modifies a centralised configuration file to determine what action(s) should +be taken on a remote control's button press. + +The same(?) module also provides a front-end for the input of /etc/lircd.conf, +necessary to specify remote controls to the LIRC system. An extra (standard +format XML-based) may be provided with the remote control description to give +less sucky (lower case, no spaces/symbols) names. + +The /etc/lircd.conf frontend has not yet been implemented, though all other +features are. + +The system tray applet interfaces with LIRC in order to catch key presses on +remote controls. It is then able to communicate with and potentially start +applications through DCOP. + +Gav Wood, 2003 (gav at kde dot org). diff --git a/kdelirc/README.profile-creation b/kdelirc/README.profile-creation new file mode 100644 index 0000000..95d9e78 --- /dev/null +++ b/kdelirc/README.profile-creation @@ -0,0 +1,145 @@ +How to give your KDE application IR support under KDE. +====================================================== + +by Gav Wood, 2003. + +Introduction +------------ + +All DCOP-using applications under KDE have basic lirc support, since KDELirc has +the ability to interface any button to any DCOP call. However, to give your +application the real professional touch when using it with KDELirc, I recommend +you create a profile for it. + +A profile tells KDELirc (and the user!) what the various DCOP calls do. +Essentially this is a kind of documentation for the DCOP calls. You don't have +to include all DCOP calls - just the ones that you feel would benefit end-users +the most (usually "interface adjusting" calls rather the "information gathering" +calls). + + +Method +------ + +1. DCOP + +The first thing to do is to give your application DCOP functionality. This is +*very* easy and essentially amounts to adding a declaration to each object you +want to give DCOP accessibility and adding an entry to your Makefile. I wont go +into it here as the KDE documentation already provides a suitable resource for +such information. + +Ensure you provide a full accessibility to your application's interface by DCOP, +and especially in the case of IR-interfacing, try not to have functions with too +many parameters, or with exotic types (stick to ints and QStrings where +necessary). + +2. Create a profile + +Having coded the necessary DCOP functionality into your application, the only +other thing to do is describe how it works to the user. This is done by means of +a .profile.xml document, examples of which may be found in the kdelirc/profiles +directory. A quick guide is given here: + +a) First create top level "profile" tags with the DCOP application id and KDE +service name (found in the .desktop file) as attributes of them: + + + + + + +b) Inside populate with name and author information. If your application is not a +KUniqueApplication, you **must** declare this with an "instances" tag, giving the +attribute "unique" a value of "0" (it defaults to "1", a KUniqueApplication). You +may optionally describe the default behavior KDELirc should take should there be +more than one instance of the application, with the attribute "ifmulti" which may +take one of "dontsend" (do nothing if >1 instance), "sendtoone" (send call to one +arbitrarily chosen instance) and "sendtoall" (send to all instances). The default +is "dontsend", however, "sendtoone" may be the most useful in many circumstances. + + + + + My Application + Me + + + +c) Populate the profile with action tags, for each DCOP action you want to be +available to the user. Each action tag should have DCOP object name and function +prototype. + Several optional attrubutes to specify are the key-class (an identifier to +act as an abstract binding between remote controls and applications). There are +several defined; see the DTD files for a current list. The other options, repeat +and autostart are boolean specificers to tell whether the action should repeat +or automatically start the program by default. + + + + + My Application + Me + + + + + +d) Give the action a name and comment: + + + + + My Application + Me + + + Show Integers + Shows a configurable integer + + + +e) Describe each argument with a comment and type attribute. Valid types are +found in the profile.dtd file. If you cant find the exact type, just use one +that is silently castable. You should declare a default value between the +default tags: + + + + + My Application + Me + + + Show Integers + Shows a configurable integer + + 5 + The integer to be shown + + + + +When you have created your profile.xml file, put in your project's main source +tree. + +3. Profile installation + +There is a data directory in KDE reserved for profiles such as these; it's path +is "$(kde_datadir)/profiles". These extra lines must therefore be added to your +Makefile.am in the directory of your profile.xml: + + profiledata_DATA = [YOURAPPHERE].profile.xml + profiledatadir = $(kde_datadir)/profiles + EXTRA_DIST = $(profiledata_DATA) + +(replace [YOURAPPHERE] with your application name---the prefix to your +profile.xml file.) + + +4. Finished + +That's it you're done! Your KDE application is now fully IR enabled. diff --git a/kdelirc/README.remote-creation b/kdelirc/README.remote-creation new file mode 100644 index 0000000..3582351 --- /dev/null +++ b/kdelirc/README.remote-creation @@ -0,0 +1,129 @@ +How to give your LIRC remote control KDELIRC functionality +========================================================== + +by Gav Wood, 2003. + +Introduction +------------ + +All LIRC-understandable remote controls automatically function in KDELirc. +However, to get the advanced (really cool) KDELirc stuff you'll need to create a +remote.xml file for your remote control. The files are simple and easy to create +so don't be put off. + +The function of the remote.xml file is to describe what the remote controls' +buttons do in a general manner and to provide free-form text names for them, +since LIRC only allows non-spaces, non-symbolic charecters in the remote control +definition files. + +When you're finished your remote.xml, you might want to send it to me +(gav at kde dot org) for inclusion in the distribution of KDELirc. It may soon +be possible to distribute the remote.xml files along with the lircd.conf files. + +Method +------ + +a) Start with the basic template and define the LIRC ID of the remote control. +The LIRC ID is most important, and must be the identifier (look for the line +"name <...>" after the "begin remote" line). put the text after "name" into "id" +attribute of the "remote" tag in the "lircd.conf" file ("/etc/lircd.conf"). + In addition to this, fill in the author and name tags with your name and the +"nice" name of the remote control. Any extra information you may wish to give it +(such as alternate names, multimedia bundles/system is comes with etc) may be +enclosed between optional information tags: + + + + + + My Remote Control + Me + As bundled with ACME LinTV + + +This would compliment a "lircd.conf" file: + + begin remote + name myremote + ... + end remote + +b) With the hard work out of the way, just start going though each button on the +remote control. For each button, make sure the "id" attribute is the same as in +the lircd.conf file. + For each (common) button, you might also want to specify the class, which will +help KDELirc match it to any application's action. For a list of all button +classes, look in the remote.dtd file which comes with KDELirc. If the class type +is one which encompasses many buttons, for example "number", then you should also +specify which number it is in the parameter attribute. Currently, this only +actually applies to "number" - all other classes are simple and do not require a +parameter attribute. + Note: If no "class" is given, it will default to the "id". In the unlikely +case that this is not what you want, simply define it to be null (class=""). + + + + + + My Remote Control + Me + + + + +This would compliment a "lircd.conf" file: + + begin remote + name myremote + ... + begin raw_codes + name num0 + ... + name rec + ... + end raw_codes + end remote + +c) The last thing to define in each of your buttons is the "nice" name. This may +be descriptive and use spaces, symbols and mixed case text, in a similar fashion +to the remote control's name. There is no need to copy the remote control's label +verbatim. If necessary expand the description to provide a readable, aethetically +pleasing label e.g. you should name the "CC" button "Closed Captions" or the "Rec" +button "Record". + + + + + + My Remote Control + Me + + + + + Note: The name of a button will automatically default to its "id", so you can +save yourself some time and effort with buttons which share the same name and id +by changing + + + +to the far less cluttered and simpler: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kdelirc/remotes/cimr100.remote.xml b/kdelirc/remotes/cimr100.remote.xml new file mode 100644 index 0000000..5dfc36d --- /dev/null +++ b/kdelirc/remotes/cimr100.remote.xml @@ -0,0 +1,31 @@ + + + + + Creative CIMR-100 + Gav Wood + + + + + + + + + + + + + + + diff --git a/kdelirc/remotes/hauppauge.remote.xml b/kdelirc/remotes/hauppauge.remote.xml new file mode 100644 index 0000000..4d2a402 --- /dev/null +++ b/kdelirc/remotes/hauppauge.remote.xml @@ -0,0 +1,29 @@ + + + + + Hauppauge + Dirk Ziegelmeier + Bundled with WinTV PCI, PVR + + + + + + + + + + + + diff --git a/kdelirc/remotes/remote.dtd b/kdelirc/remotes/remote.dtd new file mode 100644 index 0000000..a09b4b6 --- /dev/null +++ b/kdelirc/remotes/remote.dtd @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/kdelirc/remotes/sherwood.remote.xml b/kdelirc/remotes/sherwood.remote.xml new file mode 100644 index 0000000..db628ba --- /dev/null +++ b/kdelirc/remotes/sherwood.remote.xml @@ -0,0 +1,61 @@ + + + + + Sherwood RM-RD-61 + Gav Wood + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kdelirc/remotes/sonytv.remote.xml b/kdelirc/remotes/sonytv.remote.xml new file mode 100644 index 0000000..4e5ee97 --- /dev/null +++ b/kdelirc/remotes/sonytv.remote.xml @@ -0,0 +1,30 @@ + + + + + SonyTV + Bundled with some Sony TVs + Dirk Ziegelmeier + + + + + + + + + + + + + diff --git a/kdessh/LICENSE.readme b/kdessh/LICENSE.readme new file mode 100644 index 0000000..eb08ce6 --- /dev/null +++ b/kdessh/LICENSE.readme @@ -0,0 +1,124 @@ +kdessh - a KDE front end to ssh + +Copyright (c) 1999,2000 by Geert Jansen + + The "Artistic License" + + Preamble + + The intent of this document is to state the conditions under which a + Package may be copied, such that the Copyright Holder maintains some + semblance of artistic control over the development of the package, + while giving the users of the package the right to use and + distribute the Package in a more-or-less customary fashion, plus the + right to make reasonable modifications. + + Definitions: + + * "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + * "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes of + the Copyright Holder. + + * "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + * "You" is you, if you're thinking about copying or distributing + this Package. + + * "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people + involved, and so on. (You will not be required to justify it to + the Copyright Holder, but only to the computing community at + large as a market that must bear the fee.) + + * "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + + 1. You may make and give away verbatim copies of the source form of + the Standard Version of this Package without restriction, provided + that you duplicate all of the original copyright notices and + associated disclaimers. + + 2. You may apply bug fixes, portability fixes and other + modifications derived from the Public Domain or from the Copyright + Holder. A Package modified in such a way shall still be considered + the Standard Version. + + 3. You may otherwise modify your copy of this Package in any way, + provided that you insert a prominent notice in each changed file + stating how and when you changed that file, and provided that you do + at least ONE of the following: + + a) place your modifications in the Public Domain or + otherwise make them Freely Available, such as by posting + said modifications to Usenet or an equivalent medium, or + placing the modifications on a major archive site such as + ftp.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation + or organization. + + c) rename any non-standard executables so the names do not + conflict with standard executables, which must also be + provided, and provide a separate manual page for each + non-standard executable that clearly documents how it + differs from the Standard Version. + + d) make other distribution arrangements with the Copyright + Holder. + + 4. You may distribute the programs of this Package in object code or + executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and + library files, together with instructions (in the manual + page or equivalent) on where to get the Standard Version. + + b) accompany the distribution with the machine-readable + source of the Package with your modifications. + + c) accompany any non-standard executables with their + corresponding Standard Version executables, giving the + non-standard executables non-standard names, and clearly + documenting the differences in manual pages (or + equivalent), together with instructions on where to get + the Standard Version. + + d) make other distribution arrangements with the Copyright + Holder. + + 5. You may charge a reasonable copying fee for any distribution of + this Package. You may charge any fee you choose for support of this + Package. You may not charge a fee for this Package itself. However, + you may distribute this Package in aggregate with other (possibly + commercial) programs as part of a larger (possibly commercial) + software distribution provided that you do not advertise this + Package as a product of your own. + + 6. The scripts and library files supplied as input to or produced as + output from the programs of this Package do not automatically fall + under the copyright of this Package, but belong to whomever + generated them, and may be sold commercially, and may be aggregated + with this Package. + + 7. C or perl subroutines supplied by you and linked into this + Package shall not be considered part of this Package. + + 8. The name of the Copyright Holder may not be used to endorse or + promote products derived from this software without specific prior + written permission. + + 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End + + diff --git a/kdessh/Makefile.am b/kdessh/Makefile.am new file mode 100644 index 0000000..987bcd7 --- /dev/null +++ b/kdessh/Makefile.am @@ -0,0 +1,17 @@ +## Makefile.am for kdessh +AM_CPPFLAGS = -DQT_NO_CAST_ASCII + +INCLUDES= $(all_includes) + +## kdessh +bin_PROGRAMS = kdessh +kdessh_SOURCES = kdessh.cpp sshdlg.cpp +kdessh_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kdessh_LDADD = $(LIB_KDEUI) -lkdesu +kdessh_METASOURCES = AUTO +noinst_HEADERS = sshdlg.h + +## Messages +messages: + $(XGETTEXT) $(kdessh_SOURCES) -o $(podir)/kdessh.pot + diff --git a/kdessh/README b/kdessh/README new file mode 100644 index 0000000..b897486 --- /dev/null +++ b/kdessh/README @@ -0,0 +1,3 @@ +kdessh: A KDE front end to ssh. + +Please report bugs to Geert Jansen . diff --git a/kdessh/kdessh.cpp b/kdessh/kdessh.cpp new file mode 100644 index 0000000..6fa10ca --- /dev/null +++ b/kdessh/kdessh.cpp @@ -0,0 +1,201 @@ +/* vi: ts=8 sts=4 sw=4 + * + * $Id$ + * + * This file is part of the KDE project, module kdesu. + * Copyright (C) 2000 Geert Jansen + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sshdlg.h" + +static KCmdLineOptions options[] = +{ + { "+host", I18N_NOOP("Specifies the remote host"), 0 }, + { "+command", I18N_NOOP("The command to run"), 0 }, + { "u ", I18N_NOOP("Specifies the target uid"), 0 }, + { "s ", I18N_NOOP("Specify remote stub location"), "kdesu_stub" }, + { "n", I18N_NOOP("Do not keep password"), 0 }, + { "q", I18N_NOOP("Stop the daemon (forgets all passwords)"), 0 }, + { "t", I18N_NOOP("Enable terminal output (no password keeping)"), 0 }, + KCmdLineLastOption +}; + + +int main(int argc, char *argv[]) +{ + KAboutData aboutData("kdessh", I18N_NOOP("KDE ssh"), + VERSION, I18N_NOOP("Runs a program on a remote host"), + KAboutData::License_Artistic, + "Copyright (c) 2000 Geert Jansen"); + aboutData.addAuthor("Geert Jansen", I18N_NOOP("Maintainer"), + "jansen@kde.org", "http://www.stack.nl/~geertj/"); + + KCmdLineArgs::init(argc, argv, &aboutData); + KCmdLineArgs::addCmdLineOptions(options); + + KApplication app; + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + // Stop daemon and exit? + if (args->isSet("q")) + { + KDEsuClient client; + if (client.ping() == -1) + { + kdError(1511) << "Daemon not running -- nothing to stop\n"; + exit(1); + } + if (client.stopServer() != -1) + { + kdDebug(1511) << "Daemon stopped\n"; + exit(0); + } + kdError(1511) << "Could not stop daemon\n"; + exit(1); + } + + if (args->count() < 2) + KCmdLineArgs::usage(i18n("No command or host specified.")); + + // Check if ssh is available + if (KStandardDirs::findExe(QString::fromLatin1("ssh")).isEmpty()) + { + kdError(1511) << "ssh not found\n"; + exit(1); + } + + // Get remote userid + QCString user = args->getOption("u"); + if (user.isNull()) + { + struct passwd *pw = getpwuid(getuid()); + if (pw == 0L) + { + kdError(1511) << "You don't exist!\n"; + exit(1); + } + user = pw->pw_name; + } + + // Remote stub location + QCString stub = args->getOption("s"); + + // Get remote host, command + QCString host = args->arg(0); + QCString command = args->arg(1); + for (int i=2; icount(); i++) + { + command += " "; + command += args->arg(i); + } + + // Check for daemon and start if necessary + bool have_daemon = true; + KDEsuClient client; + if (!client.isServerSGID()) + { + kdWarning(1511) << "Daemon not safe (not sgid), not using it.\n"; + have_daemon = false; + } + else if ((client.ping() == -1) && (client.startServer() == -1)) + { + kdWarning(1511) << "Could not start daemon, reduced functionality.\n"; + have_daemon = false; + } + + // Try to exec the command with kdesud? + bool keep = !args->isSet("n") && have_daemon; + bool terminal = args->isSet("t"); + if (keep && !terminal) + { + client.setHost(host); + if (client.exec(command, user) != -1) + return 0; + } + + // Set core dump size to 0 because we will have + // root's password in memory. + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = 0; + if (setrlimit(RLIMIT_CORE, &rlim)) + { + kdError(1511) << "rlimit(): " << perror << "\n"; + exit(1); + } + + + // Read configuration + KConfig *config = KGlobal::config(); + config->setGroup(QString::fromLatin1("Passwords")); + int timeout = config->readNumEntry(QString::fromLatin1("Timeout"), defTimeout); + + SshProcess proc(host, user); + proc.setStub(stub); + int needpw = proc.checkNeedPassword(); + if (needpw < 0) + { + QString msg = i18n("Ssh returned with an error!\n" + "The error message is:\n\n"); + msg += proc.error(); + KMessageBox::error(0L, msg); + exit(1); + } + + QCString password; + if (needpw != 0) + { + KDEsshDialog *dlg = new KDEsshDialog(host, user, stub, + proc.prompt(), keep && !terminal); + dlg->addLine(i18n("Command"), command); + int res = dlg->exec(); + if (res == KDEsshDialog::Rejected) + exit(0); + keep = dlg->keep(); + password = dlg->password(); + delete dlg; + } else + keep = 0; + + // Make the dialog go away. + app.processEvents(); + + // Run command + if (keep && have_daemon) + { + client.setHost(host); + client.setPass(password, timeout); + return client.exec(command, user); + } else + { + proc.setCommand(command); + proc.setTerminal(terminal); + proc.setErase(true); + return proc.exec(password); + } +} + diff --git a/kdessh/sshdlg.cpp b/kdessh/sshdlg.cpp new file mode 100644 index 0000000..a652688 --- /dev/null +++ b/kdessh/sshdlg.cpp @@ -0,0 +1,80 @@ +/* vi: ts=8 sts=4 sw=4 + * + * $Id$ + * + * This file is part of the KDE project, module kdesu. + * Copyright (C) 2000 Geert Jansen + */ + +#include +#include + +#include +#include "sshdlg.h" + + +KDEsshDialog::KDEsshDialog(QCString host, QCString user, QCString stub, + QString prompt, bool enableKeep) + : KPasswordDialog(Password, enableKeep, 0) +{ + m_Host = host; + m_User = user; + m_Stub = stub; + + setCaption(QString::fromLatin1("%1@%2").arg(m_User).arg(m_Host)); + + // Make the prompt a little more polite :-) + if (prompt.lower().left(6) == QString::fromLatin1("enter ")) + prompt.remove(0, 6); + int pos = prompt.find(':'); + if (pos != -1) + prompt.remove(pos, 10); + prompt += '.'; + prompt.prepend(i18n("The action you requested needs authentication. " + "Please enter ")); + setPrompt(prompt); +} + + +KDEsshDialog::~KDEsshDialog() +{ +} + + +bool KDEsshDialog::checkPassword(const char *password) +{ + SshProcess proc(m_Host, m_User); + proc.setStub(m_Stub); + + int ret = proc.checkInstall(password); + switch (ret) + { + case -1: + KMessageBox::error(this, i18n("Conversation with ssh failed.\n")); + done(Rejected); + return false; + + case 0: + return true; + + case SshProcess::SshNotFound: + KMessageBox::sorry(this, + i18n("The programs 'ssh' or 'kdesu_stub' cannot be found.\n" + "Make sure your PATH is set correctly.")); + done(Rejected); + return false; + + case SshProcess::SshIncorrectPassword: + KMessageBox::sorry(this, i18n("Incorrect password. Please try again.")); + return false; + + default: + KMessageBox::error(this, i18n("Internal error: Illegal return from " + "SshProcess::checkInstall()")); + done(Rejected); + } + return true; +} + + +#include "sshdlg.moc" diff --git a/kdessh/sshdlg.h b/kdessh/sshdlg.h new file mode 100644 index 0000000..1090312 --- /dev/null +++ b/kdessh/sshdlg.h @@ -0,0 +1,32 @@ +/* vi: ts=8 sts=4 sw=4 + * + * $Id$ + * + * This file is part of the KDE project, module kdesu. + * Copyright (C) 2000 Geert Jansen + */ + +#ifndef __SshDlg_h_Included__ +#define __SshDlg_h_Included__ + +#include + +class KDEsshDialog + : public KPasswordDialog +{ + Q_OBJECT + +public: + KDEsshDialog(QCString host, QCString user, QCString stub, + QString prompt, bool enableKeep); + ~KDEsshDialog(); + +protected: + bool checkPassword(const char *password); + +private: + QCString m_User, m_Host, m_Stub; +}; + + +#endif // __SshDlg_h_Included__ diff --git a/kdeutils.lsm b/kdeutils.lsm new file mode 100644 index 0000000..be4b71d --- /dev/null +++ b/kdeutils.lsm @@ -0,0 +1,11 @@ +Begin4 +Title: kdeutils +Version: 3.5.10 +Entered-date: 2008-08-26 +Description: Utilities for the K Desktop Environment (KDE) +Keywords: KDE X11 desktop Qt +Author: http://bugs.kde.org/ (KDE Bugtracking System) +Primary-site: http://www.kde.org/download/ +Platforms: Unix, Qt +Copying-policy: GPL, Artistic +End diff --git a/kdf/Makefile.am b/kdf/Makefile.am new file mode 100644 index 0000000..b9a81ad --- /dev/null +++ b/kdf/Makefile.am @@ -0,0 +1,37 @@ +SUBDIRS = pics + +INCLUDES= $(all_includes) + +bin_PROGRAMS = kdf kwikdisk + +noinst_LTLIBRARIES = libkdf_common.la +libkdf_common_la_SOURCES = kdfwidget.cpp kdfconfig.cpp mntconfig.cpp disklist.cpp \ + disks.cpp listview.cpp optiondialog.cpp stdoption.cpp + +kdf_SOURCES = kdf.cpp +kdf_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kdf_LDADD = libkdf_common.la $(LIB_KFILE) + +kwikdisk_SOURCES = kwikdisk.cpp +kwikdisk_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kwikdisk_LDADD = libkdf_common.la $(LIB_KFILE) + +kde_module_LTLIBRARIES = kcm_kdf.la + +kcm_kdf_la_SOURCES = kcmdf.cpp +kcm_kdf_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +kcm_kdf_la_LIBADD = libkdf_common.la $(LIB_KFILE) + +noinst_HEADERS = kdfwidget.h kcmdf.h kdfconfig.h mntconfig.h \ +disks.h kdf.h disklist.h kwikdisk.h listview.h optiondialog.h stdoption.h + +METASOURCES = AUTO + +xdg_apps_DATA = kdf.desktop kwikdisk.desktop kcmdf.desktop + +rc_DATA = kdfui.rc + +rcdir = $(kde_datadir)/kdf + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kdf.pot diff --git a/kdf/disklist.cpp b/kdf/disklist.cpp new file mode 100644 index 0000000..b2718ac --- /dev/null +++ b/kdf/disklist.cpp @@ -0,0 +1,506 @@ +/* + * disklist.cpp + * + * Copyright (c) 1999 Michael Kropfberger + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include +#include +#include +#include + +#include "disklist.h" + +#define BLANK ' ' +#define DELIMITER '#' +#define FULL_PERCENT 95.0 + +/*************************************************************************** + * constructor +**/ +DiskList::DiskList(QObject *parent, const char *name) + : QObject(parent,name) +{ + kdDebug() << k_funcinfo << endl; + + updatesDisabled = false; + + if (NO_FS_TYPE) { + kdDebug() << "df gives no FS_TYPE" << endl; + } + + disks = new Disks; + disks->setAutoDelete(TRUE); + + // BackgroundProcesses **************************************** + dfProc = new KProcess(); Q_CHECK_PTR(dfProc); + connect( dfProc, SIGNAL(receivedStdout(KProcess *, char *, int) ), + this, SLOT (receivedDFStdErrOut(KProcess *, char *, int)) ); + connect(dfProc,SIGNAL(processExited(KProcess *) ), + this, SLOT(dfDone() ) ); + + readingDFStdErrOut=FALSE; + config = kapp->config(); + loadSettings(); +} + + +/*************************************************************************** + * destructor +**/ +DiskList::~DiskList() +{ + kdDebug() << k_funcinfo << endl; +} + +/** +Updated need to be disabled sometimes to avoid pulling the DiskEntry out from the popupmenu handler +*/ +void DiskList::setUpdatesDisabled(bool disable) +{ + updatesDisabled = disable; +} + +/*************************************************************************** + * saves the KConfig for special mount/umount scripts +**/ +void DiskList::applySettings() +{ + kdDebug() << k_funcinfo << endl; + + QString oldgroup=config->group(); + config->setGroup("DiskList"); + QString key; + DiskEntry *disk; + for (disk=disks->first();disk!=0;disk=disks->next()) { + key.sprintf("Mount%s%s%s%s",SEPARATOR,disk->deviceName().latin1() + ,SEPARATOR,disk->mountPoint().latin1()); + config->writePathEntry(key,disk->mountCommand()); + + key.sprintf("Umount%s%s%s%s",SEPARATOR,disk->deviceName().latin1() + ,SEPARATOR,disk->mountPoint().latin1()); + config->writePathEntry(key,disk->umountCommand()); + + key.sprintf("Icon%s%s%s%s",SEPARATOR,disk->deviceName().latin1() + ,SEPARATOR,disk->mountPoint().latin1()); + config->writePathEntry(key,disk->realIconName()); + } + config->sync(); + config->setGroup(oldgroup); +} + + +/*************************************************************************** + * reads the KConfig for special mount/umount scripts +**/ +void DiskList::loadSettings() +{ + kdDebug() << k_funcinfo << endl; + + config->setGroup("DiskList"); + QString key; + DiskEntry *disk; + for (disk=disks->first();disk!=0;disk=disks->next()) { + key.sprintf("Mount%s%s%s%s",SEPARATOR,disk->deviceName().latin1() + ,SEPARATOR,disk->mountPoint().latin1()); + disk->setMountCommand(config->readPathEntry(key)); + + key.sprintf("Umount%s%s%s%s",SEPARATOR,disk->deviceName().latin1() + ,SEPARATOR,disk->mountPoint().latin1()); + disk->setUmountCommand(config->readPathEntry(key)); + + key.sprintf("Icon%s%s%s%s",SEPARATOR,disk->deviceName().latin1() + ,SEPARATOR,disk->mountPoint().latin1()); + QString icon=config->readPathEntry(key); + if (!icon.isEmpty()) disk->setIconName(icon); + } +} + + +static QString expandEscapes(const QString& s) { +QString rc; + for (unsigned int i = 0; i < s.length(); i++) { + if (s[i] == '\\') { + i++; + switch(s[i]) { + case '\\': // backslash '\' + rc += '\\'; + break; + case '0': // octal 0nn + rc += static_cast(s.mid(i,3).toInt(0, 8)); + i += 2; + break; + default: + // give up and not process anything else because I'm too lazy + // to implement other escapes + rc += '\\'; + rc += s[i]; + break; + } + } else { + rc += s[i]; + } + } +return rc; +} + +/*************************************************************************** + * tries to figure out the possibly mounted fs +**/ +int DiskList::readFSTAB() +{ + kdDebug() << k_funcinfo << endl; + + if (readingDFStdErrOut || dfProc->isRunning()) return -1; + +QFile f(FSTAB); + if ( f.open(IO_ReadOnly) ) { + QTextStream t (&f); + QString s; + DiskEntry *disk; + + //disks->clear(); // ############ + + while (! t.eof()) { + s=t.readLine(); + s=s.simplifyWhiteSpace(); + if ( (!s.isEmpty() ) && (s.find(DELIMITER)!=0) ) { + // not empty or commented out by '#' + // kdDebug() << "GOT: [" << s << "]" << endl; + disk = new DiskEntry();// Q_CHECK_PTR(disk); + disk->setMounted(FALSE); + disk->setDeviceName(expandEscapes(s.left(s.find(BLANK)))); + s=s.remove(0,s.find(BLANK)+1 ); + // kdDebug() << " deviceName: [" << disk->deviceName() << "]" << endl; +#ifdef _OS_SOLARIS_ + //device to fsck + s=s.remove(0,s.find(BLANK)+1 ); +#endif + disk->setMountPoint(expandEscapes(s.left(s.find(BLANK)))); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug() << " MountPoint: [" << disk->mountPoint() << "]" << endl; + //kdDebug() << " Icon: [" << disk->iconName() << "]" << endl; + disk->setFsType(s.left(s.find(BLANK)) ); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug() << " FS-Type: [" << disk->fsType() << "]" << endl; + disk->setMountOptions(s.left(s.find(BLANK)) ); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug() << " Mount-Options: [" << disk->mountOptions() << "]" << endl; + if ( (disk->deviceName() != "none") + && (disk->fsType() != "swap") + && (disk->fsType() != "sysfs") + && (disk->mountPoint() != "/dev/swap") + && (disk->mountPoint() != "/dev/pts") + && (disk->mountPoint() != "/dev/shm") + && (disk->mountPoint().find("/proc") == -1 ) ) + replaceDeviceEntry(disk); + else + delete disk; + + } //if not empty + } //while + f.close(); + } //if f.open + + loadSettings(); //to get the mountCommands + + // kdDebug() << "DiskList::readFSTAB DONE" << endl; + return 1; +} + + +/*************************************************************************** + * is called, when the df-command writes on StdOut or StdErr +**/ +void DiskList::receivedDFStdErrOut(KProcess *, char *data, int len ) +{ + kdDebug() << k_funcinfo << endl; + + + /* ATTENTION: StdERR no longer connected to this... + * Do we really need StdErr?? on HP-UX there was eg. a line + * df: /home_tu1/ijzerman/floppy: Stale NFS file handle + * but this shouldn't cause a real problem + */ + + + QString tmp = QString::fromLatin1(data, len); + dfStringErrOut.append(tmp); +} + +/*************************************************************************** + * reads the df-commands results +**/ +int DiskList::readDF() +{ + kdDebug() << k_funcinfo << endl; + + if (readingDFStdErrOut || dfProc->isRunning()) return -1; + setenv("LANG", "en_US", 1); + setenv("LC_ALL", "en_US", 1); + setenv("LC_MESSAGES", "en_US", 1); + setenv("LC_TYPE", "en_US", 1); + setenv("LANGUAGE", "en_US", 1); + dfStringErrOut=""; // yet no data received + dfProc->clearArguments(); + (*dfProc) << "env" << "LC_ALL=POSIX" << DF_COMMAND << DF_ARGS; + if (!dfProc->start( KProcess::NotifyOnExit, KProcess::AllOutput )) + qFatal(i18n("could not execute [%s]").local8Bit().data(), DF_COMMAND); + return 1; +} + + +/*************************************************************************** + * is called, when the df-command has finished +**/ +void DiskList::dfDone() +{ + kdDebug() << k_funcinfo << endl; + + if (updatesDisabled) + return; //Don't touch the data for now.. + + readingDFStdErrOut=TRUE; + for ( DiskEntry *disk=disks->first(); disk != 0; disk=disks->next() ) + disk->setMounted(FALSE); // set all devs unmounted + + QTextStream t (dfStringErrOut, IO_ReadOnly); + QString s=t.readLine(); + if ( ( s.isEmpty() ) || ( s.left(10) != "Filesystem" ) ) + qFatal("Error running df command... got [%s]",s.latin1()); + while ( !t.atEnd() ) { + QString u,v; + DiskEntry *disk; + s=t.readLine(); + s=s.simplifyWhiteSpace(); + if ( !s.isEmpty() ) { + disk = new DiskEntry(); Q_CHECK_PTR(disk); + + if (s.find(BLANK)<0) // devicename was too long, rest in next line + if ( !t.eof() ) { // just appends the next line + v=t.readLine(); + s=s.append(v.latin1() ); + s=s.simplifyWhiteSpace(); + //kdDebug() << "SPECIAL GOT: [" << s << "]" << endl; + }//if silly linefeed + + //kdDebug() << "EFFECTIVELY GOT " << s.length() << " chars: [" << s << "]" << endl; + + disk->setDeviceName(s.left(s.find(BLANK)) ); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug() << " DeviceName: [" << disk->deviceName() << "]" << endl; + + if (NO_FS_TYPE) { + //kdDebug() << "THERE IS NO FS_TYPE_FIELD!" << endl; + disk->setFsType("?"); + } else { + disk->setFsType(s.left(s.find(BLANK)) ); + s=s.remove(0,s.find(BLANK)+1 ); + }; + //kdDebug() << " FS-Type: [" << disk->fsType() << "]" << endl; + //kdDebug() << " Icon: [" << disk->iconName() << "]" << endl; + + u=s.left(s.find(BLANK)); + disk->setKBSize(u.toInt() ); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug() << " Size: [" << disk->kBSize() << "]" << endl; + + u=s.left(s.find(BLANK)); + disk->setKBUsed(u.toInt() ); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug() << " Used: [" << disk->kBUsed() << "]" << endl; + + u=s.left(s.find(BLANK)); + disk->setKBAvail(u.toInt() ); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug() << " Avail: [" << disk->kBAvail() << "]" << endl; + + + s=s.remove(0,s.find(BLANK)+1 ); // delete the capacity 94% + disk->setMountPoint(s); + //kdDebug() << " MountPoint: [" << disk->mountPoint() << "]" << endl; + + if ( (disk->kBSize() > 0) + && (disk->deviceName() != "none") + && (disk->fsType() != "swap") + && (disk->fsType() != "sysfs") + && (disk->mountPoint() != "/dev/swap") + && (disk->mountPoint() != "/dev/pts") + && (disk->mountPoint() != "/dev/shm") + && (disk->mountPoint().find("/proc") == -1 ) ) { + disk->setMounted(TRUE); // its now mounted (df lists only mounted) + replaceDeviceEntry(disk); + } else + delete disk; + + }//if not header + }//while further lines available + + readingDFStdErrOut=FALSE; + loadSettings(); //to get the mountCommands + emit readDFDone(); +} + + +void DiskList::deleteAllMountedAt(const QString &mountpoint) +{ + kdDebug() << k_funcinfo << endl; + + + for ( DiskEntry *item = disks->first(); item; ) + { + if (item->mountPoint() == mountpoint ) { + kdDebug() << "delete " << item->deviceName() << endl; + disks->remove(item); + item = disks->current(); + } else + item = disks->next(); + } +} + +/*************************************************************************** + * updates or creates a new DiskEntry in the KDFList and TabListBox +**/ +void DiskList::replaceDeviceEntry(DiskEntry *disk) +{ + //kdDebug() << k_funcinfo << disk->deviceRealName() << " " << disk->realMountPoint() << endl; + + // + // The 'disks' may already already contain the 'disk'. If it do + // we will replace some data. Otherwise 'disk' will be added to the list + // + + // + // 1999-27-11 Espen Sand: + // I can't get find() to work. The Disks::compareItems(..) is + // never called. + // + //int pos=disks->find(disk); + + QString deviceRealName = disk->deviceRealName(); + QString realMountPoint = disk->realMountPoint(); + + int pos = -1; + for( u_int i=0; icount(); i++ ) + { + DiskEntry *item = disks->at(i); + int res = deviceRealName.compare( item->deviceRealName() ); + if( res == 0 ) + { + res = realMountPoint.compare( item->realMountPoint() ); + } + if( res == 0 ) + { + pos = i; + break; + } + } + + if ((pos == -1) && (disk->mounted()) ) + // no matching entry found for mounted disk + if ((disk->fsType() == "?") || (disk->fsType() == "cachefs")) { + //search for fitting cachefs-entry in static /etc/vfstab-data + DiskEntry* olddisk = disks->first(); + while (olddisk != 0) { + int p; + // cachefs deviceNames have no / behind the host-column + // eg. /cache/cache/.cfs_mnt_points/srv:_home_jesus + // ^ ^ + QString odiskName = olddisk->deviceName(); + int ci=odiskName.find(':'); // goto host-column + while ((ci =odiskName.find('/',ci)) > 0) { + odiskName.replace(ci,1,"_"); + }//while + // check if there is something that is exactly the tail + // eg. [srv:/tmp3] is exact tail of [/cache/.cfs_mnt_points/srv:_tmp3] + if ( ( (p=disk->deviceName().findRev(odiskName + ,disk->deviceName().length()) ) + != -1) + && (p + odiskName.length() + == disk->deviceName().length()) ) + { + pos = disks->at(); //store the actual position + disk->setDeviceName(olddisk->deviceName()); + olddisk=0; + } else + olddisk=disks->next(); + }// while + }// if fsType == "?" or "cachefs" + + +#ifdef NO_FS_TYPE + if (pos != -1) { + DiskEntry * olddisk = disks->at(pos); + if (olddisk) + disk->setFsType(olddisk->fsType()); + } +#endif + + if (pos != -1) { // replace + DiskEntry * olddisk = disks->at(pos); + if ( (-1!=olddisk->mountOptions().find("user")) && + (-1==disk->mountOptions().find("user")) ) { + // add "user" option to new diskEntry + QString s=disk->mountOptions(); + if (s.length()>0) s.append(","); + s.append("user"); + disk->setMountOptions(s); + } + disk->setMountCommand(olddisk->mountCommand()); + disk->setUmountCommand(olddisk->umountCommand()); + + // Same device name, but maybe one is a symlink and the other is its target + // Keep the shorter one then, /dev/hda1 looks better than /dev/ide/host0/bus0/target0/lun0/part1 + if ( disk->deviceName().length() > olddisk->deviceName().length() ) + disk->setDeviceName(olddisk->deviceName()); + + //FStab after an older DF ... needed for critFull + //so the DF-KBUsed survive a FStab lookup... + //but also an unmounted disk may then have a kbused set... + if ( (olddisk->mounted()) && (!disk->mounted()) ) { + disk->setKBSize(olddisk->kBSize()); + disk->setKBUsed(olddisk->kBUsed()); + disk->setKBAvail(olddisk->kBAvail()); + } + if ( (olddisk->percentFull() != -1) && + (olddisk->percentFull() < FULL_PERCENT) && + (disk->percentFull() >= FULL_PERCENT) ) { + kdDebug() << "Device " << disk->deviceName() + << " is critFull! " << olddisk->percentFull() + << "--" << disk->percentFull() << endl; + emit criticallyFull(disk); + } + disks->remove(pos); // really deletes old one + disks->insert(pos,disk); + } else { + disks->append(disk); + }//if + +} + +#include "disklist.moc" + + + + + + diff --git a/kdf/disklist.h b/kdf/disklist.h new file mode 100644 index 0000000..7a99841 --- /dev/null +++ b/kdf/disklist.h @@ -0,0 +1,138 @@ +/* + * disklist.h + * + * Copyright (c) 1999 Michael Kropfberger + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __DISKLIST_H__ +#define __DISKLIST_H__ + +#include +#include +#include +//#include + +// defines the os-type +#include + +#include "disks.h" + +#define DF_COMMAND "df" +// be pessimistic: df -T only works under linux !?? +#if defined(_OS_LINUX_) +#define DF_ARGS "-kT" +#define NO_FS_TYPE false +#else +#define DF_ARGS "-k" +#define NO_FS_TYPE true +#endif + +#ifdef _OS_SOLARIS_ +#define CACHEFSTAB "/etc/cachefstab" +#define FSTAB "/etc/vfstab" +#else +#define FSTAB "/etc/fstab" +#endif + +#define SEPARATOR "|" + +/***************************************************************************/ +typedef QPtrList DisksBase; +typedef QPtrListIterator DisksIterator; + +/***************************************************************************/ +class Disks : public DisksBase +{ + public: + Disks(bool deepCopies=TRUE) { dc = deepCopies;} + ~Disks() { clear(); } +private: + int compareItems( DiskEntry s1, DiskEntry s2 ) + { + int ret = s1.deviceName().compare(s2.deviceName()); + if( ret == 0 ) + { + ret = s1.mountPoint().compare(s2.mountPoint()); + } + + kdDebug() << "compareDISKS " << s1.deviceName() << " vs " << s2.deviceName() << " (" << ret << ")" << endl; + return( ret ); + } + + /* + int compareItems( DiskEntry* s1, DiskEntry* s2 ) { + int ret; + ret = strcmp (static_cast(s1)->deviceName(), + static_cast(s2)->deviceName() ); + if (0 == ret) + ret = strcmp (static_cast(s1)->mountPoint(), + static_cast(s2)->mountPoint()); + return ret; + }; + */ + + bool dc; +}; + +/***************************************************************************/ +class DiskList : public QObject +{ Q_OBJECT +public: + DiskList( QObject *parent=0, const char *name=0 ); + ~DiskList(); + int readFSTAB(); + int readDF(); + int find(const DiskEntry* disk) {return disks->find(disk);} + DiskEntry* at(uint index) {return disks->at(index);} + DiskEntry* first() {return disks->first();} + DiskEntry* next() {return disks->next();} + uint count() { return disks->count(); } + + void deleteAllMountedAt(const QString &mountpoint); + void setUpdatesDisabled(bool disable); + +signals: + void readDFDone(); + void criticallyFull(DiskEntry *disk); + +public slots: + void loadSettings(); + void applySettings(); + +private slots: + void receivedDFStdErrOut(KProcess *, char *data, int len); + void dfDone(); + +private: + void replaceDeviceEntry(DiskEntry *disk); + + Disks *disks; + KProcess *dfProc; + QString dfStringErrOut; + bool readingDFStdErrOut; + KConfig *config; + bool updatesDisabled; + +}; +/***************************************************************************/ + + +#endif diff --git a/kdf/disks.cpp b/kdf/disks.cpp new file mode 100644 index 0000000..c1a4a0e --- /dev/null +++ b/kdf/disks.cpp @@ -0,0 +1,335 @@ +/* + * disks.cpp + * + * Copyright (c) 1998 Michael Kropfberger + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include +#include + +#include "disks.h" +#include "disks.moc" + +/****************************************************/ +/********************* DiskEntry ********************/ +/****************************************************/ + +/** + * Constructor +**/ +void DiskEntry::init() +{ + device=""; + type=""; + mountedOn=""; + options=""; + size=0; + used=0; + avail=0; + isMounted=FALSE; + mntcmd=""; + umntcmd=""; + iconSetByUser=FALSE; + icoName=""; + + + // BackgroundProcesses **************************************** + + sysProc = new KShellProcess(); Q_CHECK_PTR(sysProc); + connect( sysProc, SIGNAL(receivedStdout(KProcess *, char *, int) ), + this, SLOT (receivedSysStdErrOut(KProcess *, char *, int)) ); + connect( sysProc, SIGNAL(receivedStderr(KProcess *, char *, int) ), + this, SLOT (receivedSysStdErrOut(KProcess *, char *, int)) ); + readingSysStdErrOut=FALSE; + + +} + +DiskEntry::DiskEntry(QObject *parent, const char *name) + : QObject (parent, name) +{ + init(); +} + +DiskEntry::DiskEntry(const QString & deviceName, QObject *parent, const char *name) + : QObject (parent, name) +{ + init(); + + setDeviceName(deviceName); +} +DiskEntry::~DiskEntry() +{ + disconnect(this); + delete sysProc; +} + +int DiskEntry::toggleMount() +{ + if (!mounted()) + return mount(); + else + return umount(); +} + +int DiskEntry::mount() +{ + QString cmdS=mntcmd; + if (cmdS.isEmpty()) // generate default mount cmd + if (getuid()!=0 ) // user mountable + { + cmdS="mount %d"; + } + else // root mounts with all params/options + { + // FreeBSD's mount(8) is picky: -o _must_ go before + // the device and mountpoint. + cmdS=QString::fromLatin1("mount -t%t -o%o %d %m"); + } + + cmdS.replace(QString::fromLatin1("%d"),deviceName()); + cmdS.replace(QString::fromLatin1("%m"),mountPoint()); + cmdS.replace(QString::fromLatin1("%t"),fsType()); + cmdS.replace(QString::fromLatin1("%o"),mountOptions()); + + kdDebug() << "mount-cmd: [" << cmdS << "]" << endl; + int e=sysCall(cmdS); + if (!e) setMounted(TRUE); + kdDebug() << "mount-cmd: e=" << e << endl; + return e; +} + +int DiskEntry::umount() +{ + kdDebug() << "umounting" << endl; + QString cmdS=umntcmd; + if (cmdS.isEmpty()) // generate default umount cmd + cmdS="umount %d"; + + cmdS.replace(QString::fromLatin1("%d"),deviceName()); + cmdS.replace(QString::fromLatin1("%m"),mountPoint()); + + kdDebug() << "umount-cmd: [" << cmdS << "]" << endl; + int e=sysCall(cmdS); + if (!e) setMounted(FALSE); + kdDebug() << "umount-cmd: e=" << e << endl; + + return e; +} + +int DiskEntry::remount() +{ + if (mntcmd.isEmpty() && umntcmd.isEmpty() // default mount/umount commands + && (getuid()==0)) // you are root + { + QString oldOpt=options; + if (options.isEmpty()) + options="remount"; + else + options+=",remount"; + int e=mount(); + options=oldOpt; + return e; + } else { + if (int e=umount()) + return mount(); + else return e; + } +} + +void DiskEntry::setMountCommand(const QString & mnt) +{ + mntcmd=mnt; +} + +void DiskEntry::setUmountCommand(const QString & umnt) +{ + umntcmd=umnt; +} + +void DiskEntry::setIconName(const QString & iconName) +{ + iconSetByUser=TRUE; + icoName=iconName; + if (icoName.right(6) == "_mount") + icoName.truncate(icoName.length()-6); + else if (icoName.right(8) == "_unmount") + icoName.truncate(icoName.length()-8); + + emit iconNameChanged(); +} + +QString DiskEntry::iconName() +{ + QString iconName=icoName; + if (iconSetByUser) { + mounted() ? iconName+="_mount" : iconName+="_unmount"; + return iconName; + } else + return guessIconName(); +} + +QString DiskEntry::guessIconName() +{ + QString iconName; + // try to be intelligent + if (-1!=mountPoint().find("cdrom",0,FALSE)) iconName+="cdrom"; + else if (-1!=deviceName().find("cdrom",0,FALSE)) iconName+="cdrom"; + else if (-1!=mountPoint().find("writer",0,FALSE)) iconName+="cdwriter"; + else if (-1!=deviceName().find("writer",0,FALSE)) iconName+="cdwriter"; + else if (-1!=mountPoint().find("mo",0,FALSE)) iconName+="mo"; + else if (-1!=deviceName().find("mo",0,FALSE)) iconName+="mo"; + else if (-1!=deviceName().find("fd",0,FALSE)) { + if (-1!=deviceName().find("360",0,FALSE)) iconName+="5floppy"; + if (-1!=deviceName().find("1200",0,FALSE)) iconName+="5floppy"; + else iconName+="3floppy"; + } + else if (-1!=mountPoint().find("floppy",0,FALSE)) iconName+="3floppy"; + else if (-1!=mountPoint().find("zip",0,FALSE)) iconName+="zip"; + else if (-1!=fsType().find("nfs",0,FALSE)) iconName+="nfs"; + else iconName+="hdd"; + mounted() ? iconName+="_mount" : iconName+="_unmount"; +// if ( -1==mountOptions().find("user",0,FALSE) ) +// iconName.prepend("root_"); // special root icon, normal user cant mount + + //debug("device %s is %s",deviceName().latin1(),iconName.latin1()); + + //emit iconNameChanged(); + return iconName; +} + + +/*************************************************************************** + * starts a command on the underlying system via /bin/sh +**/ +int DiskEntry::sysCall(const QString & command) +{ + if (readingSysStdErrOut || sysProc->isRunning() ) return -1; + + sysStringErrOut=i18n("Called: %1\n\n").arg(command); // put the called command on ErrOut + sysProc->clearArguments(); + (*sysProc) << command; + if (!sysProc->start( KProcess::Block, KProcess::AllOutput )) + kdFatal() << i18n("could not execute %1").arg(command.local8Bit().data()) << endl; + + if (sysProc->exitStatus()!=0) emit sysCallError(this, sysProc->exitStatus()); + + return (sysProc->exitStatus()); +} + + +/*************************************************************************** + * is called, when the Sys-command writes on StdOut or StdErr +**/ +void DiskEntry::receivedSysStdErrOut(KProcess *, char *data, int len) +{ + QString tmp = QString::fromLocal8Bit(data, len); + sysStringErrOut.append(tmp); +} + +float DiskEntry::percentFull() const +{ + if (size != 0) { + return 100 - ( ((float)avail / (float)size) * 100 ); + } else { + return -1; + } +} + +void DiskEntry::setDeviceName(const QString & deviceName) +{ + device=deviceName; + emit deviceNameChanged(); +} + +QString DiskEntry::deviceRealName() const +{ + QFileInfo inf( device ); + QDir dir( inf.dirPath( true ) ); + QString relPath = inf.fileName(); + if ( inf.isSymLink() ) { + QString link = inf.readLink(); + if ( link.startsWith( "/" ) ) + return link; + relPath = link; + } + return dir.canonicalPath() + "/" + relPath; +} + +void DiskEntry::setMountPoint(const QString & mountPoint) +{ + mountedOn=mountPoint; + emit mountPointChanged(); +} + +QString DiskEntry::realMountPoint() const +{ + QDir dir( mountedOn ); + return dir.canonicalPath(); +} + +void DiskEntry::setMountOptions(const QString & mountOptions) +{ + options=mountOptions; + emit mountOptionsChanged(); +} + +void DiskEntry::setFsType(const QString & fsType) +{ + type=fsType; + emit fsTypeChanged(); +} + +void DiskEntry::setMounted(bool nowMounted) +{ + isMounted=nowMounted; + emit mountedChanged(); +} + +void DiskEntry::setKBSize(int kb_size) +{ + size=kb_size; + emit kBSizeChanged(); +} + +void DiskEntry::setKBUsed(int kb_used) +{ + used=kb_used; + if ( size < (used+avail) ) { //adjust kBAvail + kdWarning() << "device " << device << ": kBAvail(" << avail << ")+*kBUsed(" << used << ") exceeds kBSize(" << size << ")" << endl; + setKBAvail(size-used); + } + emit kBUsedChanged(); +} + +void DiskEntry::setKBAvail(int kb_avail) +{ + avail=kb_avail; + if ( size < (used+avail) ) { //adjust kBUsed + kdWarning() << "device " << device << ": *kBAvail(" << avail << ")+kBUsed(" << used << ") exceeds kBSize(" << size << ")" << endl; + setKBUsed(size-avail); + } + emit kBAvailChanged(); +} + + diff --git a/kdf/disks.h b/kdf/disks.h new file mode 100644 index 0000000..9899927 --- /dev/null +++ b/kdf/disks.h @@ -0,0 +1,148 @@ +/* + * disks.h + * + * Copyright (c) 1998 Michael Kropfberger + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __DISKS_H__ +#define __DISKS_H__ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +class DiskEntry : public QObject +{ + Q_OBJECT +public: + DiskEntry(QObject *parent=0, const char *name=0); + DiskEntry(const QString & deviceName, QObject *parent=0, const char *name=0); + ~DiskEntry(); + QString lastSysError() {return sysStringErrOut; } + QString deviceName() const { return device; } + // The real device (in case deviceName() is a symlink) + QString deviceRealName() const; + QString mountPoint() const { return mountedOn; } + QString mountOptions() const { return options; } + // The real device (in case deviceName() is a symlink) + QString realMountPoint() const; + /** + * sets the used mountCommand for the actual DiskEntry. + * @param mntcmd is a string containing the executable file and + * special codes which will be filled in when used:
+ * %m : mountpoint
+ * %d : deviceName
+ * %t : filesystem type
+ * %o : mount options
+ * all this information is gained from the objects' data + * if no mountCommand is set it defaults to "mount %d" + **/ + QString mountCommand() const { return mntcmd; } + /** + * sets the used umountCommand for the actual DiskEntry. + * @param mntcmd is a string containing the executable file and + * special codes which will be filled in when used:
+ * %m : mountpoint
+ * %d : deviceName
+ * all this information is gained from the objects' data + * if no umountCommand is set it defaults to "umount %d" + **/ + QString umountCommand() const { return umntcmd; } + QString fsType() const { return type; } + bool mounted() const { return isMounted; } + int kBSize() const { return size; } + QString iconName(); + QString realIconName() { return icoName; } + QString prettyKBSize() const { return KIO::convertSizeFromKB(size); } + int kBUsed() const { return used; } + QString prettyKBUsed() const { return KIO::convertSizeFromKB(used); } + int kBAvail() const { return avail; } + QString prettyKBAvail() const { return KIO::convertSizeFromKB(avail); } + float percentFull() const; + +signals: + void sysCallError(DiskEntry *disk, int err_no); + void deviceNameChanged(); + void mountPointChanged(); + void mountOptionsChanged(); + void fsTypeChanged(); + void mountedChanged(); + void kBSizeChanged(); + void kBUsedChanged(); + void kBAvailChanged(); + void iconNameChanged(); + +public slots: + + int toggleMount(); + int mount(); + int umount(); + int remount(); + void setMountCommand(const QString & mnt); + void setUmountCommand(const QString & umnt); + void setDeviceName(const QString & deviceName); + void setMountPoint(const QString & mountPoint); + void setIconName(const QString & iconName); + void setMountOptions(const QString & mountOptions); + void setFsType(const QString & fsType); + void setMounted(bool nowMounted); + void setKBSize(int kb_size); + void setKBUsed(int kb_used); + void setKBAvail(int kb_avail); + QString guessIconName(); + +private slots: + void receivedSysStdErrOut(KProcess *, char *data, int len); + +private: + void init(); + int sysCall(const QString & command); + QString prettyPrint(int kBValue) const; + + KShellProcess *sysProc; + QString sysStringErrOut; + bool readingSysStdErrOut; + + QString device, + type, + mountedOn, + options, + icoName, + mntcmd, + umntcmd; + + int size, + used, + avail; // ATTENTION: used+avail != size (clustersize!) + + bool isMounted, + iconSetByUser; +}; + +#endif diff --git a/kdf/kcmdf.cpp b/kdf/kcmdf.cpp new file mode 100644 index 0000000..3c30a01 --- /dev/null +++ b/kdf/kcmdf.cpp @@ -0,0 +1,66 @@ +/* + kcmdf.cpp - KcmDiskFree + + Copyright (C) 1998 by Michael Kropfberger + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + +// +// 1999-12-05 Espen Sand +// Modified to use KCModule instead of the old and obsolete +// KControlApplication +// + + +#include + +#include + +#include "kcmdf.h" + +KDiskFreeWidget::KDiskFreeWidget( QWidget *parent, const char *name ) + : KCModule( parent, name ) +{ + setButtons(Help); + + QVBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() ); + + mKdf = new KDFWidget( this, "kdf", false ); + topLayout->addWidget( mKdf ); +} + +KDiskFreeWidget::~KDiskFreeWidget() +{ + mKdf->applySettings(); +} + +QString KDiskFreeWidget::quickHelp() const +{ + return i18n("

Hardware Information


All the information modules return information" + " about a certain aspect of your computer hardware or your operating system." + " Not all modules are available on all hardware architectures and/or operating systems."); +} + +extern "C" +{ + KDE_EXPORT KCModule* create_kdf( QWidget *parent, const char * /*name*/ ) + { + return new KDiskFreeWidget( parent , "kdf" ); + } +} + +#include "kcmdf.moc" diff --git a/kdf/kcmdf.desktop b/kdf/kcmdf.desktop new file mode 100644 index 0000000..3513576 --- /dev/null +++ b/kdf/kcmdf.desktop @@ -0,0 +1,138 @@ +[Desktop Entry] +X-KDE-ModuleType=Library +X-KDE-Library=kdf +X-KDE-FactoryName=kdf +X-KDE-LocalUser=false +Exec=kcmshell kcmdf +Icon=kcmdf +Type=Application +Name=Storage Devices +Name[af]=Stoorplek Toestelle +Name[ar]=أجهزة تخزين +Name[bg]=Твърди дискове +Name[bs]=Uređaji za smještaj +Name[ca]=Dispositius d'emmagatzemament +Name[cs]=Úložná zařízení +Name[cy]=Dyfeisiau Storio +Name[da]=Opbevaringsenheder +Name[de]=Speichergeräte +Name[el]=Συσκευές αποθήκευσης +Name[eo]=Memor-aparatoj +Name[es]=Dispositivos de almacenamiento +Name[et]=Salvestusseadmed +Name[eu]=Biltegiratze Gailuak +Name[fa]=دستگاههای ذخیره +Name[fi]=Tallennuslaitteet +Name[fr]=Périphériques de stockage +Name[ga]=Gléasanna Stórais +Name[gl]=Dispositivos de Almaceamento +Name[he]=התקני איחסון +Name[hi]=भंडारण औज़ार +Name[hr]=Skladišni uređaji +Name[hu]=Tárolóeszközök +Name[is]=Minnisbúnaður +Name[it]=Dispositivi di memorizzazione +Name[ja]=ストレージデバイス +Name[ka]=ინფორმაციის შემნახველი მოწყობილობები +Name[kk]=Жинақтаушы құрылғылар +Name[km]=ឧបករណ៍​ផ្ទុក +Name[lt]=Saugojimo įrenginiai +Name[mk]=Уреди за складирање +Name[mt]=Apparat għas-sarr ta' informazzjoni +Name[nb]=Lagringsenheter +Name[nds]=Spiekerreedschappen +Name[ne]=यन्त्र भण्डारण गर्नुहोस् +Name[nl]=Opslagapparaten +Name[nn]=Lagringseiningar +Name[pa]=ਸਟੋਰੇਜ਼ ਜੰਤਰ +Name[pl]=Urządzenia do przechowywania danych +Name[pt]=Dispositivos de Armazenamento +Name[pt_BR]=Dispositivos de Armazenamento +Name[ro]=Dispozitive de stocare +Name[ru]=Устройства хранения данных +Name[sk]=Disky +Name[sl]=Naprave za shranjevanje +Name[sr]=Складишни уређаји +Name[sr@Latn]=Skladišni uređaji +Name[sv]=Lagringsenheter +Name[ta]= சேமிப்பு சாதனங்கள் +Name[tg]=Дастгоҳҳои Захиракунӣ +Name[th]=อุปกรณ์เก็บข้อมูล +Name[tr]=Depolama Aygıtları +Name[uk]=Пристрої накопичення +Name[uz]=Saqlash uskunalari +Name[uz@cyrillic]=Сақлаш ускуналари +Name[wa]=Éndjins di wårdaedje +Name[xh]=Amacebo Okugcina +Name[zh_CN]=存储设备 +Name[zh_TW]=儲存裝置 +Name[zu]=Amathuluzi Ethala +DocPath=kinfocenter/blockdevices/index.html +Comment=Shows the disk usage of the mounted devices +Comment[af]=Vertoon die disket gebruik van die gekoppelde toestelle +Comment[ar]=يعرض المساحة المستخدمة من الأقراص المضمومة +Comment[az]=Bağlı avadanlıqların disk istifadəsini göstərir +Comment[bg]=Информация за използваното пространство на монтираните устройства +Comment[br]=Diskouez an egor implijet gant an trobarzhelloù marc'het +Comment[bs]=Prikazuje iskorištenost diskova na montiranim uređajima +Comment[ca]=Mostra l'ús de disc dels dispositius muntats +Comment[cs]=Zobrazuje využití připojených diskových zařízení +Comment[cy]=Dangos defnydd disg y dyfeisiau mowntiedig +Comment[da]=Viser monterede enheders diskforbrug +Comment[de]=Zeigt die Speicherbelegung eingebundener Geräte +Comment[el]=Εμφανίζει τη χρήση αποθηκευτικού χώρου των προσαρτημένων συσκευών +Comment[eo]=Montras la kapacitojn de la kroĉitaj aparatoj +Comment[es]=Muestra el uso del disco en los dispositivos montados +Comment[et]=Ühendatud seadmete kettakasutuse vaatamine +Comment[eu]=Muntatutako diskoen erabilera erakusten du +Comment[fa]=استفادۀ دیسک دستگاههای سوار‌شده را نمایش می‌دهد +Comment[fi]=Näyttää levynkäytön liitetyillä laitteilla +Comment[fr]=Affiche l'espace utilisé sur les périphériques montés +Comment[ga]=Taispeánann úsáid diosca na ngléasanna feistithe +Comment[gl]=Amosa o uso do disco dos dispositivos montados +Comment[he]=מידע על השימוש בנפח האיחסון של ההתקנים המחוברים +Comment[hi]=माउन्टेड औज़ारों के डिस्क उपयोग दिखाता है +Comment[hr]=Prikazuje iskorištenost diskova +Comment[hu]=Megmutatja a csatlakoztatott (mountolt) eszközök kihasználtságát +Comment[id]=Perlihatkan penggunanan disk yang sedang dimount +Comment[is]=Sýnir nýtingu diskanna sem eru tengdir skráarkerfinu +Comment[it]=Mostra l'uso del disco dei dispositivi montati +Comment[ja]=マウントされているデバイスのディスク使用状況を表示 +Comment[ka]=მონტირებული დისკების გამოყენებას +Comment[kk]=Тіркеген құрылғыларда бар орынды көрсетеді +Comment[km]=បង្ហាញ​ការប្រើប្រាស់​ថាស​របស់​ឧបករណ៍​ដែល​បាន​ម៉ោន +Comment[ko]=마운트된 장치의 디스크 사용을 보여줍니다. +Comment[lt]=Rodo sumontuotų įrenginių disko vietos panaudojimą +Comment[lv]=Rāda piemontēto iekārtu diska izlietošanu +Comment[mk]=Ја покажува искористеноста на монтираните уреди +Comment[ms]=Memaparkan penggunaan cakera pada peranti yang dilekapkan +Comment[mt]=Juri kemm qed jintuża mid-diski mmuntati +Comment[nb]=Viser brukt diskplass på de monterte enhetene +Comment[nds]=Wiest den Fastplattbruuk vun inhangt Reedschappen +Comment[ne]=माउन्ट गरिएको यन्त्रका डिस्क उपयोग देखाउँदछ +Comment[nl]=Toont het schijfgebruik van de aangekoppelde bestandssystemen +Comment[nn]=Viser diskbruken for monterte einingar +Comment[pa]=ਮਾਊਟ ਕੀਤੇ ਜੰਤਰ ਵੇਖਾਉਦਾ ਹੈ +Comment[pl]=Pokazuje wykorzystanie przestrzeni dyskowej na zamontowanych urządzeniach +Comment[pt]=Mostra o espaço ocupado nos dispositivos montados +Comment[pt_BR]=Mostra a utilização do disco nos dispositivos montados +Comment[ro]=Afişează utilizarea spaţiului pentru dispozitivele montate +Comment[ru]=Показывает свободное место на смонтированных устройствах +Comment[sk]=Ukazuje využité miesto na pripojených diskových zariadeniach +Comment[sl]=Prikaže porabo diska v priklopljenih napravah +Comment[sr]=Приказује искоришћеност капацитета монтираних дискова +Comment[sr@Latn]=Prikazuje iskorišćenost kapaciteta montiranih diskova +Comment[sv]=Visar diskanvändning för monterade enheter +Comment[ta]= ஏற்றப்பட்ட சாதனங்களின் வட்டு பயன்பாட்டை காட்டுகிறது +Comment[tg]=Фазоҳои хомро дар дастгоҳи насбшуда нишон диҳед +Comment[th]=แสดงการใช้พื้นทีี่ของดิสก์ที่เมานท์ใช้งานอยู่ +Comment[tr]=Bağlı aygıtların disk kullanımını gösterir +Comment[uk]=Показує ступінь використання змонтованих пристроїв +Comment[ven]=I sumbedza mashumisele a maano o gonyiswaho +Comment[vi]=Hiển thềEtrạng thái sử dụng đĩa của các thiết bềEđã được mount +Comment[wa]=Mostere l' eployaedje des deurès plakes ki sont montêyes +Comment[zh_CN]=显示挂接设备的磁盘使用率 +Comment[zh_TW]=顯示連接的設備的磁碟使用率 +Comment[zu]=Ikhombisa ukusebenziswa kwediski yamathuluzi okunyuka + +Categories=Qt;KDE;X-KDE-information; diff --git a/kdf/kcmdf.h b/kdf/kcmdf.h new file mode 100644 index 0000000..c3e2b58 --- /dev/null +++ b/kdf/kcmdf.h @@ -0,0 +1,49 @@ +/* + kcmdf.h - KDiskFree + + Copyright (C) 1999 by Michael Kropfberger + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + + +#ifndef __KCMDF_H__ +#define __KCMDF_H__ + +#include "kdfwidget.h" +#include "kdfconfig.h" +#include "mntconfig.h" + +#include +#include + +class KDiskFreeWidget : public KCModule +{ + Q_OBJECT + + public: + KDiskFreeWidget( QWidget *parent=0, const char *name=0 ); + ~KDiskFreeWidget(); + + QString quickHelp() const; + + private: + KDFWidget *mKdf; + KDFConfigWidget *mMcw; + MntConfigWidget *mKcw; +}; + +#endif diff --git a/kdf/kconftest.cpp b/kdf/kconftest.cpp new file mode 100644 index 0000000..75d13fd --- /dev/null +++ b/kdf/kconftest.cpp @@ -0,0 +1,80 @@ +/* +** +** Copyright (C) 1999 by Michael Kropfberger +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ + + +/* compile with +* gcc -I$QTDIR/include -I$KDEDIR/include -L/opt/kde/lib -L/usr/X11R6/lib -lkfm -lkdeui -lkdecore -lqt -lX11 -lXext -fno-rtti kconftest.cpp +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char description[] = + I18N_NOOP("A test application"); + +static const char version[] = "v0.0.1"; + +main(int argc, char ** argv) +{ + KCmdLineArgs::init(argc, argv, "test", description, version); + + KApplication app; + KConfig * cfg = kapp->config(); + + QDict dict; + + dict.insert("Blah", "Arse"); + dict.insert("Blah", "Smack"); + dict.insert("Blah", "Monkey"); + + QDictIterator it(dict); + + QString key = "TestConfigItem"; + + for (; it.current(); ++it) { + + cerr << "Before saving: " << endl; + cerr << "key : \"" << key << "\"" << endl; + cerr << "val : \"" << it.current() << "\"" << endl; + + debug("got back [%s]",cfg->writeEntry(key, it.current())); +// debug("got back [%s]",s.data()); + + cerr << "After saving: " << endl; + cerr << "key : \"" << key << "\"" << endl; + cerr << "val : \"" << it.current() << "\"" << endl; + + cerr << endl; + } +} diff --git a/kdf/kdf.cpp b/kdf/kdf.cpp new file mode 100644 index 0000000..f48cf48 --- /dev/null +++ b/kdf/kdf.cpp @@ -0,0 +1,96 @@ +/* + * kdf.cpp - KDiskFree + * + * written 1998-2001 by Michael Kropfberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "kdf.h" +#include + +static const char description[] = + I18N_NOOP("KDE free disk space utility"); + +static const char version[] = "v0.5"; + + +/***************************************************************/ +KDFTopLevel::KDFTopLevel(QWidget *, const char *name) + : KMainWindow(0, name) +{ + kdf = new KDFWidget(this,"kdf",FALSE); + Q_CHECK_PTR(kdf); + (void) new KAction( i18n( "&Update" ), 0, kdf, SLOT( updateDF() ), actionCollection(), "updatedf" ); + + KStdAction::quit(this, SLOT(close()), actionCollection()); + KStdAction::preferences(kdf, SLOT(settingsBtnClicked()), actionCollection()); + KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), +actionCollection()); + setCentralWidget(kdf); + // kdf->setMinimumSize(kdf->sizeHint()); + kdf->resize(kdf->sizeHint()); + setupGUI(KMainWindow::Keys | StatusBar | Save | Create); +} + + +bool KDFTopLevel::queryExit( void ) +{ + kdf->applySettings(); + return( true ); +} + + +/***************************************************************/ +int main(int argc, char **argv) +{ + KAboutData aboutData( "kdf", I18N_NOOP("KDiskFree"), + version, description, KAboutData::License_GPL, + "(c) 1998-2001, Michael Kropfberger"); + aboutData.addAuthor("Michael Kropfberger",0, "michael.kropfberger@gmx.net"); + KCmdLineArgs::init( argc, argv, &aboutData ); + + KApplication app; + + if( app.isRestored() ) //SessionManagement + { + for( int n=1; KDFTopLevel::canBeRestored(n); n++ ) + { + KDFTopLevel *ktl = new KDFTopLevel(); + Q_CHECK_PTR(ktl); + app.setMainWidget(ktl); + ktl->restore(n); + } + } + else + { + KDFTopLevel *ktl = new KDFTopLevel(); + Q_CHECK_PTR(ktl); + ktl->show(); + } + + return app.exec(); +} + +#include "kdf.moc" + diff --git a/kdf/kdf.desktop b/kdf/kdf.desktop new file mode 100644 index 0000000..89eb513 --- /dev/null +++ b/kdf/kdf.desktop @@ -0,0 +1,88 @@ +[Desktop Entry] +Name=KDiskFree +Name[af]=Kdiskfree +Name[eo]=Diskuzo +Name[hi]=के-डिस्क-फ्री +Name[lv]=KDiskāBrīvs +Name[ne]=केडीई डिस्क खाली +Name[pa]=ਕੇਡਿਸਕ ਥਾਂ +Name[pl]=Wolna przestrzeń na dyskach +Name[pt_BR]=Disco Livre +Name[sl]=Prosti disk +Name[sv]=Kdiskfree +Name[ta]= கேடிஸ்க் இல்வசம் +Name[tg]=KДиски Озод +Name[th]=การใช้พื้นที่ดิสก์ +Name[tr]=K Disk Boşluğu +Name[ven]=KDisiki ya mahala +Name[zh_TW]=磁碟剩餘空間 +Exec=kdf -caption "%c" +Icon=kdf +Type=Application +GenericName=View Disk Usage +GenericName[af]=Besigtig Disket Gebruik +GenericName[ar]=عرض المستخدم من القرص +GenericName[bg]=Свободно място на диска +GenericName[bs]=Pregled iskorištenosti diska +GenericName[ca]=Veure l'ús de disc +GenericName[cs]=Zobrazení využití disku +GenericName[cy]=Gweld Defnydd y Disg +GenericName[da]=Se diskforbrug +GenericName[de]=Festplattenbelegung etc. anzeigen +GenericName[el]=Προβολή χρήσης του δίσκου +GenericName[eo]=Montras la okupitan kaj liberan spacon sur la diskoj +GenericName[es]=Muestra el uso del disco +GenericName[et]=Kettakasutus +GenericName[eu]=Erakutsi Diskoaren Erabilera +GenericName[fa]=مشاهدۀ کاربرد دیسک +GenericName[fi]=Näytä levynkäyttö +GenericName[fr]=Affiche l'utilisation de l'espace disque +GenericName[ga]=Taispeáin úsáid diosca +GenericName[he]=הצגת שיעור השימוש בדיסקים +GenericName[hi]=डिस्क उपयोग देखें +GenericName[hr]=Prikazuje iskorištenost diska +GenericName[hu]=Lemezterület-kijelző +GenericName[is]=Skoða nýtni á diskum +GenericName[it]=Mostra lo spazio disco libero +GenericName[ja]=ディスク使用状況を表示 +GenericName[ka]=იხილეთ დისკის გამოყენება +GenericName[kk]=Дискідегі орынды көрсету +GenericName[km]=មើល​ការប្រើប្រាស់​ថាស +GenericName[lt]=Žiūrėti disko panaudojimą +GenericName[lv]=Skatīt Diska Izmantošanu +GenericName[mk]=Видете ја искористеноста на дискот +GenericName[ms]=Lihat Penggunaan Cakera +GenericName[mt]=Uri l-użu tad-diski +GenericName[nb]=Vis diskplass +GenericName[nds]=Fastplattbruuk wiesen +GenericName[ne]=डिस्क उपयोग हेर्नुहोस् +GenericName[nl]=Schijfgebruik bekijken +GenericName[nn]=Vis diskbruk +GenericName[pa]=ਡਿਸਕ ਦੀ ਵਰਤੀ ਥਾਂ ਵੇਖੋ +GenericName[pl]=Informacja o wolnym miejscu na dyskach +GenericName[pt]=Utilização do Disco +GenericName[pt_BR]=Ver Uso do Disco +GenericName[ro]=Afişează utilizarea discului +GenericName[ru]=Использование дисков +GenericName[sk]=Využitie disku +GenericName[sl]=Pokaže porabo diska +GenericName[sr]=Приказ искоришћености дискова +GenericName[sr@Latn]=Prikaz iskorišćenosti diskova +GenericName[sv]=Visa diskanvändning +GenericName[ta]=வட்டு பயன்பாட்டை பார்க்கவும் +GenericName[tg]=Назари Истифодабарии Диск +GenericName[th]=แสดงการใช้พื้นที่ดิสก์ +GenericName[tr]=Disk Kullanımını Görüntüle +GenericName[uk]=Перегляд використання диску +GenericName[ven]=Sedzani mashumisele a Disk +GenericName[vi]=Xem đĩa trống +GenericName[wa]=Vey l' eployaedje del deure plake +GenericName[xh]=Jonga Ukusebenziseka KweDiskic +GenericName[zh_CN]=查看磁盘使用状况 +GenericName[zh_TW]=檢視磁碟使用情形 +GenericName[zu]= Buka Ukusetshenziswa Kwediski +Terminal=false +DocPath=kdf/index.html +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;System;X-KDE-More; diff --git a/kdf/kdf.h b/kdf/kdf.h new file mode 100644 index 0000000..9cae3c7 --- /dev/null +++ b/kdf/kdf.h @@ -0,0 +1,45 @@ +/* + kdf.h - KDiskFree + + Copyright (C) 1998 by Michael Kropfberger + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + +#ifndef __KDF_H__ +#define __KDF_H__ + +#include +#include + +#include "kdfwidget.h" + +/***************************************************************/ +class KDFTopLevel : public KMainWindow +{ + Q_OBJECT + + public: + KDFTopLevel(QWidget *parent=0, const char *name=0); + ~KDFTopLevel() { }; + + protected slots: + virtual bool queryExit( void ); + protected: + KDFWidget* kdf; +}; + +#endif diff --git a/kdf/kdfconfig.cpp b/kdf/kdfconfig.cpp new file mode 100644 index 0000000..499e2e3 --- /dev/null +++ b/kdf/kdfconfig.cpp @@ -0,0 +1,263 @@ +/* + * kdfconfig.cpp + * + * Copyright (c) 1999 Michael Kropfberger + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +// +// 1999-11-29 Espen Sand +// Converted to QLayout and QListView + cleanups +// + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "listview.h" +#include "kdfconfig.h" + +#ifndef GUI_DEFINED +static bool GUI; +#define GUI_DEFINED +#endif + + +KDFConfigWidget::KDFConfigWidget(QWidget *parent, const char *name, bool init) + : QWidget( parent, name) +{ + + mTabName.resize(8); + mTabName[0] = new CTabName( "Icon", i18n("Icon") ); + mTabName[1] = new CTabName( "Device", i18n("Device") ); + mTabName[2] = new CTabName( "Type", i18n("Type") ); + mTabName[3] = new CTabName( "Size", i18n("Size") ); + mTabName[4] = new CTabName( "MountPoint", i18n("Mount Point") ); + mTabName[5] = new CTabName( "Free", i18n("Free") ); + // xgettext:no-c-format + mTabName[6] = new CTabName( "Full%", i18n("Full %") ); + mTabName[7] = new CTabName( "UsageBar", i18n("Usage") ); + + GUI = !init; + if(GUI) + { + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint()); + + mList = new CListView( this, "list", 1 ); + mList->setAllColumnsShowFocus(true); + mList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken ); + mList->header()->setMovingEnabled(false); + for( uint i=0; i < mTabName.size(); i++ ) + { + mList->addColumn( mTabName[i]->mName ); + } + connect( mList, SIGNAL(clicked(QListViewItem *, const QPoint &, int)), + this, SLOT(toggleListText(QListViewItem *,const QPoint &,int))); + connect( mList, SIGNAL(clicked(QListViewItem *, const QPoint &, int)), + this, SLOT(slotChanged())); + topLayout->addWidget( mList ); + + QListViewItem *mListItem = new QListViewItem( mList ); + for( uint i=mList->header()->count(); i>0; i-- ) + { + mListItem->setText(i-1, i18n("visible") ); + mListItem->setPixmap( i-1, UserIcon ( "tick" ) ); + } + mList->setSelected( mListItem, true ); + + QGridLayout *gl = new QGridLayout( 2, 2 ); + topLayout->addLayout( gl ); + gl->setColStretch( 1, 10 ); + + mScroll = new QScrollBar( this ); + Q_CHECK_PTR(mScroll); + mScroll->setOrientation( QScrollBar::Horizontal ); + mScroll->setSteps(1,20); + mScroll->setRange(0, 180 ); + gl->addWidget( mScroll, 1, 1 ); + connect(mScroll,SIGNAL(valueChanged(int)),this,SLOT(slotChanged())); + + mLCD = new QLCDNumber( this ); + Q_CHECK_PTR(mLCD); + mLCD->setNumDigits( 3 ); + mLCD->setSegmentStyle(QLCDNumber::Filled); + connect(mScroll,SIGNAL(valueChanged(int)),mLCD,SLOT(display(int))); + gl->addMultiCellWidget( mLCD, 0, 1, 0, 0 ); + + text = i18n("Update frequency [seconds]. The value 0 disables update" ); + QLabel *label = new QLabel( text, this ); + Q_CHECK_PTR(label); + gl->addWidget( label, 0, 1 ); + + + label = new QLabel( i18n("File manager (e.g. konsole -e mc %m):") ,this); + Q_CHECK_PTR(label); + topLayout->addWidget( label ); + + mFileManagerEdit = new QLineEdit( this ); + Q_CHECK_PTR(mFileManagerEdit); + topLayout->addWidget( mFileManagerEdit ); + connect(mFileManagerEdit,SIGNAL(textChanged (const QString &)),this,SLOT(slotChanged())); + + text = i18n("Open file manager automatically on mount"); + mOpenMountCheck = new QCheckBox(text, this ); + Q_CHECK_PTR(mOpenMountCheck); + topLayout->addWidget( mOpenMountCheck ); + connect(mOpenMountCheck,SIGNAL(toggled(bool)),this,SLOT(slotChanged())); + + text = i18n("Pop up a window when a disk gets critically full"); + mPopupFullCheck = new QCheckBox( text, this ); + Q_CHECK_PTR(mPopupFullCheck); + topLayout->addWidget( mPopupFullCheck ); + connect(mPopupFullCheck,SIGNAL(toggled(bool)),this,SLOT(slotChanged())); + } + + loadSettings(); + if( init ) + { + applySettings(); + } +} + + +KDFConfigWidget::~KDFConfigWidget() +{ +} + + +void KDFConfigWidget::closeEvent(QCloseEvent *) +{ + applySettings(); + kapp->quit(); +} + + +void KDFConfigWidget::applySettings( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup("KDFConfig"); + + if( GUI ) + { + //config.writeEntry( "Width", width() ); + //config.writeEntry( "Height", height() ); + + mStd.setFileManager( mFileManagerEdit->text() ); + mStd.setUpdateFrequency( mScroll->value() ); + mStd.setPopupIfFull( mPopupFullCheck->isChecked() ); + mStd.setOpenFileManager( mOpenMountCheck->isChecked() ); + mStd.writeConfiguration(); + + QListViewItem *item = mList->firstChild(); + if( item != 0 ) + { + for( int i=mList->header()->count(); i>0; i-- ) + { + bool state = item->text(i-1) == i18n("visible") ? true : false; + config.writeEntry( mTabName[i-1]->mRes, state ); + } + } + } + else + { + mStd.writeDefaultFileManager(); + } + config.sync(); +} + + +void KDFConfigWidget::loadSettings( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup("KDFConfig"); + + if( GUI ) + { + mStd.updateConfiguration(); + mScroll->setValue( mStd.updateFrequency() ); + mLCD->display( mStd.updateFrequency() ); + mPopupFullCheck->setChecked( mStd.popupIfFull() ); + mOpenMountCheck->setChecked( mStd.openFileManager() ); + mFileManagerEdit->setText( mStd.fileManager() ); + + QListViewItem *item = mList->firstChild(); + if( item != 0 ) + { + for( int i=mList->header()->count(); i>0; i-- ) + { + int j = config.readNumEntry( mTabName[i-1]->mRes, 1 ); + item->setText( i-1, j==0 ? i18n("hidden") : i18n("visible") ); + item->setPixmap( i-1, j==0 ? UserIcon ( "delete" ) + : UserIcon ( "tick" ) ); + } + } + } + +} + +void KDFConfigWidget::defaultsBtnClicked( void ) +{ + mStd.setDefault(); + mScroll->setValue( mStd.updateFrequency() ); + mLCD->display( mStd.updateFrequency() ); + mPopupFullCheck->setChecked( mStd.popupIfFull() ); + mOpenMountCheck->setChecked( mStd.openFileManager() ); + mFileManagerEdit->setText( mStd.fileManager() ); + + QListViewItem *item = mList->firstChild(); + if( item != 0 ) + { + for( int i=mList->header()->count(); i>0; i-- ) + { + item->setText( i-1, i18n("visible") ); + item->setPixmap( i-1, UserIcon ( "tick" ) ); + + } + } +} + + +void KDFConfigWidget::toggleListText( QListViewItem *item, const QPoint &, + int column ) +{ + if (!item) return; + QString text = item->text( column ); + item->setText(column, text==i18n("visible")?i18n("hidden"):i18n("visible")); + item->setPixmap( column, text==i18n("visible") ? UserIcon ( "delete" ) + : UserIcon ( "tick" ) ); +} + +void KDFConfigWidget::slotChanged() +{ + emit configChanged(); +} + +#include "kdfconfig.moc" diff --git a/kdf/kdfconfig.h b/kdf/kdfconfig.h new file mode 100644 index 0000000..34aa7d4 --- /dev/null +++ b/kdf/kdfconfig.h @@ -0,0 +1,97 @@ +/* + * kdfconfig.h + * + * Copyright (c) 1999 Michael Kropfberger + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __KDFCONFIG_H__ +#define __KDFCONFIG_H__ + +#include +#include + +#include "stdoption.h" + +class QCheckBox; +class QLabel; +class QLCDNumber; +class QLineEdit; +class QListViewItem; +class QScrollBar; + +class CListView; + +class KDFConfigWidget : public QWidget +{ + Q_OBJECT + + class CTabName + { + public: + CTabName( const QString &res, const QString &name ) + { + mRes = res; + mName = name; + } + CTabName( void ) { } + ~CTabName( void ) { } + + QString mRes; + QString mName; + }; + + public: + KDFConfigWidget( QWidget *parent=0, const char *name=0, bool init=false); + ~KDFConfigWidget(); + + public slots: + void loadSettings( void ); + void applySettings( void ); + void defaultsBtnClicked( void ); + + protected slots: + void slotChanged(); + + private slots: + void toggleListText( QListViewItem *item, const QPoint &, int column ); + + protected: + void closeEvent( QCloseEvent * ); + + private: + QMemArray mTabName; + CListView *mList; + QScrollBar *mScroll; + QLCDNumber *mLCD; + QLineEdit *mFileManagerEdit; + QCheckBox *mOpenMountCheck; + QCheckBox *mPopupFullCheck; + CStdOption mStd; + + signals: + void configChanged(); +}; + + +#endif + + + diff --git a/kdf/kdfui.rc b/kdf/kdfui.rc new file mode 100644 index 0000000..65589e2 --- /dev/null +++ b/kdf/kdfui.rc @@ -0,0 +1,11 @@ + + + + + &File + + + + + + diff --git a/kdf/kdfwidget.cpp b/kdf/kdfwidget.cpp new file mode 100644 index 0000000..ea7aee9 --- /dev/null +++ b/kdf/kdfwidget.cpp @@ -0,0 +1,652 @@ +/* + * kdfwidget.cpp + * + * Copyright (c) 1998-2001 Michael Kropfberger + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// +// 1999-11-29 Espen Sand +// Converted to QLayout and QListView + cleanups +// 1999-12-05 Espen Sand +// Usage bars should work again. +// + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "listview.h" +#include "kdfwidget.h" +#include "optiondialog.h" + + +#define BAR_COLUMN 7 +#define FULL_PERCENT 95.0 + +#ifndef GUI_DEFINED +static bool GUI; +#define GUI_DEFINED +#endif + +/**************************************************************/ + +CListViewItem::CListViewItem( CListView * parent, QListViewItem * after ) + :QListViewItem( parent, after ) +{} + +int CListViewItem::compare ( QListViewItem *i, int column, bool ) const +{ + QString tmp; + + CListViewItem *c = static_cast(i); + + switch (column) { + case KDFWidget::sizeCol: + return (size==c->size) ? 0 : (sizesize) ? -1 : 1; + + case KDFWidget::freeCol: + return (avail==c->avail) ? 0 : (availavail) ? -1 : 1; + + case KDFWidget::fullCol: + case KDFWidget::usageCol: + return (full==c->full) ? 0 : (fullfull) ? -1 : 1; + + default: + return key(column,true).compare(i->key(column,true)); + } +} + +void CListViewItem::setKeys (int kb_size, int kb_avail, float percent_full) +{ + size = kb_size; + avail = kb_avail; + full = (percent_full >= 0.) ? percent_full : 0.; + return; +} + +/**************************************************************/ + +KDFWidget::KDFWidget( QWidget *parent, const char *name, bool init ) + : QWidget(parent, name), mOptionDialog(0), mPopup(0), mTimer(0) +{ + connect(&mDiskList , SIGNAL(readDFDone() ), + this, SLOT (updateDFDone()) ); + connect(&mDiskList , SIGNAL(criticallyFull(DiskEntry*)), + this, SLOT (criticallyFull(DiskEntry*)) ); + + mTabProp.resize(8); + mTabProp[0] = new CTabEntry( "Icon", i18n("Icon"), true, 32); + mTabProp[1] = new CTabEntry( "Device", i18n("Device"), true, 80); + mTabProp[2] = new CTabEntry( "Type", i18n("Type"), true, 50); + mTabProp[3] = new CTabEntry( "Size", i18n("Size"), true, 72); + mTabProp[4] = new CTabEntry( "MountPoint", i18n("Mount Point"), true, 90 ); + mTabProp[5] = new CTabEntry( "Free", i18n("Free"), true, 55); + // xgettext:no-c-format + mTabProp[6] = new CTabEntry( "Full%", i18n("Full %"), true, 70); + mTabProp[7] = new CTabEntry( "UsageBar", i18n("Usage"), true, 100); + + GUI = !init; + if( GUI ) + { + QVBoxLayout *topLayout = new QVBoxLayout( this, 0, 0 ); + mList = new CListView( this, "list" ); + topLayout->addWidget( mList ); + + mList->setAllColumnsShowFocus( true ); + mList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken ); + mList->setShowSortIndicator(true); + connect( mList, + SIGNAL( rightButtonPressed( QListViewItem *, const QPoint &, int )), + this, SLOT( rightButtonPressed( QListViewItem *, const QPoint &, int ))); + connect( mList, + SIGNAL( rightButtonClicked( QListViewItem *, const QPoint &, int )), + this, SLOT( rightButtonClicked( QListViewItem *, const QPoint &, int ))); + connect( mList->header(), SIGNAL(sizeChange(int, int, int)), + this, SLOT(columnSizeChanged(int, int, int)) ); + makeColumns(); + + mIsTopLevel = QString(parent->className()) == "KDFTopLevel" ? true : false; + } + + loadSettings(); + if( init == true ) + { + applySettings(); + } +} + + +KDFWidget::~KDFWidget() +{ +} + + + +void KDFWidget::makeColumns( void ) +{ + uint i; + + // + // 1999-11-29 Espen Sand + // This smells like a bad hack but I need to remove the headers + // first. If I don't, the list look like shit afterwards. The iterator + // is just used to prevent an endless loop. With my Qt (1999-11-10 ?) + // I only need as many iterations as there are header items but who knows + // what a new Qt can do! + // + for( i=1000; mList->header()->count() > 0 && i>0; i-- ) + { + mList->header()->removeLabel( 0 ); + mList->header()->update(); + } + for( i=0; iremoveColumn(i++) ); + mList->clear(); + + for( i=0; iaddColumn( e.mName, e.mWidth ); + else + mList->addColumn( e.mName, 0 ); // zero width makes it invisible + } + +} + + + + +/******************************************************************/ +void KDFWidget::closeEvent(QCloseEvent *) +{ + applySettings(); + kapp->quit(); +} + + +void KDFWidget::settingsChanged( void ) +{ + applySettings(); + loadSettings(); +} + + +/*************************************************************************** + * writes the KConfig +**/ +void KDFWidget::applySettings( void ) +{ + KConfig &config = *kapp->config(); + + config.setGroup("KDiskFree"); + if( GUI ) + { + for( uint i=0; icolumnWidth(i); + } + config.writeEntry( e.mRes, e.mWidth ); + } + } + config.sync(); + updateDF(); +} + + +/*************************************************************************** + * reads the KConfig +**/ +void KDFWidget::loadSettings( void ) +{ + mStd.updateConfiguration(); + + if(GUI) + { + KConfig &config = *kapp->config(); + config.setGroup("KDiskFree"); + for( uint i=0; imWidth > 16) + mTabProp[usageCol]->mWidth -= 16; + + config.setGroup("KDFConfig"); + for( uint i=0; ishow(); + } +} + + +/*************************************************************************** + * resets the timer for automatic df-refreshes +**/ +void KDFWidget::setUpdateFrequency( int frequency ) +{ + // + // Kill current timer and restart it if the frequency is + // larger than zero. + // + killTimers(); + if( frequency > 0 ) + { + startTimer( frequency * 1000 ); + } +} + +/*************************************************************************** + * Update (reread) all disk-dependencies +**/ +void KDFWidget::timerEvent(QTimerEvent *) +{ + updateDF(); +} + + +/*************************************************************************** + * checks fstab & df +**/ +void KDFWidget::updateDF( void ) +{ + // + // We can only do this if the popupmenu is not present + // + if( mPopup == 0 ) + { + readingDF = TRUE; + mDiskList.readFSTAB(); + mDiskList.readDF(); + } +} + +/*************************************************************************** + * gets the signal when the diskList is complete and up to date +**/ +void KDFWidget::updateDFDone( void ){ + if (mPopup) //The popup menu is ont he screen... Don't touch the list view... + return; + + mList->clear(); + + int i=0; + CListViewItem *item = 0; + for( DiskEntry *disk=mDiskList.first(); disk!=0; disk=mDiskList.next() ) + { + i++; + QString size, percent; + if( disk->kBSize() > 0 ) + { + percent = KGlobal::locale()->formatNumber(disk->percentFull(), 1) + '%'; + size = disk->prettyKBSize(); + } + else + { + percent = i18n("N/A"); + size = i18n("N/A"); + } + + int k=0; + item = new CListViewItem( mList, item ); + bool root = disk->mountOptions().find("user",0,false)==-1 ? true : false; + item->setPixmap( k++, mList->icon( disk->iconName(), root ) ); + item->setText( k++, disk->deviceName() ); + item->setText( k++, disk->fsType() ); + item->setText( k++, size ); + item->setText( k++, disk->mountPoint() ); + item->setText( k++, disk->prettyKBAvail() ); + item->setText( k++, percent ); + item->setKeys( disk->kBSize(), disk->kBAvail(), disk->percentFull()); + } + readingDF = false; + updateDiskBarPixmaps(); + + mList->sort(); +} + +/*************************************************************************** + * Update display +**/ +void KDFWidget::resizeEvent( QResizeEvent * ) +{ + updateDiskBarPixmaps(); +} + + + +/************************************************************************** + * connected with diskList +**/ +void KDFWidget::criticallyFull( DiskEntry *disk ) +{ + if( mStd.popupIfFull() == true ) + { + QString msg = i18n("Device [%1] on [%2] is getting critically full!"). + arg(disk->deviceName()).arg(disk->mountPoint()); + KMessageBox::sorry( this, msg, i18n("Warning")); + } +} + + +/************************************************************************** + * find correct disk related to list item +**/ +DiskEntry *KDFWidget::selectedDisk( QListViewItem *item ) +{ + if( item == 0 ) + { + item = mList->selectedItem(); + } + if( item == 0 ) + { + return(0); + } + + DiskEntry disk(item->text(deviceCol)); + disk.setMountPoint(item->text(mntCol)); + + // I can't get find() to work. The Disks::compareItems(..) is + // never called. + // + //int pos=mDiskList->find(disk); + + int pos = -1; + for( u_int i=0; ideviceName() ); + if( res == 0 ) + { + res = disk.mountPoint().compare( item->mountPoint() ); + } + if( res == 0 ) + { + pos = i; + break; + } + } + + + return mDiskList.at(pos); + // return(0); +} + +void KDFWidget::rightButtonPressed( QListViewItem *item, const QPoint &p, int ) +{ + if( KContextMenuManager::showOnButtonPress() == true ) + { + popupMenu( item, p ); + } +} + + +void KDFWidget::rightButtonClicked( QListViewItem *item, const QPoint &p, int ) +{ + if( KContextMenuManager::showOnButtonPress() == false ) + { + popupMenu( item, p ); + } +} + + +/************************************************************************** + * pops up and asks for mount/umount right-clicked device +**/ +void KDFWidget::popupMenu( QListViewItem *item, const QPoint &p ) +{ + if (mPopup) //The user may even be able to popup another menu while this open is active... + return; + + // + // The list update will be disabled as long as this menu is + // visible. Reason: The 'disk' may no longer be valid. + // + + mDiskList.setUpdatesDisabled(true); + DiskEntry *disk = selectedDisk( item ); + if( disk == 0 ) + { + return; + } + + mPopup = new KPopupMenu( 0 ); + mPopup->insertTitle( disk->mountPoint() ); + mPopup->insertItem( i18n("Mount Device"), 0 ); + mPopup->insertItem( i18n("Unmount Device"), 1 ); + mPopup->insertSeparator(); + mPopup->insertItem( i18n("Open in File Manager"), 2 ); + mPopup->setItemEnabled( 0, disk->mounted() ? false : true ); + mPopup->setItemEnabled( 1, disk->mounted() ); + mPopup->setItemEnabled( 2, disk->mounted() ); + int position = mPopup->exec( p ); + + + + bool openFileManager = false; + if( position == -1 ) + { + mDiskList.setUpdatesDisabled(false); + delete mPopup; mPopup = 0; + return; + } + else if( position == 0 || position == 1 ) + { + item->setText( sizeCol, i18n("MOUNTING") ); + item->setText( freeCol, i18n("MOUNTING") ); + item->setPixmap( 0, mList->icon( "mini-clock", false ) ); + + int val = disk->toggleMount(); + if( val != 0 /*== false*/ ) + { + KMessageBox::error( this, disk->lastSysError() ); + } + else if ( ( mStd.openFileManager() == true) + && (position == 0) ) //only on mount + { + openFileManager = true; + } + + delete item; + mDiskList.deleteAllMountedAt(disk->mountPoint()); + } + else if( position == 2 ) + { + openFileManager = true; + } + + if( openFileManager == true ) + { + kdDebug() << "opening filemanager" << endl; + if( mStd.fileManager().isEmpty() == false ) + { + QString cmd = mStd.fileManager(); + int pos = cmd.find("%m"); + if( pos > 0 ) + { + cmd = cmd.replace( pos, 2, KProcess::quote(disk->mountPoint()) ) + " &"; + } + else + { + cmd += " " + KProcess::quote(disk->mountPoint()) +" &"; + } + system( QFile::encodeName(cmd) ); + } + } + + //Update only here as showing of error message triggers event loop. + mDiskList.setUpdatesDisabled(false); + delete mPopup; mPopup = 0; + + if( position != 2 ) // No need to update when just opening the fm. + { + updateDF(); + } + +} + + + + +/************************************************************************** + * recalculates and repaints the pixBars +**/ +void KDFWidget::updateDiskBarPixmaps( void ) +{ + if (mTabProp[usageCol]->mVisible != true) + return; + + + int size=0, w=0; + + for(uint i=0; icolumnWidth(i); + w=mList->width() - size - 4; + if (w<0) + w=0; + mList->setColumnWidth(usageCol, w ); + + int h = mList->fontMetrics().lineSpacing()-2; + if( h <= 0 ) + { + return; + } + + int i=0; + for(QListViewItem *it=mList->firstChild(); it!=0;it=it->nextSibling(),i++ ) + { + // I can't get find() to work. The Disks::compareItems(..) is + // never called. + // + //int pos=mDiskList->find(disk); + + DiskEntry dummy(it->text(deviceCol)); + dummy.setMountPoint(it->text(mntCol)); + int pos = -1; + for( u_int i=0; ideviceName() ); + if( res == 0 ) + { + res = dummy.mountPoint().compare( item->mountPoint() ); + } + if( res == 0 ) + { + pos = i; + break; + } + } + + + DiskEntry *disk = mDiskList.at(pos); + if( disk == 0 ) { continue; } + + if( disk->mounted() == true && disk->percentFull() != -1 ) + { + int w = mList->columnWidth(usageCol)-2; + if( w <= 0 ) { continue; } + + QPixmap *pix = new QPixmap( w, h ); + if( pix == 0 ) { continue; } + + pix->fill(white); + QPainter p(pix); + p.setPen(black); + p.drawRect(0,0,w,h); + QColor c; + if ( (disk->iconName().find("cdrom") != -1) + || (disk->iconName().find("writer") != -1) ) + c = gray; + else + c = disk->percentFull() > FULL_PERCENT ? red : darkGreen; + p.setBrush(c ); + p.setPen(white); + p.drawRect(1,1,(int)(((float)pix->width()-2)*(disk->percentFull()/100)), + pix->height()-2); + it->setPixmap ( usageCol, *pix ); + p.end(); + delete pix; + } + } +} + + +void KDFWidget::columnSizeChanged( int, int, int ) +{ + + if( mTimer == 0 ) + { + mTimer = new QTimer( this ); + connect( mTimer, SIGNAL(timeout()), this, SLOT(updateDiskBarPixmaps()) ); + } + else if( mTimer->isActive() == true ) + { + mTimer->stop(); + } + + mTimer->start( 10, true ); +} + + +void KDFWidget::invokeHelp() +{ + kapp->invokeHelp("", "kcontrol/kdf"); +} + +#include "kdfwidget.moc" + diff --git a/kdf/kdfwidget.h b/kdf/kdfwidget.h new file mode 100644 index 0000000..13e14ed --- /dev/null +++ b/kdf/kdfwidget.h @@ -0,0 +1,153 @@ +/* + * kdfwidget.h + * + * Copyright (c) 1998 Michael Kropfberger + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __KDFWIDGET_H__ +#define __KDFWIDGET_H__ + +#include +#include +#include +#include + +#include "disks.h" +#include "disklist.h" +#include "mntconfig.h" +#include "kdfconfig.h" +#include "stdoption.h" + +class CListView; +class COptionDialog; +class QTimer; +class KPopupMenu; + +/**************************************************************/ + +class CTabEntry +{ + public: + CTabEntry( const QString &res, const QString &name, bool visible, + uint width ) + { + mRes = res; + mName = name; + mVisible = visible; + mWidth = width; + } + CTabEntry( void ) { } + ~CTabEntry( void ) { } + + + QString mRes; + QString mName; + bool mVisible; + uint mWidth; +}; + +/**************************************************************/ +// +// 2001-03-10 Walter F.J. Mueller +// The purpose of this class is: +// 1) overload the key() method to provide sorting keys so that the +// columns with a numeric value are sorted by numerical value. +// + +class CListViewItem : public QListViewItem +{ + public: + CListViewItem ( CListView * parent, QListViewItem * after ); + + virtual int compare ( QListViewItem* i, int col, bool) const; + + void setKeys ( int kb_size, int kb_avail, float percent_full ) ; + + private: + int size; + int avail; + float full; +}; + +/**************************************************************/ + +class KDFWidget : public QWidget +{ + Q_OBJECT + + public: + enum ColId + { + iconCol = 0, + deviceCol = 1, + typeCol = 2, + sizeCol = 3, + mntCol = 4, + freeCol = 5, + fullCol = 6, + usageCol = 7 + }; + + public: + KDFWidget( QWidget *parent=0, const char *name=0, bool init=false); + ~KDFWidget( void ); + + public slots: + void settingsChanged( void ); + void loadSettings( void ); + void applySettings( void ); + void updateDF( void ); + void updateDFDone( void ); + void settingsBtnClicked( void ); + + private slots: + void criticallyFull( DiskEntry *disk ); + void rightButtonPressed( QListViewItem *item, const QPoint &p, int ); + void rightButtonClicked( QListViewItem *item, const QPoint &p, int ); + void popupMenu( QListViewItem *item, const QPoint &p ); + void setUpdateFrequency( int frequency ); + void columnSizeChanged( int column, int, int newSize ); + void updateDiskBarPixmaps( void ); + void invokeHelp( void ); + + protected: + void timerEvent( QTimerEvent * ); + void closeEvent( QCloseEvent * ); + void resizeEvent( QResizeEvent * ); + + private: + void makeColumns( void ); + DiskEntry *selectedDisk( QListViewItem *item=0 ); + + private: + bool readingDF; + QMemArray mTabProp; + CListView *mList; + COptionDialog *mOptionDialog; + KPopupMenu *mPopup; + QTimer *mTimer; + DiskList mDiskList; + bool mIsTopLevel; + CStdOption mStd; +}; + + +#endif diff --git a/kdf/kwikdisk.cpp b/kdf/kwikdisk.cpp new file mode 100644 index 0000000..d287b16 --- /dev/null +++ b/kdf/kwikdisk.cpp @@ -0,0 +1,346 @@ +/* + kwikdisk.cpp - KDiskFree + + Copyright (C) 1999 by Michael Kropfberger + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + +// +// 1999-12-03 Espen Sand +// Cleanups, improvements and fixes for KDE-2 +// +// 2004-07-15 Stanislav Karchebny +// Rewrite for KDE 3 +// + +#include "kwikdisk.h" + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char description[] = + I18N_NOOP("KDE Free disk space utility"); + +static const char version[] = "0.2"; + +static KCmdLineOptions options[] = +{ + KCmdLineLastOption +}; + +/*****************************************************************************/ + +KwikDisk::KwikDisk() + : KSystemTray() + , m_readingDF(FALSE) + , m_dirty(TRUE) + , m_menuVisible(FALSE) + , m_inside(FALSE) + , m_optionDialog(0) +{ + kdDebug() << k_funcinfo << endl; + + setPixmap(KSystemTray::loadIcon("kdf")); + show(); + + connect( &m_diskList, SIGNAL(readDFDone()), this, SLOT(updateDFDone()) ); + connect( &m_diskList, SIGNAL(criticallyFull(DiskEntry*)), + this, SLOT(criticallyFull(DiskEntry*)) ); + + connect( contextMenu(), SIGNAL(aboutToHide()), this, SLOT(aboutToHide()) ); + + loadSettings(); + updateDF(); +} + +void KwikDisk::aboutToHide() +{ + kdDebug() << k_funcinfo << endl; + if( !m_inside ) + m_menuVisible = FALSE; +} + +void KwikDisk::enterEvent(QEvent *) +{ + kdDebug() << k_funcinfo << endl; + m_inside = TRUE; +} + +void KwikDisk::leaveEvent(QEvent *) +{ + kdDebug() << k_funcinfo << endl; + m_inside = FALSE; +} + +void KwikDisk::mousePressEvent(QMouseEvent *me) +{ + kdDebug() << k_funcinfo << endl; + + if( m_dirty ) + updateDF(); + + if( m_menuVisible ) + { + contextMenu()->hide(); + m_menuVisible = FALSE; + me->ignore(); + return; + } + + contextMenuAboutToShow(contextMenu()); + contextMenu()->popup( me->globalPos() ); + m_menuVisible = TRUE; +} + +void KwikDisk::loadSettings() +{ + kdDebug() << k_funcinfo << endl; + + m_options.updateConfiguration(); + setUpdateFrequency( m_options.updateFrequency() ); +} + +void KwikDisk::setUpdateFrequency(int frequency) +{ + kdDebug() << k_funcinfo << endl; + + // + // Kill current timer and restart it if the frequency is + // larger than zero. + // + killTimers(); + if( frequency > 0 ) + { + startTimer(frequency * 1000); + } +} + +/** + * Mark the list as dirty thus forcing a reload the next time the + * popup menu is about to become visible. Note: A current visible popup + * will not be updated now. + */ +void KwikDisk::timerEvent(QTimerEvent *) +{ + kdDebug() << k_funcinfo << endl; + m_dirty = TRUE; +} + +void KwikDisk::updateDF() +{ + kdDebug() << k_funcinfo << endl; + + m_readingDF = true; + m_diskList.readFSTAB(); + m_diskList.readDF(); +} + +void KwikDisk::updateDFDone() +{ + kdDebug() << k_funcinfo << endl; + + m_readingDF = FALSE; + m_dirty = FALSE; + + contextMenu()->clear(); + contextMenu()->insertTitle(KSystemTray::loadIcon("kdf"), i18n("KwikDisk")); + + int itemNo = 0; + for( DiskEntry *disk = m_diskList.first(); disk != 0; disk = m_diskList.next() ) + { + // FIXME: tool tips are unused atm + QString toolTipText = i18n("%1 (%2) %3 on %4") + .arg( disk->mounted() ? i18n("Unmount") : i18n("Mount")) + .arg(disk->fsType()).arg(disk->deviceName()).arg(disk->mountPoint()); + + QString entryName = disk->mountPoint(); + if( disk->mounted() ) + { + entryName += QString("\t\t\t[%1]").arg(disk->prettyKBAvail()); + } + int id = contextMenu()->insertItem("", this, SLOT(toggleMount(int)) ); + contextMenu()->setItemParameter(id, itemNo); + itemNo++; + + QPixmap *pix = new QPixmap(KSystemTray::loadIcon(disk->iconName())); + + if( getuid() !=0 && disk->mountOptions().find("user",0, false) == -1 ) + { + // + // Special root icon, normal user cant mount. + // + // 2000-01-23 Espen Sand + // Careful here: If the mask has not been defined we can + // not use QPixmap::mask() because it returns 0 => segfault + // + if( pix->mask() != 0 ) + { + QBitmap *bm = new QBitmap(*(pix->mask())); + if( bm != 0 ) + { + QPainter qp( bm ); + qp.setPen(QPen(white,1)); + qp.drawRect(0,0,bm->width(),bm->height()); + qp.end(); + pix->setMask(*bm); + } + QPainter qp( pix ); + qp.setPen(QPen(red,1)); + qp.drawRect(0,0,pix->width(),pix->height()); + qp.end(); + } + contextMenu()->disconnectItem(id,disk,SLOT(toggleMount())); + toolTipText = i18n("You must login as root to mount this disk"); + } + + contextMenu()->changeItem(*pix,entryName,id); + } + + contextMenu()->insertSeparator(); + + contextMenu()->insertItem( + KSystemTray::loadIcon("kdf"), + i18n("&Start KDiskFree"), this, SLOT(startKDF()),0); + + contextMenu()->insertItem( + KSystemTray::loadIcon("configure"), + i18n("&Configure KwikDisk..."), this, SLOT(changeSettings()),0); + + contextMenu()->insertItem( + KSystemTray::loadIcon("help"), + KStdGuiItem::help().text(), this, SLOT(invokeHelp()),0); + + contextMenu()->insertSeparator(); + + contextMenu()->insertItem( + KSystemTray::loadIcon("exit"), + KStdGuiItem::quit().text(), this, SIGNAL(quitSelected()) ); +} + +void KwikDisk::toggleMount(int item) +{ + kdDebug() << k_funcinfo << endl; + + DiskEntry *disk = m_diskList.at(item); + if( disk == 0 ) + { + return; + } + + int val = disk->toggleMount(); + if( val != 0 ) + { + KMessageBox::error(this, disk->lastSysError()); + } + else if( (m_options.openFileManager() == true) && (disk->mounted() == true ) ) + { + kdDebug() << "opening filemanager" << endl; + if( m_options.fileManager().isEmpty() == false ) + { + QString cmd = m_options.fileManager(); + int pos = cmd.find("%m"); + if( pos > 0 ) + { + cmd = cmd.replace( pos, 2, KProcess::quote(disk->mountPoint()) ) + " &"; + } + else + { + cmd += " " + KProcess::quote(disk->mountPoint()) +" &"; + } + system( QFile::encodeName(cmd) ); + } + } + m_dirty = TRUE; +} + +void KwikDisk::criticallyFull(DiskEntry *disk) +{ + kdDebug() << k_funcinfo << endl; + + if( m_options.popupIfFull() == true ) + { + QString msg = i18n("Device [%1] on [%2] is getting critically full!") + .arg(disk->deviceName()).arg(disk->mountPoint()); + KMessageBox::sorry( this, msg, i18n("Warning")); + } +} + +void KwikDisk::changeSettings() +{ + if( m_optionDialog == 0 ) + { + m_optionDialog = new COptionDialog(this, "options", FALSE); + if( !m_optionDialog ) return; + connect(m_optionDialog, SIGNAL(valueChanged()), + this, SLOT(loadSettings())); + } + m_optionDialog->show(); +} + +void KwikDisk::startKDF() +{ + kdDebug() << k_funcinfo << endl; + + KRun::runCommand("kdf"); +} + +void KwikDisk::invokeHelp() +{ + kapp->invokeHelp("", "kdf"); +} + +/*****************************************************************************/ + +int main(int argc, char **argv) +{ + KLocale::setMainCatalogue( "kdf" ); + + KAboutData about("kwikdisk", I18N_NOOP("KwikDisk"), version, description, + KAboutData::License_GPL, "(C) 2004 Stanislav Karchebny", + 0, 0, "Stanislav.Karchebny@kdemail.net"); + about.addAuthor( "Michael Kropfberger", I18N_NOOP("Original author"), + "michael.kropfberger@gmx.net" ); + about.addAuthor( "Espen Sand", I18N_NOOP("KDE 2 changes"), "" ); + about.addAuthor( "Stanislav Karchebny", I18N_NOOP("KDE 3 changes"), + "Stanislav.Karchebny@kdemail.net" ); + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions( options ); + KApplication app; + KwikDisk *mainWin = 0; + + mainWin = new KwikDisk; + QObject::connect(mainWin, SIGNAL(quitSelected()), &app, SLOT(quit())); + + // mainWin has WDestructiveClose flag by default, so it will delete itself. + return app.exec(); +} + +/*****************************************************************************/ + +#include "kwikdisk.moc" diff --git a/kdf/kwikdisk.desktop b/kdf/kwikdisk.desktop new file mode 100644 index 0000000..7e3ab52 --- /dev/null +++ b/kdf/kwikdisk.desktop @@ -0,0 +1,78 @@ +[Desktop Entry] +Name=KwikDisk +Name[af]=Kwikdisk +Name[eo]=Diskokroĉilo +Name[et]=Ketaste ühendamine +Name[fa]=Kwikدیسک +Name[hi]=क्विक-डिस्क +Name[ja]=マウントツール +Name[ne]=क्विक डिस्क +Name[sv]=Snabbdisk +Name[ta]= கிவிக்வட்டு +Name[th]=เรียกใช้ดิสก์ด่วน +Exec=kwikdisk -caption "%c" +Icon=kwikdisk +Type=Application +DocPath=kdf/index.html +GenericName=Removable Media Utility +GenericName[af]=Verwyderbare Media Program +GenericName[ar]=أداة الوسائط القابلة للإزالة +GenericName[bg]=Преносими носители +GenericName[br]=Ostilh media lem-laka +GenericName[bs]=Alat za izmjenjive medije +GenericName[ca]=Utilitat per discos extraïbles +GenericName[cs]=Nástroj pro výměnné disky +GenericName[cy]=Cyfleuster Cyfryngau Symudadwy +GenericName[da]=Flytbart medieredskab +GenericName[de]=Dienstprogramm für Wechselmedien +GenericName[el]=Εργαλείο αφαιρούμενων μέσων +GenericName[eo]=Ŝanĝebla disko ilo +GenericName[es]=Herramienta de medios extraíbles +GenericName[et]=Eemaldatavate andmekandjate utiliit +GenericName[eu]=Euskarri Eramangarrien Erabilgarritasuna +GenericName[fa]=برنامۀ سودمند رسانه‌ای قابل حذف +GenericName[fi]=Poistettavan median työkalu +GenericName[fr]=Utilitaire de média éjectable +GenericName[ga]=Uirlis Meáin Inscortha +GenericName[he]=כלי מדיה נשלפת +GenericName[hi]=हटाया जा सकने वाला मीडिया यूटिलिटी +GenericName[hr]=Alat za uklonjive medije +GenericName[hu]=Lemezcsatlakoztató +GenericName[is]=Diskatól +GenericName[it]=Accessorio per i supporti rimovibili +GenericName[ja]=リムーバブルメディアユーティリティ +GenericName[ka]=მოხსნადი მედიის უტილიტა +GenericName[kk]=Ауыстырмалы тасушының утилитасы +GenericName[km]=ឧបករណ៍​មេឌៀ​ដែល​អាច​យក​ចេញ +GenericName[lt]=Keičiamų diskų ar kitų įrenginių programa +GenericName[mk]=Алатка за менливи носачи +GenericName[ms]=Utiliti Media Mudah Alih +GenericName[nb]=Verktøy for flyttbare media +GenericName[nds]=Deenstprogramm för tuuschbore Medien +GenericName[ne]=हटाउन योग्य मिडिया युटिलिटी +GenericName[nl]=Verwisselbare media beheren +GenericName[nn]=Verktøy for flyttbare medium +GenericName[pa]=ਹਟਾਉਣਯੋਗ ਮੀਡਿਆ ਸਹੂਲਤ +GenericName[pl]=Narzędzie do wyjmowalnych dysków +GenericName[pt]=Utilitário para Media Removível +GenericName[pt_BR]=Utilitário de Mídia Removível +GenericName[ro]=Utilitar ejectare mediu +GenericName[ru]=Управление дисками +GenericName[sk]=Nástroj pre vymeniteľné médiá +GenericName[sl]=Pripomoček za izmenjevalne medije +GenericName[sr]=Алат за уклоњиве медије +GenericName[sr@Latn]=Alat za uklonjive medije +GenericName[sv]=Verktyg för flyttbar media +GenericName[ta]= நீக்ககூடிய ஊடக பயன்பாடு +GenericName[tg]=Барномаи Пуштибон барои Расонаҳои Ҷойивазшаванда +GenericName[th]=เครื่องมือจัดการสื่อที่ถอดได้ +GenericName[tr]=Çıkartılabilir Aygıt +GenericName[uk]=Утиліта змінних носіїв +GenericName[wa]=Usteye po les bodjåves sopoirts +GenericName[xh]=Umdlali wezoSasazo +GenericName[zh_CN]=可移动介质工具 +GenericName[zh_TW]=可移動媒體公用程式 +GenericName[zu]=Umsebenzi Wonozindaba Ogudluzekayo +Terminal=false +Categories=Qt;KDE;System;X-KDE-More; +OnlyShowIn=KDE; diff --git a/kdf/kwikdisk.h b/kdf/kwikdisk.h new file mode 100644 index 0000000..09066cc --- /dev/null +++ b/kdf/kwikdisk.h @@ -0,0 +1,78 @@ +/* + kwikdisk.cpp - KDiskFree + + Copyright (C) 1999 by Michael Kropfberger + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + +// With changes by Espen Sand and Stanislav Karchebny. + +#ifndef _KWIKDISK_H_ +#define _KWIKDISK_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "disklist.h" +#include "stdoption.h" +#include "optiondialog.h" + +#include +#include + +/** +* @short Application Main Window (however in Tray) +* @version 0.2 +*/ +class KwikDisk : public KSystemTray +{ + Q_OBJECT + public: + KwikDisk(); + + private slots: + void updateDFDone(); + void criticallyFull(DiskEntry*); + void toggleMount(int); + void loadSettings(); + void changeSettings(); + void startKDF(); + void invokeHelp(); + void aboutToHide(); + + private: + void mousePressEvent(QMouseEvent *); + void timerEvent(QTimerEvent *); + void enterEvent(QEvent *); + void leaveEvent(QEvent *); + + void setUpdateFrequency(int frequency); + + void updateDF(); + + private: + DiskList m_diskList; + CStdOption m_options; + bool m_readingDF; + bool m_dirty; + bool m_menuVisible; + bool m_inside; + COptionDialog *m_optionDialog; +}; + +#endif // _KWIKDISK_H_ diff --git a/kdf/listview.cpp b/kdf/listview.cpp new file mode 100644 index 0000000..b522a22 --- /dev/null +++ b/kdf/listview.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 1999 Espen Sand, espen@kde.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +// +// 1999-11-28 Espen Sand +// The purpose of this class is: +// 1) Easily set minimum number of visible items and to adjust the sizeHint() +// 2) Provide a pixmap collection +// + +#include +#include +#include + +#include + +#include "listview.h" + +template class QDict; + +CListView::CListView( QWidget *parent, const char *name, int visibleItem ) + :KListView( parent, name ), mVisibleItem(QMAX( 1, visibleItem )) +{ + setVisibleItem(visibleItem); + mPixDict.setAutoDelete(true); +} + +void CListView::setVisibleItem( int visibleItem, bool updateSize ) +{ + mVisibleItem = QMAX( 1, visibleItem ); + if( updateSize == true ) + { + QSize s = sizeHint(); + setMinimumSize( s.width() + verticalScrollBar()->sizeHint().width() + + lineWidth() * 2, s.height() ); + } +} + +QSize CListView::sizeHint( void ) const +{ + QSize s = QListView::sizeHint(); + + int h = fontMetrics().height() + 2*itemMargin(); + if( h % 2 > 0 ) { h++; } + + s.setHeight( h*mVisibleItem + lineWidth()*2 + header()->sizeHint().height()); + return( s ); +} + + + +const QPixmap &CListView::icon( const QString &iconName, bool drawBorder ) +{ + QPixmap *pix = mPixDict[ iconName ]; + if( pix == 0 ) + { + pix = new QPixmap( SmallIcon( iconName ) ); + + if( drawBorder == true ) + { + // + // 2000-01-23 Espen Sand + // Careful here: If the mask has not been defined we can + // not use QPixmap::mask() because it returns 0 => segfault + // + if( pix->mask() != 0 ) + { + QBitmap *bm = new QBitmap(*(pix->mask())); + if( bm != 0 ) + { + QPainter qp(bm); + qp.setPen(QPen(white,1)); + qp.drawRect(0,0,bm->width(),bm->height()); + qp.end(); + pix->setMask(*bm); + } + + QPainter qp(pix); + qp.setPen(QPen(red,1)); + qp.drawRect(0,0,pix->width(),pix->height()); + qp.end(); + delete bm; + + } + } + mPixDict.replace( iconName, pix ); + } + + return( *pix ); +} + + +#include "listview.moc" + + + + diff --git a/kdf/listview.h b/kdf/listview.h new file mode 100644 index 0000000..0bb4bc5 --- /dev/null +++ b/kdf/listview.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 1999 Espen Sand, espen@kde.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _LISTVIEW_H_ +#define _LISTVIEW_H_ + +#include +#include + +#include + +class CListView : public KListView +{ + Q_OBJECT + + public: + CListView( QWidget *parent=0, const char *name=0, int visibleItem=10 ); + + void setVisibleItem( int visibleItem, bool updateSize=true ); + virtual QSize sizeHint( void ) const; + const QPixmap &icon( const QString &iconName, bool drawBorder ); + + private: + int mVisibleItem; + QDict mPixDict; +}; + + + + +#endif + + + + + + diff --git a/kdf/mntconfig.cpp b/kdf/mntconfig.cpp new file mode 100644 index 0000000..c1c1bbe --- /dev/null +++ b/kdf/mntconfig.cpp @@ -0,0 +1,364 @@ +/* + * mntconfig.cpp + * + * Copyright (c) 1999 Michael Kropfberger + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +// +// 1999-11-29 Espen Sand +// Converted to QLayout and QListView + cleanups +// + +#include +#include +#include +#include + +#undef Unsorted + +#include +#include +#include +#include + +#include "listview.h" +#include "mntconfig.h" + +#ifndef KDE_USE_FINAL +static bool GUI; +#endif + + +MntConfigWidget::MntConfigWidget(QWidget *parent, const char *name, bool init) + : QWidget(parent, name) +{ + mInitializing = false; + + GUI = !init; + if (GUI) + { + //tabList fillup waits until disklist.readDF() is done... + mDiskList.readFSTAB(); + mDiskList.readDF(); + mInitializing = true; + connect( &mDiskList,SIGNAL(readDFDone()),this,SLOT(readDFDone())); + + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint()); + + mList = new CListView( this, "list", 8 ); + mList->setAllColumnsShowFocus( true ); + mList->addColumn( i18n("Icon") ); + mList->addColumn( i18n("Device") ); + mList->addColumn( i18n("Mount Point") ); + mList->addColumn( i18n("Mount Command") ); + mList->addColumn( i18n("Unmount Command") ); + mList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken ); + connect( mList, SIGNAL(selectionChanged(QListViewItem *)), + this, SLOT(clicked(QListViewItem *))); + + topLayout->addWidget( mList ); + + text = QString("%1: %2 %3: %4"). + arg(mList->header()->label(DEVCOL)). + arg(i18n("None")). + arg(mList->header()->label(MNTPNTCOL)). + arg(i18n("None")); + mGroupBox = new QGroupBox( text, this ); + Q_CHECK_PTR(mGroupBox); + topLayout->addWidget(mGroupBox); + + QGridLayout *gl = new QGridLayout(mGroupBox, 3, 4, KDialog::spacingHint()); + if( gl == 0 ) { return; } + gl->addRowSpacing( 0, fontMetrics().lineSpacing() ); + + mIconLineEdit = new QLineEdit(mGroupBox); + Q_CHECK_PTR(mIconLineEdit); + mIconLineEdit->setMinimumWidth( fontMetrics().maxWidth()*10 ); + connect( mIconLineEdit, SIGNAL(textChanged(const QString&)), + this,SLOT(iconChanged(const QString&))); + connect( mIconLineEdit, SIGNAL(textChanged(const QString&)), + this,SLOT(slotChanged())); + gl->addWidget( mIconLineEdit, 2, 0 ); + + mIconButton = new KIconButton(mGroupBox); + mIconButton->setIconType(KIcon::Small, KIcon::Device); + Q_CHECK_PTR(mIconButton); + mIconButton->setFixedWidth( mIconButton->sizeHint().height() ); + connect(mIconButton,SIGNAL(iconChanged(QString)),this,SLOT(iconChangedButton(QString))); + gl->addWidget( mIconButton, 2, 1 ); + + //Mount + mMountButton = new QPushButton( i18n("Get Mount Command"), mGroupBox ); + Q_CHECK_PTR(mMountButton); + connect(mMountButton,SIGNAL(clicked()),this,SLOT(selectMntFile())); + gl->addWidget( mMountButton, 1, 2 ); + + mMountLineEdit = new QLineEdit(mGroupBox); + Q_CHECK_PTR(mMountLineEdit); + mMountLineEdit->setMinimumWidth( fontMetrics().maxWidth()*10 ); + connect(mMountLineEdit,SIGNAL(textChanged(const QString&)), + this,SLOT(mntCmdChanged(const QString&))); + connect( mMountLineEdit, SIGNAL(textChanged(const QString&)), + this,SLOT(slotChanged())); + gl->addWidget( mMountLineEdit, 1, 3 ); + + //Umount + mUmountButton = new QPushButton(i18n("Get Unmount Command"), mGroupBox ); + Q_CHECK_PTR( mUmountButton ); + connect(mUmountButton,SIGNAL(clicked()),this,SLOT(selectUmntFile())); + gl->addWidget( mUmountButton, 2, 2 ); + + mUmountLineEdit=new QLineEdit(mGroupBox); + Q_CHECK_PTR(mUmountLineEdit); + mUmountLineEdit->setMinimumWidth( fontMetrics().maxWidth()*10 ); + connect(mUmountLineEdit,SIGNAL(textChanged(const QString&)), + this,SLOT(umntCmdChanged(const QString&))); + connect( mUmountLineEdit, SIGNAL(textChanged(const QString&)), + this,SLOT(slotChanged())); + gl->addWidget( mUmountLineEdit, 2, 3 ); + + } + + loadSettings(); + if(init) + { + applySettings(); + mDiskLookup.resize(0); + } + + mGroupBox->setEnabled( false ); +} + + +MntConfigWidget::~MntConfigWidget( void ) +{ +} + + +void MntConfigWidget::readDFDone( void ) +{ + mInitializing = false; + mList->clear(); + mDiskLookup.resize(mDiskList.count()); + + int i=0; + QListViewItem *item = 0; + for( DiskEntry *disk=mDiskList.first(); disk!=0; disk=mDiskList.next(),++i ) + { + item = new QListViewItem( mList, item, QString::null, disk->deviceName(), + disk->mountPoint(), disk->mountCommand(), disk->umountCommand() ); + item->setPixmap( ICONCOL, SmallIcon( disk->iconName() ) ); + mDiskLookup[i] = item; + } + + loadSettings(); + applySettings(); +} + + +void MntConfigWidget::applySettings( void ) +{ + mDiskList.applySettings(); + + KConfig &config = *kapp->config(); + config.setGroup("MntConfig"); + if(GUI ) + { + config.writeEntry("Width", width() ); + config.writeEntry("Height", height() ); + } + config.sync(); +} + + +void MntConfigWidget::loadSettings( void ) +{ + KConfig &config = *kapp->config(); + if( mInitializing == false && GUI ) + { + config.setGroup("MntConfig"); + if( isTopLevel() ) + { + int w = config.readNumEntry("Width",this->width() ); + int h = config.readNumEntry("Height",this->height() ); + resize(w,h); + } + + QListViewItem *item = mList->selectedItem(); + if( item != 0 ) + { + clicked( item ); + } + } +} + + +void MntConfigWidget::clicked( QListViewItem *item ) +{ + mGroupBox->setEnabled( true ); + mGroupBox->setTitle( QString("%1: %2 %3: %4"). + arg(mList->header()->label(DEVCOL)). + arg(item->text(DEVCOL)). + arg(mList->header()->label(MNTPNTCOL)). + arg(item->text(MNTPNTCOL)) ); + + + const QPixmap *pix = item->pixmap(ICONCOL); + if( pix != 0 ) + { + mIconButton->setPixmap( *pix ); + } + + for(unsigned i=0 ; i < mDiskList.count() ; ++i) + { + if (mDiskLookup[i] == item) + { + DiskEntry *disk = mDiskList.at(i); + if( disk != 0 ) + { + mIconLineEdit->setText( disk->iconName() ); + } + break; + } + } + mMountLineEdit->setText( item->text(MNTCMDCOL) ); + mUmountLineEdit->setText( item->text(UMNTCMDCOL) ); +} + + +void MntConfigWidget::iconChangedButton(QString iconName) +{ + iconChanged(iconName); +} +void MntConfigWidget::iconChanged(const QString &iconName) +{ + if( iconName.findRev('_') == 0 || + (iconName.right(iconName.length()-iconName.findRev('_'))!="_mount" && + iconName.right(iconName.length()-iconName.findRev('_'))!="_unmount")) + { + QString msg = i18n("" + "This filename is not valid: %1\n" + "It must end with " + "\"_mount\" or \"_unmount\".").arg(iconName); + KMessageBox::sorry( this, msg ); + return; + } + + QListViewItem *item = mList->selectedItem(); + for(unsigned i=0 ; i < mDiskList.count() ; ++i) + { + if (mDiskLookup[i] == item) + { + DiskEntry *disk = mDiskList.at(i); + if( disk != 0 ) + { + disk->setIconName(iconName); + mIconLineEdit->setText(iconName); + KIconLoader &loader = *KGlobal::iconLoader(); + item->setPixmap( ICONCOL, loader.loadIcon( iconName, KIcon::Small)); + } + break; + } + } +} + + +void MntConfigWidget::selectMntFile() +{ + KURL url = KFileDialog::getOpenURL( "","*", this ); + + if( url.isEmpty() ) + return; + + if( !url.isLocalFile() ) + { + KMessageBox::sorry( 0L, i18n( "Only local files supported." ) ); + return; + } + + mMountLineEdit->setText( url.path() ); +} + +void MntConfigWidget::selectUmntFile() +{ + KURL url = KFileDialog::getOpenURL( "", "*", this ); + + if( url.isEmpty() ) + return; + + if( !url.isLocalFile() ) + { + KMessageBox::sorry( 0L, i18n( "Only local files are currently supported." ) ); + return; + } + + mUmountLineEdit->setText( url.path() ); +} + +void MntConfigWidget::mntCmdChanged( const QString &data ) +{ + QListViewItem *item = mList->selectedItem(); + for(unsigned i=0 ; i < mDiskList.count() ; ++i) + { + if (mDiskLookup[i] == item) + { + DiskEntry *disk = mDiskList.at(i); + if( disk != 0 ) + { + disk->setMountCommand(data); + item->setText( MNTCMDCOL, data ); + } + break; + } + } +} + + +void MntConfigWidget::umntCmdChanged( const QString &data ) +{ + QListViewItem *item = mList->selectedItem(); + for(unsigned i=0 ; i < mDiskList.count() ; ++i) + { + if (mDiskLookup[i] == item) + { + DiskEntry *disk = mDiskList.at(i); + if( disk != 0 ) + { + disk->setUmountCommand(data); + item->setText( UMNTCMDCOL, data ); + } + break; + } + } +} + + +void MntConfigWidget::closeEvent(QCloseEvent *) +{ +} + +void MntConfigWidget::slotChanged() +{ + emit configChanged(); +} + +#include "mntconfig.moc" diff --git a/kdf/mntconfig.h b/kdf/mntconfig.h new file mode 100644 index 0000000..d24c8b1 --- /dev/null +++ b/kdf/mntconfig.h @@ -0,0 +1,102 @@ +/* + * mntconfig.h + * + * Copyright (c) 1999 Michael Kropfberger + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __MNTCONFIG_H__ +#define __MNTCONFIG_H__ + +#include +#include +#include + +#include "disks.h" +#include "disklist.h" + +class QGroupBox; +class QPushButton; +class QRadioButton; +class QLineEdit; +class KIconButton; + +class CListView; +class QListViewItem; + +/**************************************************************/ + +class MntConfigWidget : public QWidget +{ + Q_OBJECT + + public: + enum ColType + { + ICONCOL=0, + DEVCOL=1, + MNTPNTCOL=2, + MNTCMDCOL=3, + UMNTCMDCOL=4 + }; + + public: + MntConfigWidget( QWidget *parent=0, const char *name=0, bool init=false ); + ~MntConfigWidget(); + + public slots: + void loadSettings( void ); + void applySettings( void ); + + protected slots: + void slotChanged(); + + private slots: + void readDFDone( void ); + void clicked( QListViewItem *item ); + void selectMntFile( void ); + void selectUmntFile( void ); + void iconChangedButton(QString); + void iconChanged( const QString & ); + void mntCmdChanged( const QString & ); + void umntCmdChanged( const QString & ); + + protected: + void closeEvent( QCloseEvent * ); + + private: + CListView *mList; + QGroupBox *mGroupBox; + QLineEdit *mIconLineEdit; + QLineEdit *mMountLineEdit; + QLineEdit *mUmountLineEdit; + QPushButton *mMountButton; + QPushButton *mUmountButton; + KIconButton *mIconButton; + DiskList mDiskList; + bool mInitializing; + QMemArray mDiskLookup; + + signals: + void configChanged(); +}; + + +#endif diff --git a/kdf/optiondialog.cpp b/kdf/optiondialog.cpp new file mode 100644 index 0000000..05c5570 --- /dev/null +++ b/kdf/optiondialog.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 1999 Espen Sand, espen@kde.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include "kdfconfig.h" +#include "mntconfig.h" +#include "optiondialog.h" + +COptionDialog::COptionDialog( QWidget *parent, const char *name, bool modal ) + :KDialogBase( Tabbed, i18n("Configure"), Help|Apply|Ok|Cancel, Ok, + parent, name, modal ) +{ + setHelp( "kcontrol/kdf/index.html", QString::null ); + + QFrame *f1 = addPage( i18n("General Settings") ); + QVBoxLayout *l1 = new QVBoxLayout( f1 ); + mConf = new KDFConfigWidget( f1, "kdfconf" ); + l1->addWidget(mConf); + connect( mConf, SIGNAL( configChanged() ), this, SLOT( slotChanged() ) ); + + QFrame *f2 = addPage( i18n("Mount Commands") ); + QVBoxLayout *l2 = new QVBoxLayout( f2 ); + mMnt = new MntConfigWidget( f2, "mntconf"); + l2->addWidget(mMnt); + connect( mMnt, SIGNAL( configChanged() ), this, SLOT( slotChanged() ) ); + enableButton( Apply, false ); + dataChanged = false; +} + + +COptionDialog::~COptionDialog( void ) +{ +} + + +void COptionDialog::slotOk( void ) +{ + if( dataChanged ) + slotApply(); + accept(); +} + + +void COptionDialog::slotApply( void ) +{ + mConf->applySettings(); + mMnt->applySettings(); + emit valueChanged(); + enableButton( Apply, false ); + dataChanged = false; +} + +void COptionDialog::slotChanged() +{ + enableButton( Apply, true ); + dataChanged = true; +} + +#include "optiondialog.moc" + + + + + + + + + diff --git a/kdf/optiondialog.h b/kdf/optiondialog.h new file mode 100644 index 0000000..d1a7a5c --- /dev/null +++ b/kdf/optiondialog.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 1999 Espen Sand, espen@kde.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _OPTION_DIALOG_H_ +#define _OPTION_DIALOG_H_ + +#include + +class KDFConfigWidget; +class MntConfigWidget; + +class COptionDialog : public KDialogBase +{ + Q_OBJECT + + public: + COptionDialog( QWidget *parent=0, const char *name=0, bool modal=true ); + ~COptionDialog( void ); + + protected slots: + virtual void slotOk( void ); + virtual void slotApply( void ); + void slotChanged(); + + signals: + void valueChanged( void ); + + private: + KDFConfigWidget *mConf; + MntConfigWidget *mMnt; + bool dataChanged; +}; + +#endif diff --git a/kdf/pics/Makefile.am b/kdf/pics/Makefile.am new file mode 100644 index 0000000..2f00b0c --- /dev/null +++ b/kdf/pics/Makefile.am @@ -0,0 +1,4 @@ +KDE_ICON = kdf kcmdf kwikdisk +pics_DATA = tick.png delete.png +picsdir = $(kde_datadir)/kdf/pics + diff --git a/kdf/pics/cr16-app-kcmdf.png b/kdf/pics/cr16-app-kcmdf.png new file mode 100644 index 0000000..7b966b6 Binary files /dev/null and b/kdf/pics/cr16-app-kcmdf.png differ diff --git a/kdf/pics/cr22-app-kcmdf.png b/kdf/pics/cr22-app-kcmdf.png new file mode 100644 index 0000000..aa92e25 Binary files /dev/null and b/kdf/pics/cr22-app-kcmdf.png differ diff --git a/kdf/pics/cr32-app-kcmdf.png b/kdf/pics/cr32-app-kcmdf.png new file mode 100644 index 0000000..eb2d9e6 Binary files /dev/null and b/kdf/pics/cr32-app-kcmdf.png differ diff --git a/kdf/pics/delete.png b/kdf/pics/delete.png new file mode 100644 index 0000000..2415dfc Binary files /dev/null and b/kdf/pics/delete.png differ diff --git a/kdf/pics/hi128-app-kdf.png b/kdf/pics/hi128-app-kdf.png new file mode 100644 index 0000000..20ba9bf Binary files /dev/null and b/kdf/pics/hi128-app-kdf.png differ diff --git a/kdf/pics/hi128-app-kwikdisk.png b/kdf/pics/hi128-app-kwikdisk.png new file mode 100644 index 0000000..cbec029 Binary files /dev/null and b/kdf/pics/hi128-app-kwikdisk.png differ diff --git a/kdf/pics/hi16-app-kdf.png b/kdf/pics/hi16-app-kdf.png new file mode 100644 index 0000000..7b966b6 Binary files /dev/null and b/kdf/pics/hi16-app-kdf.png differ diff --git a/kdf/pics/hi16-app-kwikdisk.png b/kdf/pics/hi16-app-kwikdisk.png new file mode 100644 index 0000000..e182aca Binary files /dev/null and b/kdf/pics/hi16-app-kwikdisk.png differ diff --git a/kdf/pics/hi22-app-kdf.png b/kdf/pics/hi22-app-kdf.png new file mode 100644 index 0000000..aa92e25 Binary files /dev/null and b/kdf/pics/hi22-app-kdf.png differ diff --git a/kdf/pics/hi22-app-kwikdisk.png b/kdf/pics/hi22-app-kwikdisk.png new file mode 100644 index 0000000..e150637 Binary files /dev/null and b/kdf/pics/hi22-app-kwikdisk.png differ diff --git a/kdf/pics/hi32-app-kdf.png b/kdf/pics/hi32-app-kdf.png new file mode 100644 index 0000000..eb2d9e6 Binary files /dev/null and b/kdf/pics/hi32-app-kdf.png differ diff --git a/kdf/pics/hi32-app-kwikdisk.png b/kdf/pics/hi32-app-kwikdisk.png new file mode 100644 index 0000000..be2e6ab Binary files /dev/null and b/kdf/pics/hi32-app-kwikdisk.png differ diff --git a/kdf/pics/hi48-app-kdf.png b/kdf/pics/hi48-app-kdf.png new file mode 100644 index 0000000..d976289 Binary files /dev/null and b/kdf/pics/hi48-app-kdf.png differ diff --git a/kdf/pics/hi48-app-kwikdisk.png b/kdf/pics/hi48-app-kwikdisk.png new file mode 100644 index 0000000..29d351f Binary files /dev/null and b/kdf/pics/hi48-app-kwikdisk.png differ diff --git a/kdf/pics/hi64-app-kdf.png b/kdf/pics/hi64-app-kdf.png new file mode 100644 index 0000000..984d3ee Binary files /dev/null and b/kdf/pics/hi64-app-kdf.png differ diff --git a/kdf/pics/hi64-app-kwikdisk.png b/kdf/pics/hi64-app-kwikdisk.png new file mode 100644 index 0000000..58378b1 Binary files /dev/null and b/kdf/pics/hi64-app-kwikdisk.png differ diff --git a/kdf/pics/mini-root.png b/kdf/pics/mini-root.png new file mode 100644 index 0000000..538a1bf Binary files /dev/null and b/kdf/pics/mini-root.png differ diff --git a/kdf/pics/tick.png b/kdf/pics/tick.png new file mode 100644 index 0000000..543710f Binary files /dev/null and b/kdf/pics/tick.png differ diff --git a/kdf/stdoption.cpp b/kdf/stdoption.cpp new file mode 100644 index 0000000..16a9e07 --- /dev/null +++ b/kdf/stdoption.cpp @@ -0,0 +1,148 @@ +/* +** +** Copyright (C) 1998 by Michael Kropfberger +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ + + +#include +#include + +#include "stdoption.h" + +QString CStdOption::mDefaultFileManager = "kfmclient openURL %m"; +int CStdOption::mDefaultUpdateFrequency = 60; + +CStdOption::CStdOption( void ) +{ + setDefault(); +} + + +CStdOption::~CStdOption( void ) +{ +} + + +void CStdOption::updateConfiguration( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup("KDFConfig"); + mFileManager = config.readPathEntry( + "FileManagerCommand", mDefaultFileManager ); + mUpdateFrequency = config.readNumEntry( + "UpdateFrequency", mDefaultUpdateFrequency ); + mPopupIfFull = config.readBoolEntry( + "PopupIfFull", true ); + mOpenFileManagerOnMount = config.readBoolEntry( + "OpenFileMgrOnMount", false ); +} + + +void CStdOption::writeConfiguration( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup("KDFConfig"); + config.writeEntry( "UpdateFrequency", mUpdateFrequency ); + config.writePathEntry( "FileManagerCommand", mFileManager ); + config.writeEntry( "PopupIfFull", mPopupIfFull ); + config.writeEntry( "OpenFileMgrOnMount", mOpenFileManagerOnMount ); + config.sync(); +} + + +void CStdOption::writeDefaultFileManager( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup("KDFConfig"); + config.writePathEntry( "FileManagerCommand", mDefaultFileManager ); + config.sync(); +} + + + +QString CStdOption::fileManager( void ) +{ + return( mFileManager ); +} + + +int CStdOption::updateFrequency( void ) +{ + return( mUpdateFrequency ); +} + + +bool CStdOption::popupIfFull( void ) +{ + return( mPopupIfFull ); +} + + +bool CStdOption::openFileManager( void ) +{ + return( mOpenFileManagerOnMount ); +} + + +void CStdOption::setDefault( void ) +{ + mFileManager = mDefaultFileManager; + mUpdateFrequency = mDefaultUpdateFrequency; + mPopupIfFull = true; + mOpenFileManagerOnMount = false; +} + + +void CStdOption::setFileManager( const QString &fileManager ) +{ + mFileManager = fileManager; +} + + +void CStdOption::setUpdateFrequency( int frequency ) +{ + mUpdateFrequency = frequency; +} + + +void CStdOption::setPopupIfFull( bool popupIfFull ) +{ + mPopupIfFull = popupIfFull; +} + + +void CStdOption::setOpenFileManager( bool openFileManagerOnMount ) +{ + mOpenFileManagerOnMount = openFileManagerOnMount; +} + + + + + + + + + diff --git a/kdf/stdoption.h b/kdf/stdoption.h new file mode 100644 index 0000000..282a16b --- /dev/null +++ b/kdf/stdoption.h @@ -0,0 +1,72 @@ +/* +** +** Copyright (C) 1998 by Michael Kropfberger +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +#ifndef _STD_OPTION_H_ +#define _STD_OPTION_H_ + +#include + +class CStdOption +{ + public: + CStdOption( void ); + ~CStdOption( void ); + + void updateConfiguration( void ); + void writeConfiguration( void ); + void writeDefaultFileManager( void ); + + QString fileManager( void ); + + int updateFrequency( void ); + bool popupIfFull( void ); + bool openFileManager( void ); + + void setDefault( void ); + void setFileManager( const QString &fileManager ); + void setUpdateFrequency( int frequency ); + void setPopupIfFull( bool popupIfFull ); + void setOpenFileManager( bool openFileManagerOnMount ); + + private: + static QString mDefaultFileManager; + static int mDefaultUpdateFrequency; + QString mFileManager; + int mUpdateFrequency; + bool mPopupIfFull; + bool mOpenFileManagerOnMount; +}; + +#endif + + + + + + + + + diff --git a/kdf/unix_outputs/df-g.hpux b/kdf/unix_outputs/df-g.hpux new file mode 100644 index 0000000..8d1e822 --- /dev/null +++ b/kdf/unix_outputs/df-g.hpux @@ -0,0 +1,392 @@ +/cern (lapphp0.in2p3.fr:/lapphp0_3/cern) : + 8192 file system block size 1024 fragment size + 4067219 total blocks 1381510 total free blocks + 974788 allocated free blocks -1 total i-nodes + -1 total free i-nodes -1 allocated free i-nodes + -16777209 file system id nfs file system type + 0 flags -1 file system name length + /cern file system specific string +/outils/produits/frame (lapphp0.in2p3.fr:/lapphp0_3/produits/frame) : + 8192 file system block size 1024 fragment size + 4067219 total blocks 1381510 total free blocks + 974788 allocated free blocks -1 total i-nodes + -1 total free i-nodes -1 allocated free i-nodes + -16777210 file system id nfs file system type + 0 flags -1 file system name length +/outils/produits/frame file system specific string +/outils/produits/rogue (lapphp0.in2p3.fr:/lapphp0_3/produits/rogue) : + 8192 file system block size 1024 fragment size + 4067219 total blocks 1381510 total free blocks + 974788 allocated free blocks -1 total i-nodes + -1 total free i-nodes -1 allocated free i-nodes + -16777211 file system id nfs file system type + 0 flags -1 file system name length +/outils/produits/rogue file system specific string +/lapphp1_6 (lapphp0.in2p3.fr:/lapphp1_6) : + 8192 file system block size 1024 fragment size + 4067219 total blocks 998796 total free blocks + 592074 allocated free blocks -1 total i-nodes + -1 total free i-nodes -1 allocated free i-nodes + -16777212 file system id nfs file system type + 0 flags -1 file system name length + /lapphp1_6 file system specific string +/lapphp8/mupad (lapphp8.in2p3.fr:/lapphp8/mupad) : + 8192 file system block size 1024 fragment size + 602301 total blocks 466919 total free blocks + 406688 allocated free blocks -1 total i-nodes + -1 total free i-nodes -1 allocated free i-nodes + -16777213 file system id nfs file system type + 0 flags -1 file system name length + /lapphp8/mupad file system specific string +/COMMUN (lappa0:/COMMUN ) : + 8192 file system block size 512 fragment size + 45528992 total blocks 8875966 total free blocks + 8578336 allocated free blocks -1 total i-nodes + -1 total free i-nodes -1 allocated free i-nodes + -16777214 file system id nfs file system type + 0 flags -1 file system name length + /COMMUN file system specific string +/nfs/virgoa1_2 (lappa0:/virgoa1_2 ) : + 8192 file system block size 1024 fragment size + 3783129 total blocks 756162 total free blocks + 377849 allocated free blocks -1 total i-nodes + -1 total free i-nodes -1 allocated free i-nodes + -16777215 file system id nfs file system type + 0 flags -1 file system name length + /nfs/virgoa1_2 file system specific string +/USERS/AMS (/dev/users_services/rio) : + 8192 file system block size 1024 fragment size + 498645 total blocks 163584 total free blocks + 113719 allocated free blocks 79872 total i-nodes + 70578 total free i-nodes 70578 allocated free i-nodes + 1074069514 file system id hfs file system type + 0 flags 255 file system name length + /USERS/AMS file system specific string +/USERS/elec (/dev/export/lvol3 ) : + 8192 file system block size 1024 fragment size + 1008204 total blocks 469459 total free blocks + 368638 allocated free blocks 118784 total i-nodes + 111661 total free i-nodes 111661 allocated free i-nodes + 1074135043 file system id hfs file system type + 0 flags 255 file system name length + /USERS/elec file system specific string +/backup/increm2 (/dev/backup/lvol4 ) : + 8192 file system block size 1024 fragment size + 3791196 total blocks 3145626 total free blocks + 2766506 allocated free blocks 444416 total i-nodes + 438557 total free i-nodes 438557 allocated free i-nodes + 1074003972 file system id hfs file system type + 0 flags 255 file system name length +/backup/increm2 file system specific string +/backup/increm3 (/dev/backup/lvol1 ) : + 8192 file system block size 1024 fragment size + 2535501 total blocks 1158823 total free blocks + 905272 allocated free blocks 184320 total i-nodes + 177347 total free i-nodes 177347 allocated free i-nodes + 1074003969 file system id hfs file system type + 0 flags 255 file system name length +/backup/increm3 file system specific string +/backup/incremental (/dev/backup/lvol2 ) : + 8192 file system block size 1024 fragment size + 4056813 total blocks 2845324 total free blocks + 2439642 allocated free blocks 294912 total i-nodes + 290399 total free i-nodes 290399 allocated free i-nodes + 1074003970 file system id hfs file system type + 0 flags 255 file system name length +/backup/incremental file system specific string +/cdrom (/dev/dsk/c1t2d0 ) : + 2048 file system block size 2048 fragment size + 1228800 total blocks 0 total free blocks + 0 allocated free blocks -1 total i-nodes + 0 total free i-nodes 0 allocated free i-nodes + 469835776 file system id cdfs file system type + 0x1 flags 37 file system name length + /cdrom file system specific string +/export/cetia (/dev/users_services/lvol9) : + 8192 file system block size 1024 fragment size + 504092 total blocks 247465 total free blocks + 197055 allocated free blocks 59392 total i-nodes + 51963 total free i-nodes 51963 allocated free i-nodes + 1074069513 file system id hfs file system type + 0 flags 255 file system name length + /export/cetia file system specific string +/export/fic (/dev/outils/lvol4 ) : + 8192 file system block size 1024 fragment size + 504092 total blocks 457204 total free blocks + 406794 allocated free blocks 59392 total i-nodes + 56723 total free i-nodes 56723 allocated free i-nodes + 1073938436 file system id hfs file system type + 0 flags 255 file system name length + /export/fic file system specific string +/export/hp (/dev/export/lvol5 ) : + 8192 file system block size 1024 fragment size + 999532 total blocks 277788 total free blocks + 177834 allocated free blocks 116736 total i-nodes + 96353 total free i-nodes 96353 allocated free i-nodes + 1074135045 file system id hfs file system type + 0 flags 255 file system name length + /export/hp file system specific string +/export/solaris (/dev/export/lvol4 ) : + 8192 file system block size 1024 fragment size + 604860 total blocks 296077 total free blocks + 235591 allocated free blocks 71680 total i-nodes + 49145 total free i-nodes 49145 allocated free i-nodes + 1074135044 file system id hfs file system type + 0 flags 255 file system name length +/export/solaris file system specific string +/export/sun (/dev/export/lvol1 ) : + 8192 file system block size 1024 fragment size + 1008204 total blocks 483024 total free blocks + 382203 allocated free blocks 118784 total i-nodes + 100998 total free i-nodes 100998 allocated free i-nodes + 1074135041 file system id hfs file system type + 0 flags 255 file system name length + /export/sun file system specific string +/export/tektro (/dev/export/lvol2 ) : + 8192 file system block size 1024 fragment size + 403308 total blocks 59710 total free blocks + 19379 allocated free blocks 47104 total i-nodes + 42499 total free i-nodes 42499 allocated free i-nodes + 1074135042 file system id hfs file system type + 0 flags 255 file system name length + /export/tektro file system specific string +/export/www (/dev/users_services/lvol8) : + 8192 file system block size 1024 fragment size + 604860 total blocks 390825 total free blocks + 330339 allocated free blocks 71680 total i-nodes + 70943 total free i-nodes 70943 allocated free i-nodes + 1074069512 file system id hfs file system type + 0 flags 255 file system name length + /export/www file system specific string +/home (/dev/vg00/lvol4 ) : + 8192 file system block size 1024 fragment size + 19861 total blocks 19851 total free blocks + 17864 allocated free blocks 3456 total i-nodes + 3451 total free i-nodes 3451 allocated free i-nodes + 1073741828 file system id hfs file system type + 0 flags 255 file system name length + /home file system specific string +/outils/adm (/dev/outils/lvol3 ) : + 8192 file system block size 1024 fragment size + 504092 total blocks 240604 total free blocks + 190194 allocated free blocks 59392 total i-nodes + 57466 total free i-nodes 57466 allocated free i-nodes + 1073938435 file system id hfs file system type + 0 flags 255 file system name length + /outils/adm file system specific string +/outils/mail (/dev/outils/lvol6 ) : + 8192 file system block size 1024 fragment size + 302284 total blocks 258286 total free blocks + 228057 allocated free blocks 36864 total i-nodes + 36724 total free i-nodes 36724 allocated free i-nodes + 1073938438 file system id hfs file system type + 0 flags 255 file system name length + /outils/mail file system specific string +/outils/newlp (/dev/vg00/newlp ) : + 8192 file system block size 1024 fragment size + 99669 total blocks 98347 total free blocks + 88380 allocated free blocks 16128 total i-nodes + 16011 total free i-nodes 16011 allocated free i-nodes + 1073741833 file system id hfs file system type + 0 flags 255 file system name length + /outils/newlp file system specific string +/outils/produits (/dev/outils/lvol1 ) : + 8192 file system block size 1024 fragment size + 1806700 total blocks 380397 total free blocks + 199727 allocated free blocks 212992 total i-nodes + 183645 total free i-nodes 183645 allocated free i-nodes + 1073938433 file system id hfs file system type + 0 flags 255 file system name length +/outils/produits file system specific string +/outils/securite (/dev/vg00/securite ) : + 8192 file system block size 1024 fragment size + 175445 total blocks 167330 total free blocks + 149785 allocated free blocks 28416 total i-nodes + 28178 total free i-nodes 28178 allocated free i-nodes + 1073741834 file system id hfs file system type + 0 flags 255 file system name length +/outils/securite file system specific string +/outils/swap (/dev/outils/lvol5 ) : + 8192 file system block size 1024 fragment size + 504092 total blocks 349880 total free blocks + 299470 allocated free blocks 59392 total i-nodes + 59312 total free i-nodes 59312 allocated free i-nodes + 1073938437 file system id hfs file system type + 0 flags 255 file system name length + /outils/swap file system specific string +/outils/tmp (/dev/outils/lvol2 ) : + 8192 file system block size 1024 fragment size + 504092 total blocks 259369 total free blocks + 208959 allocated free blocks 59392 total i-nodes + 57081 total free i-nodes 57081 allocated free i-nodes + 1073938434 file system id hfs file system type + 0 flags 255 file system name length + /outils/tmp file system specific string +/tmp (/dev/vg00/lvol6 ) : + 8192 file system block size 1024 fragment size + 23013 total blocks 13120 total free blocks + 10818 allocated free blocks 10880 total i-nodes + 10456 total free i-nodes 10456 allocated free i-nodes + 1073741830 file system id hfs file system type + 0 flags 255 file system name length + /tmp file system specific string +/users/admin (/dev/users_services/lvol5) : + 8192 file system block size 1024 fragment size + 302284 total blocks 202293 total free blocks + 172064 allocated free blocks 36864 total i-nodes + 34848 total free i-nodes 34848 allocated free i-nodes + 1074069509 file system id hfs file system type + 0 flags 255 file system name length + /users/admin file system specific string +/users/aleph (/dev/users_manip/lvol9) : + 8192 file system block size 1024 fragment size + 403308 total blocks 42599 total free blocks + 2268 allocated free blocks 47104 total i-nodes + 46495 total free i-nodes 46495 allocated free i-nodes + 1073872905 file system id hfs file system type + 0 flags 255 file system name length + /users/aleph file system specific string +/users/atlas (/dev/users_manip/lvol8) : + 8192 file system block size 1024 fragment size + 403308 total blocks 173249 total free blocks + 132918 allocated free blocks 47104 total i-nodes + 45153 total free i-nodes 45153 allocated free i-nodes + 1073872904 file system id hfs file system type + 0 flags 255 file system name length + /users/atlas file system specific string +/users/autres (/dev/users_manip/lvol6) : + 8192 file system block size 1024 fragment size + 403308 total blocks 65799 total free blocks + 25468 allocated free blocks 47104 total i-nodes + 43062 total free i-nodes 43062 allocated free i-nodes + 1073872902 file system id hfs file system type + 0 flags 255 file system name length + /users/autres file system specific string +/users/backup (/dev/backup/lvol3 ) : + 8192 file system block size 1024 fragment size + 2535501 total blocks 242538 total free blocks + 0 allocated free blocks 184320 total i-nodes + 182966 total free i-nodes 182966 allocated free i-nodes + 1074003971 file system id hfs file system type + 0 flags 255 file system name length + /users/backup file system specific string +/users/calcul (/dev/users_services/lvol4) : + 8192 file system block size 1024 fragment size + 2016620 total blocks 538692 total free blocks + 337030 allocated free blocks 235520 total i-nodes + 205815 total free i-nodes 205815 allocated free i-nodes + 1074069508 file system id hfs file system type + 0 flags 255 file system name length + /users/calcul file system specific string +/users/chooz (/dev/users_manip/lvol10) : + 8192 file system block size 1024 fragment size + 403308 total blocks 114724 total free blocks + 74393 allocated free blocks 47104 total i-nodes + 40686 total free i-nodes 40686 allocated free i-nodes + 1073872906 file system id hfs file system type + 0 flags 255 file system name length + /users/chooz file system specific string +/users/cms (/dev/users_manip/lvol3) : + 8192 file system block size 1024 fragment size + 798476 total blocks 284186 total free blocks + 204338 allocated free blocks 94208 total i-nodes + 78569 total free i-nodes 78569 allocated free i-nodes + 1073872899 file system id hfs file system type + 0 flags 255 file system name length + /users/cms file system specific string +/users/ftp (/dev/users_services/lvol3) : + 8192 file system block size 1024 fragment size + 201516 total blocks 70339 total free blocks + 50187 allocated free blocks 24576 total i-nodes + 24019 total free i-nodes 24019 allocated free i-nodes + 1074069507 file system id hfs file system type + 0 flags 255 file system name length + /users/ftp file system specific string +/users/l3 (/dev/users_manip/lvol2) : + 8192 file system block size 1024 fragment size + 201516 total blocks 201097 total free blocks + 180945 allocated free blocks 24576 total i-nodes + 24533 total free i-nodes 24533 allocated free i-nodes + 1073872898 file system id hfs file system type + 0 flags 255 file system name length + /users/l3 file system specific string +/users/mecanique (/dev/users_services/lvol7) : + 8192 file system block size 1024 fragment size + 403308 total blocks 352849 total free blocks + 312518 allocated free blocks 47104 total i-nodes + 44704 total free i-nodes 44704 allocated free i-nodes + 1074069511 file system id hfs file system type + 0 flags 255 file system name length +/users/mecanique file system specific string +/users/na50 (/dev/users_manip/lvol1) : + 8192 file system block size 1024 fragment size + 302284 total blocks 44997 total free blocks + 14768 allocated free blocks 36864 total i-nodes + 34548 total free i-nodes 34548 allocated free i-nodes + 1073872897 file system id hfs file system type + 0 flags 255 file system name length + /users/na50 file system specific string +/users/nomad (/dev/users_manip/lvol4) : + 8192 file system block size 1024 fragment size + 403308 total blocks 49910 total free blocks + 9579 allocated free blocks 47104 total i-nodes + 36509 total free i-nodes 36509 allocated free i-nodes + 1073872900 file system id hfs file system type + 0 flags 255 file system name length + /users/nomad file system specific string +/users/ovw (/dev/users_services/OVW) : + 8192 file system block size 1024 fragment size + 600571 total blocks 587212 total free blocks + 527154 allocated free blocks 95680 total i-nodes + 95584 total free i-nodes 95584 allocated free i-nodes + 1074069506 file system id hfs file system type + 0 flags 255 file system name length + /users/ovw file system specific string +/users/swap (/dev/users_services/lvol1) : + 8192 file system block size 1024 fragment size + 604860 total blocks 604851 total free blocks + 544365 allocated free blocks 71680 total i-nodes + 71676 total free i-nodes 71676 allocated free i-nodes + 1074069505 file system id hfs file system type + 0 flags 255 file system name length + /users/swap file system specific string +/users/theorie (/dev/users_manip/lvol5) : + 8192 file system block size 1024 fragment size + 403308 total blocks 338520 total free blocks + 298189 allocated free blocks 47104 total i-nodes + 45098 total free i-nodes 45098 allocated free i-nodes + 1073872901 file system id hfs file system type + 0 flags 255 file system name length + /users/theorie file system specific string +/users/virgo (/dev/users_manip/lvol7) : + 8192 file system block size 1024 fragment size + 403308 total blocks 48737 total free blocks + 8406 allocated free blocks 47104 total i-nodes + 45583 total free i-nodes 45583 allocated free i-nodes + 1073872903 file system id hfs file system type + 0 flags 255 file system name length + /users/virgo file system specific string +/usr (/dev/vg00/lvol7 ) : + 8192 file system block size 1024 fragment size + 299157 total blocks 42849 total free blocks + 12933 allocated free blocks 48000 total i-nodes + 32334 total free i-nodes 32334 allocated free i-nodes + 1073741831 file system id hfs file system type + 0 flags 255 file system name length + /usr file system specific string +/var (/dev/vg00/lvol8 ) : + 8192 file system block size 1024 fragment size + 69125 total blocks 35338 total free blocks + 28425 allocated free blocks 32640 total i-nodes + 31684 total free i-nodes 31684 allocated free i-nodes + 1073741832 file system id hfs file system type + 0 flags 255 file system name length + /var file system specific string +/ (/dev/vg00/lvol1 ) : + 8192 file system block size 1024 fragment size + 59797 total blocks 22524 total free blocks + 16544 allocated free blocks 9600 total i-nodes + 7301 total free i-nodes 7301 allocated free i-nodes + 1073741825 file system id hfs file system type + 0 flags 255 file system name length + / file system specific string diff --git a/kdf/unix_outputs/df-k.digital b/kdf/unix_outputs/df-k.digital new file mode 100644 index 0000000..ae61ca5 --- /dev/null +++ b/kdf/unix_outputs/df-k.digital @@ -0,0 +1,42 @@ +Filesystem 1024-blocks Used Available Capacity Mounted on +root_domain#root 265536 92583 159784 37% / +/proc 0 0 0 100% /proc +usr_domain#usr 1996712 553180 1424016 28% /usr +var_domain#var 1796712 74125 1714456 5% /var +/dev/rz17a 969738 115812 756952 14% /afscache +user_domain#calcul 1066986 626663 440323 59% /users/calcul +user_domain#atlas 444577 418063 26514 95% /users/atlas +user_domain#mecanique 444577 47918 396659 11% /users/mecanique +user_domain#elec 533493 527901 5592 99% /users/elec +user_domain#ams 889155 749420 139735 85% /users/ams +user_domain#theorie 1600479 1109849 490630 70% /users/theorie +data_domain#calcul 1043416 10376 1033040 1% /data/calcul +data_domain#elec 1043415 144 1043271 1% /data/elec +data_domain#admin 521707 24 521683 1% /data/admin +data_domain#l3 521707 331546 190161 64% /data/l3 +data_domain#theorie 2608538 1558632 1049906 60% /data/theorie +data_domain#atlas 1043415 825608 217807 80% /data/atlas +data_domain#virgo 1043415 32 1043383 1% /data/virgo +data_domain#aleph 1565123 72119 1493004 5% /data/aleph +data_domain#na50 521707 16 521691 1% /data/na50 +data_domain#babar 1043415 24 1043391 1% /data/babar +data_domain#cms 1043415 32 1043383 1% /data/cms +data_domain#ams 2086830 1016564 1070266 49% /data/ams +data_domain#nomad 1043415 32 1043383 1% /data/nomad +user_domain#l3 444577 116017 328560 27% /users/l3 +user_domain#aleph 444577 9672 434905 3% /users/aleph +user_domain#na50 444577 16 444561 1% /users/na50 +user_domain#babar 444577 6561 438016 2% /users/babar +user_domain#cms 444577 5902 438675 2% /users/cms +user_domain#nomad 444577 13956 430621 4% /users/nomad +user_domain#admin 444577 3294 441283 1% /users/admin +data_domain#mecanique 521707 42026 479681 9% /data/mecanique +user_domain#virgo 444577 58 444519 1% /users/virgo +user_domain#autres 444577 857 443720 1% /users/autres +data_domain#autres 521707 17216 504491 4% /data/autres +/COMMUN@lappa0 22764496 18302140 4313416 81% /COMMUN +/opt@lappa0 6245280 4713319 1392480 78% /opt +/var/spool/mail@lappa0 2653928 1201276 1415072 46% /var/spool/mail +/virgoa1_3@lappa0 8574909 7165973 551445 93% /virgoa1_3 +/lappa6_2@lappa0 8598343 4844545 2893963 63% /lappa6_2 +AFS 2000000 0 2000000 0% /afs diff --git a/kdf/unix_outputs/df-k.hpux b/kdf/unix_outputs/df-k.hpux new file mode 100644 index 0000000..3e9a386 --- /dev/null +++ b/kdf/unix_outputs/df-k.hpux @@ -0,0 +1,196 @@ +/cern (lapphp0.in2p3.fr:/lapphp0_3/cern) : 3660497 total allocated Kb + 974788 free allocated Kb + 2685709 used allocated Kb + 73 % allocation used +/outils/produits/frame (lapphp0.in2p3.fr:/lapphp0_3/produits/frame) : 3660497 total allocated Kb + 974788 free allocated Kb + 2685709 used allocated Kb + 73 % allocation used +/outils/produits/rogue (lapphp0.in2p3.fr:/lapphp0_3/produits/rogue) : 3660497 total allocated Kb + 974788 free allocated Kb + 2685709 used allocated Kb + 73 % allocation used +/lapphp1_6 (lapphp0.in2p3.fr:/lapphp1_6) : 3660497 total allocated Kb + 592074 free allocated Kb + 3068423 used allocated Kb + 83 % allocation used +/lapphp8/mupad (lapphp8.in2p3.fr:/lapphp8/mupad) : 542070 total allocated Kb + 406688 free allocated Kb + 135382 used allocated Kb + 24 % allocation used +/COMMUN (lappa0:/COMMUN ) : 0 total allocated Kb + 0 free allocated Kb + 0 used allocated Kb + 81 % allocation used +/nfs/virgoa1_2 (lappa0:/virgoa1_2 ) : 3404816 total allocated Kb + 377849 free allocated Kb + 3026967 used allocated Kb + 88 % allocation used +/USERS/AMS (/dev/users_services/rio) : 448780 total allocated Kb + 113719 free allocated Kb + 335061 used allocated Kb + 74 % allocation used +/USERS/elec (/dev/export/lvol3 ) : 907383 total allocated Kb + 368658 free allocated Kb + 538725 used allocated Kb + 59 % allocation used +/backup/increm2 (/dev/backup/lvol4 ) : 3412076 total allocated Kb + 2766506 free allocated Kb + 645570 used allocated Kb + 18 % allocation used +/backup/increm3 (/dev/backup/lvol1 ) : 2281950 total allocated Kb + 905272 free allocated Kb + 1376678 used allocated Kb + 60 % allocation used +/backup/incremental (/dev/backup/lvol2 ) : 3651131 total allocated Kb + 2439642 free allocated Kb + 1211489 used allocated Kb + 33 % allocation used +/cdrom (/dev/dsk/c1t2d0 ) : 2457600 total allocated Kb + 0 free allocated Kb + 2457600 used allocated Kb + 100 % allocation used +/export/cetia (/dev/users_services/lvol9) : 453682 total allocated Kb + 197055 free allocated Kb + 256627 used allocated Kb + 56 % allocation used +/export/fic (/dev/outils/lvol4 ) : 453682 total allocated Kb + 406794 free allocated Kb + 46888 used allocated Kb + 10 % allocation used +/export/hp (/dev/export/lvol5 ) : 899578 total allocated Kb + 177834 free allocated Kb + 721744 used allocated Kb + 80 % allocation used +/export/solaris (/dev/export/lvol4 ) : 544374 total allocated Kb + 235591 free allocated Kb + 308783 used allocated Kb + 56 % allocation used +/export/sun (/dev/export/lvol1 ) : 907383 total allocated Kb + 382203 free allocated Kb + 525180 used allocated Kb + 57 % allocation used +/export/tektro (/dev/export/lvol2 ) : 362977 total allocated Kb + 19379 free allocated Kb + 343598 used allocated Kb + 94 % allocation used +/export/www (/dev/users_services/lvol8) : 544374 total allocated Kb + 330339 free allocated Kb + 214035 used allocated Kb + 39 % allocation used +/home (/dev/vg00/lvol4 ) : 17874 total allocated Kb + 17864 free allocated Kb + 10 used allocated Kb + 0 % allocation used +/outils/adm (/dev/outils/lvol3 ) : 453682 total allocated Kb + 190194 free allocated Kb + 263488 used allocated Kb + 58 % allocation used +/outils/mail (/dev/outils/lvol6 ) : 272055 total allocated Kb + 228067 free allocated Kb + 43988 used allocated Kb + 16 % allocation used +/outils/newlp (/dev/vg00/newlp ) : 89702 total allocated Kb + 88381 free allocated Kb + 1321 used allocated Kb + 1 % allocation used +/outils/produits (/dev/outils/lvol1 ) : 1626030 total allocated Kb + 199727 free allocated Kb + 1426303 used allocated Kb + 87 % allocation used +/outils/securite (/dev/vg00/securite ) : 157900 total allocated Kb + 149785 free allocated Kb + 8115 used allocated Kb + 5 % allocation used +/outils/swap (/dev/outils/lvol5 ) : 453682 total allocated Kb + 309750 free allocated Kb + 143932 used allocated Kb + 31 % allocation used +/outils/tmp (/dev/outils/lvol2 ) : 453682 total allocated Kb + 208958 free allocated Kb + 244724 used allocated Kb + 53 % allocation used +/tmp (/dev/vg00/lvol6 ) : 20711 total allocated Kb + 10970 free allocated Kb + 9741 used allocated Kb + 47 % allocation used +/users/admin (/dev/users_services/lvol5) : 272055 total allocated Kb + 172064 free allocated Kb + 99991 used allocated Kb + 36 % allocation used +/users/aleph (/dev/users_manip/lvol9) : 362977 total allocated Kb + 2268 free allocated Kb + 360709 used allocated Kb + 99 % allocation used +/users/atlas (/dev/users_manip/lvol8) : 362977 total allocated Kb + 132918 free allocated Kb + 230059 used allocated Kb + 63 % allocation used +/users/autres (/dev/users_manip/lvol6) : 362977 total allocated Kb + 25468 free allocated Kb + 337509 used allocated Kb + 92 % allocation used +/users/backup (/dev/backup/lvol3 ) : 2292963 total allocated Kb + 0 free allocated Kb + 2292963 used allocated Kb + 100 % allocation used +/users/calcul (/dev/users_services/lvol4) : 1814958 total allocated Kb + 337030 free allocated Kb + 1477928 used allocated Kb + 81 % allocation used +/users/chooz (/dev/users_manip/lvol10) : 362977 total allocated Kb + 74394 free allocated Kb + 288583 used allocated Kb + 79 % allocation used +/users/cms (/dev/users_manip/lvol3) : 718628 total allocated Kb + 204338 free allocated Kb + 514290 used allocated Kb + 71 % allocation used +/users/ftp (/dev/users_services/lvol3) : 181364 total allocated Kb + 50187 free allocated Kb + 131177 used allocated Kb + 72 % allocation used +/users/l3 (/dev/users_manip/lvol2) : 181364 total allocated Kb + 180945 free allocated Kb + 419 used allocated Kb + 0 % allocation used +/users/mecanique (/dev/users_services/lvol7) : 362977 total allocated Kb + 312518 free allocated Kb + 50459 used allocated Kb + 13 % allocation used +/users/na50 (/dev/users_manip/lvol1) : 272055 total allocated Kb + 14768 free allocated Kb + 257287 used allocated Kb + 94 % allocation used +/users/nomad (/dev/users_manip/lvol4) : 362977 total allocated Kb + 9579 free allocated Kb + 353398 used allocated Kb + 97 % allocation used +/users/ovw (/dev/users_services/OVW) : 540513 total allocated Kb + 527154 free allocated Kb + 13359 used allocated Kb + 2 % allocation used +/users/swap (/dev/users_services/lvol1) : 544374 total allocated Kb + 544365 free allocated Kb + 9 used allocated Kb + 0 % allocation used +/users/theorie (/dev/users_manip/lvol5) : 362977 total allocated Kb + 298189 free allocated Kb + 64788 used allocated Kb + 17 % allocation used +/users/virgo (/dev/users_manip/lvol7) : 362977 total allocated Kb + 8406 free allocated Kb + 354571 used allocated Kb + 97 % allocation used +/usr (/dev/vg00/lvol7 ) : 269241 total allocated Kb + 12933 free allocated Kb + 256308 used allocated Kb + 95 % allocation used +/var (/dev/vg00/lvol8 ) : 62212 total allocated Kb + 28427 free allocated Kb + 33785 used allocated Kb + 54 % allocation used +/ (/dev/vg00/lvol1 ) : 53817 total allocated Kb + 16544 free allocated Kb + 37273 used allocated Kb + 69 % allocation used diff --git a/kdf/unix_outputs/df.man.hpux b/kdf/unix_outputs/df.man.hpux new file mode 100644 index 0000000..969320d --- /dev/null +++ b/kdf/unix_outputs/df.man.hpux @@ -0,0 +1,198 @@ + + + + df(1M) df(1M) + + + + + NAME + df (generic) - report number of free file system disk blocks + + SYNOPSIS + /usr/bin/df [-F FStype] [-befgiklnv] [-t|-P] [-o specific_options] [-V] + [special|directory]... + + DESCRIPTION + The df command displays the number of free 512-byte blocks and free + inodes available for file systems by examining the counts kept in the + superblock or superblocks. If a special or a directory is not + specified, the free space on all mounted file systems is displayed. + If the arguments to df are path names, df reports on the file systems + containing the named files. If the argument to df is a special of an + unmounted file system, the free space in the unmounted file system is + displayed. + + Options + df recognizes the following options: + + -b Report only the number of kilobytes (KB) free. + + -e Report the number of files free. + + -f Report only the actual count of the blocks in the + free list (free inodes are not reported). + + -F FStype Report only on the FStype file system type (see + fstyp(1M)). + + -g Report the entire structure described in + statvfs(2). + + -i Report the total number of inodes, the number of + free inodes, number of used inodes, and the + percentage of inodes in use. + + -k Report the allocation in kilobytes (KB). + + -l Report on local file systems only. + + -n Report the file system name. If used with no + other options, display a list of mounted file + system types. + + -o specific_options + Specify options specific to each file system type. + specific_options is a comma-separated list of + suboptions intended for a specific FStype module + of the command. See the file-system-specific + manual entries for further details. + + + + Hewlett-Packard Company - 1 - HP-UX Release 10.10: November 1995 + + + + + + + df(1M) df(1M) + + + + + -P Report the name of the file system, the size of + the file system, the number of blocks used, the + number of blocks free, the percentage of blocks + used and the directory below which the file system + hierarchy appears. + + -t Report the total allocated block figures and the + number of free blocks. + + -v Report the percentage of blocks used, the number + of blocks used, and the number of blocks free. + This option cannot be used with other options. + + -V Echo the completed command line, but perform no + other action. The command line is generated by + incorporating the user-specified options and other + information derived from /etc/fstab. This option + allows the user to verify the command line. + + EXTERNAL INFLUENCES + Environment Variables + LC_MESSAGES determines the language in which messages are displayed. + + If LC_MESSAGES is not specified in the environment or is set to the + empty string, the value of LANG is used as a default for each + unspecified or empty variable. If LANG is not specified or is set to + the empty string, a default of "C" (see lang(5)) is used instead of + LANG. + + If any internationalization variable contains an invalid setting, df + behaves as if all internationalization variables are set to "C". See + environ(5). + + International Code Set Support + Single-byte and multi-byte character code sets are supported. + + EXAMPLES + Report the number of free disk blocks for all mounted file systems: + + df + + Report the number of free disk blocks for all mounted HFS file + systems: + + df -F hfs + + Report the number of free files for all mounted NFS file systems: + + df -F nfs -e + + + + + + Hewlett-Packard Company - 2 - HP-UX Release 10.10: November 1995 + + + + + + + df(1M) df(1M) + + + + + Report the total allocated block figures and the number of free + blocks, for all mounted file systems: + + df -t + + Report the total allocated block figures and the number of free + blocks, for the file system mounted as /usr: + + df -t /usr + + FILES + /dev/dsk/* File system devices + /etc/fstab Static information about the file systems + /etc/mnttab Mounted file system table + SEE ALSO + du(1), df_FStype(1M), fsck(1M), fstab(4), fstyp(1M), statvfs(2), + mnttab(4). + STANDARDS CONFORMANCE + df: SVID2, SVID3, XPG2, XPG3, XPG4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Hewlett-Packard Company - 3 - HP-UX Release 10.10: November 1995 + + + diff --git a/kdf/unix_outputs/etcfstab.digital b/kdf/unix_outputs/etcfstab.digital new file mode 100644 index 0000000..1bfcc0e --- /dev/null +++ b/kdf/unix_outputs/etcfstab.digital @@ -0,0 +1,43 @@ +root_domain#root / advfs rw 0 0 +/proc /proc procfs rw 0 0 +usr_domain#usr /usr advfs rw 0 0 +var_domain#var /var advfs rw 0 0 +/dev/rz16b swap1 ufs sw 0 2 +/dev/rz14a swap2 ufs sw 0 2 +/dev/rz17a /afscache ufs rw 1 2 +/COMMUN@lappa0 /COMMUN nfs rw,bg 0 0 +/opt@lappa0 /opt nfs rw,bg 0 0 +/var/spool/mail@lappa0 /var/spool/mail nfs rw,bg 0 0 +/w3@lappa0 /w3 nfs rw,bg 0 0 +/virgoa1_3@lappa0 /virgoa1_3 nfs rw,bg 0 0 +/lappa6_2@lappa0 /lappa6_2 nfs rw,bg 0 0 +user_domain#calcul /users/calcul advfs rw,userquota,groupquota 0 2 +user_domain#atlas /users/atlas advfs rw,userquota,groupquota 0 2 +user_domain#mecanique /users/mecanique advfs rw,userquota,groupquota 0 2 +user_domain#elec /users/elec advfs rw,userquota,groupquota 0 2 +user_domain#ams /users/ams advfs rw,userquota,groupquota 0 2 +user_domain#theorie /users/theorie advfs rw,userquota,groupquota 0 2 +data_domain#calcul /data/calcul advfs rw,userquota,groupquota 0 2 +data_domain#elec /data/elec advfs rw,userquota,groupquota 0 2 +data_domain#admin /data/admin advfs rw,userquota,groupquota 0 2 +data_domain#l3 /data/l3 advfs rw,userquota,groupquota 0 2 +data_domain#theorie /data/theorie advfs rw,userquota,groupquota 0 2 +data_domain#atlas /data/atlas advfs rw,userquota,groupquota 0 2 +data_domain#virgo /data/virgo advfs rw,userquota,groupquota 0 2 +data_domain#aleph /data/aleph advfs rw,userquota,groupquota 0 2 +data_domain#na50 /data/na50 advfs rw,userquota,groupquota 0 2 +data_domain#babar /data/babar advfs rw,userquota,groupquota 0 2 +data_domain#cms /data/cms advfs rw,userquota,groupquota 0 2 +data_domain#ams /data/ams advfs rw,userquota,groupquota 0 2 +data_domain#nomad /data/nomad advfs rw,userquota,groupquota 0 2 +user_domain#l3 /users/l3 advfs rw,userquota,groupquota 0 2 +user_domain#aleph /users/aleph advfs rw,userquota,groupquota 0 2 +user_domain#na50 /users/na50 advfs rw,userquota,groupquota 0 2 +user_domain#babar /users/babar advfs rw,userquota,groupquota 0 2 +user_domain#cms /users/cms advfs rw,userquota,groupquota 0 2 +user_domain#nomad /users/nomad advfs rw,userquota,groupquota 0 2 +user_domain#admin /users/admin advfs rw,userquota,groupquota 0 2 +data_domain#mecanique /data/mecanique advfs rw,userquota,groupquota 0 2 +user_domain#virgo /users/virgo advfs rw,userquota,groupquota 0 2 +user_domain#autres /users/autres advfs rw,userquota,groupquota 0 2 +data_domain#autres /data/autres advfs rw,userquota,groupquota 0 2 diff --git a/kdf/unix_outputs/etcfstab.hpux b/kdf/unix_outputs/etcfstab.hpux new file mode 100644 index 0000000..af333b1 --- /dev/null +++ b/kdf/unix_outputs/etcfstab.hpux @@ -0,0 +1,75 @@ +/dev/vg00/lvol1 / hfs defaults 0 1 +/dev/vg00/lvol3 ... swap defaults 0 0 +/dev/vg00/lvol4 /home hfs defaults 0 2 +/dev/vg00/lvol6 /tmp hfs defaults 0 2 +/dev/vg00/lvol7 /usr hfs defaults 0 2 +/dev/vg00/lvol8 /var hfs defaults 0 2 +/dev/vg00/newlp /outils/newlp hfs rw,suid 0 2 +# +/dev/export/lvol1 /export/sun hfs rw,suid 0 2 +/dev/export/lvol2 /export/tektro hfs rw,suid 0 2 +/dev/export/lvol3 /USERS/elec hfs rw,suid 0 2 +/dev/export/lvol4 /export/solaris hfs rw,suid 0 2 +/dev/export/lvol5 /export/hp hfs rw,suid 0 2 +# +/dev/users_manip/lvol1 /users/na50 hfs rw,suid 0 2 +/dev/users_manip/lvol2 /users/l3 hfs rw,suid 0 2 +/dev/users_manip/lvol3 /users/cms hfs rw,suid 0 2 +/dev/users_manip/lvol4 /users/nomad hfs rw,suid 0 2 +/dev/users_manip/lvol5 /users/theorie hfs rw,suid 0 2 +/dev/users_manip/lvol6 /users/autres hfs rw,suid 0 2 +/dev/users_manip/lvol7 /users/virgo hfs rw,suid 0 2 +/dev/users_manip/lvol8 /users/atlas hfs rw,suid 0 2 +/dev/users_manip/lvol9 /users/aleph hfs rw,suid 0 2 +/dev/users_manip/lvol10 /users/chooz hfs rw,suid 0 2 +# +/dev/users_services/lvol1 /users/swap hfs rw,suid 0 2 +/dev/users_services/lvol3 /users/ftp hfs rw,suid 0 2 +/dev/users_services/lvol4 /users/calcul hfs rw,suid 0 2 +/dev/users_services/lvol5 /users/admin hfs rw,suid 0 2 +/dev/users_services/lvol7 /users/mecanique hfs rw,suid 0 2 +/dev/users_services/lvol8 /export/www hfs rw,suid 0 2 +/dev/users_services/lvol9 /export/cetia hfs rw,suid 0 2 +/dev/users_services/rio /USERS/AMS hfs rw,suid 0 2 +/dev/users_services/OVW /users/ovw hfs rw,suid 0 2 +# +/dev/outils/lvol1 /outils/produits hfs rw,suid 0 2 +/dev/outils/lvol2 /outils/tmp hfs rw,suid 0 2 +/dev/outils/lvol3 /outils/adm hfs rw,suid 0 2 +/dev/outils/lvol4 /export/fic hfs rw,suid 0 2 +/dev/outils/lvol5 /outils/swap hfs rw,suid 0 2 +/dev/outils/lvol5 /outils/swap swapfs min=12800,lim=38400,pri=1 0 2 +/dev/outils/lvol6 /outils/mail hfs rw,suid 0 2 +# +/dev/backup/lvol1 /backup/increm3 hfs rw,suid 0 2 +/dev/backup/lvol2 /backup/incremental hfs rw,suid 0 2 +/dev/backup/lvol3 /users/backup hfs rw,suid 0 2 +/dev/backup/lvol4 /backup/increm2 hfs rw,suid 0 2 +# +#---------------------------------------------------- +# le CDROM est toujours a part +#------------------------------------------- +/dev/dsk/c1t2d0 /cdrom cdfs ro,suid 0 2 +# +#----------------------------------- +# rondelles NFS +#--------------------------------------------------- +# lapphp0 +lapphp0.in2p3.fr:/lapphp0_3/cern /cern nfs rw,suid,bg 0 0 +lapphp0.in2p3.fr:/lapphp0_3/produits/frame /outils/produits/frame nfs rw,suid,bg 0 0 +lapphp0.in2p3.fr:/lapphp0_3/produits/rogue /outils/produits/rogue nfs rw,suid,bg 0 0 +lapphp0.in2p3.fr:/lapphp1_6 /lapphp1_6 nfs rw,suid,bg 0 0 +#lapphp0.in2p3.fr:/lapphp0_2/local /usr/local.hp0 nfs rw,suid,bg 0 0 +# pour Alain Bazan (5/01/98) +#lapphp0.in2p3.fr:/usr/lib/X11R6 /usr/lib/X11R6 nfs rw,suid,bg 0 0 +#lapphp0.in2p3.fr:/usr/lib/Motif1.2_R6 /usr/lib/Motif1.2_R6 nfs rw,suid,bg 0 0 + +# rondelles lapphp8 : produits logiciels a deplacer sur lapphp0 +# pour eviter les NFS croises +lapphp8.in2p3.fr:/lapphp8/mupad /lapphp8/mupad nfs rw,suid,bg 0 0 +lapphp8.in2p3.fr:/lapphp8/maple /lapphp8/maple nfs rw,suid,bg 0 0 + +# lappa0 +lappa0:/COMMUN /COMMUN nfs rw,suid,bg 0 0 +lappa0:/virgoa1_2 /nfs/virgoa1_2 nfs rw,suid,bg 0 0 +/dev/vg00/securite /outils/securite hfs rw,suid 0 2 diff --git a/kdf/unix_outputs/unix-defines.txt b/kdf/unix_outputs/unix-defines.txt new file mode 100644 index 0000000..75a2846 --- /dev/null +++ b/kdf/unix_outputs/unix-defines.txt @@ -0,0 +1,125 @@ +What about using builtin symbols defined by the compiler (gcc) +itself. For example on Alpha I have : + +lappa{bussat}(74) echo 'main(){printf("hello world\n";}' |gcc -E -v - +Reading specs from /usr/local/lib/gcc-lib/alpha-dec-osf4.0/2.7.2.3/specs +gcc version 2.7.2.3 + /usr/local/lib/gcc-lib/alpha-dec-osf4.0/2.7.2.3/cpp -lang-c -v -undef +-D__GNUC__=2 -D__GNUC_MINOR__=7 -Dunix -D__osf__ -D__alpha -D__alpha__ +-D_LONGLONG -DSYSTYPE_BSD -D_SYSTYPE_BSD -D__unix__ -D__osf__ -D__alpha +-D__alpha__ -D_LONGLONG -D__SYSTYPE_BSD__ -D_SYSTYPE_BSD -D__unix +-D__SYSTYPE_BSD -Asystem(unix) -Asystem(xpg4) -Acpu(alpha) +-Amachine(alpha) -D__LANGUAGE_C__ -D__LANGUAGE_C -DLANGUAGE_C - +GNU CPP version 2.7.2.3 +#include "..." search starts here: +#include <...> search starts here: + /usr/local/include + /usr/local/alpha-dec-osf4.0/include + /usr/local/lib/gcc-lib/alpha-dec-osf4.0/2.7.2.3/include + /usr/include +End of search list. +# 1 "" +main(){printf("hello world\n";} + +On HP, this becomes : +bussat [21] echo 'main(){printf("hello world\n";}' |gcc -E -v - +Reading specs from +/opt/gcc/lib/gcc-lib/hppa1.1-hp-hpux10.10/2.7.2.2/specs +gcc version 2.7.2.2 + /opt/gcc/lib/gcc-lib/hppa1.1-hp-hpux10.10/2.7.2.2/cpp -lang-c -v -undef +-D__GNUC__=2 -D__GNUC_MINOR__=7 -Dhppa -Dhp9000s800 -D__hp9000s800 +-Dhp9k8 -DPWB -Dhpux -Dunix -D_HPUX_SOURCE -D__hppa__ -D__hp9000s800__ +-D__hp9000s800 -D__hp9k8__ -D__PWB__ -D__hpux__ -D__unix__ +-D_HPUX_SOURCE -D__hppa -D__hp9000s800 -D__hp9k8 -D__PWB -D__hpux +-D__unix -Asystem(unix) -Asystem(hpux) -Acpu(hppa) -Amachine(hppa) +-D__hp9000s700 -D_PA_RISC1_1 - +GNU CPP version 2.7.2.2 (hppa) +#include "..." search starts here: +#include <...> search starts here: + /opt/gcc/include + /opt/gcc/hppa1.1-hp-hpux10.10/include + /opt/gcc/lib/gcc-lib/hppa1.1-hp-hpux10.10/2.7.2.2/include + /usr/include +End of search list. +# 1 "" +main(){printf("hello world +";} + +On Sun Solaris2.5 I found +lappsun8{bussat}[1]: echo 'main(){printf("hello world\n";}' |gcc -E -v - +Reading specs from +/opt/FSFgcc/lib/gcc-lib/sparc-sun-solaris2.5/2.7.2/specs +gcc version 2.7.2 + /opt/FSFgcc/lib/gcc-lib/sparc-sun-solaris2.5/2.7.2/cpp -lang-c -v +-undef -D__GNUC__=2 -D__GNUC_MINOR__=7 -Dsun -Dsparc -Dunix -D__svr4__ +-D__SVR4 -D__GCC_NEW_VARARGS__ -D__sun__ -D__sparc__ -D__unix__ +-D__svr4__ -D__SVR4 -D__GCC_NEW_VARARGS__ -D__sun -D__sparc -D__unix +-Asystem(unix) -Asystem(svr4) -Acpu(sparc) -Amachine(sparc) - +GNU CPP version 2.7.2 (sparc) +#include "..." search starts here: +#include <...> search starts here: + /usr/local/include + /opt/FSFgcc/sparc-sun-solaris2.5/include + /opt/FSFgcc/lib/gcc-lib/sparc-sun-solaris2.5/2.7.2/include + /usr/include +End of search list. +# 1 "" +main(){printf("hello world +";} + +Finally, on Sun with SunOS4.1 the results are : +lappsun1{bussat}[1]: echo 'main(){printf("hello world\n";}' |gcc -E -v +- +Reading specs from +/usr/local/lib/gcc-lib/sparc-sun-sunos4.1.3_U1/2.6.0/specs +gcc version 2.6.0 + /usr/local/lib/gcc-lib/sparc-sun-sunos4.1.3_U1/2.6.0/cpp -lang-c -v +-undef -D__GNUC__=2 -D__GNUC_MINOR__=6 -Dsparc -Dsun -Dunix +-D__GCC_NEW_VARARGS__ -D__sparc__ -D__sun__ -D__unix__ +-D__GCC_NEW_VARARGS__ -D__sparc -D__sun -D__unix -Asystem(unix) +-Asystem(bsd) -Acpu(sparc) -Amachine(sparc) - +GNU CPP version 2.6.0 (sparc) +#include "..." search starts here: +#include <...> search starts here: + /usr/local/include + /usr/local/sparc-sun-sunos4.1.3_U1/include + /usr/local/lib/gcc-lib/sparc-sun-sunos4.1.3_U1/2.6.0/include + /usr/include +End of search list. +# 1 "" +main(){printf("hello world +";} + +on a Linux box there is: +mike@kermit:/home/mike > echo 'main(){printf("hello world\n";}' |gcc -E -v - +Reading specs from /usr/lib/gcc-lib/i486-linux/2.7.2.1/specs +gcc version 2.7.2.1 + /usr/lib/gcc-lib/i486-linux/2.7.2.1/cpp -lang-c -v -undef -D__GNUC__=2 +-D__GNUC_MINOR__=7 -D__ELF__ -Dunix -Di386 -Dlinux -D__ELF__ -D__unix__ +-D__i386__ -D__linux__ -D__unix -D__i386 -D__linux -Asystem(unix) +-Asystem(posix) -Acpu(i386) -Amachine(i386) -D__i486__ - GNU CPP version +2.7.2.1 (i386 Linux/ELF) #include "..." search starts here: #include <...> +search starts here: /usr/local/include + /usr/i486-linux/include + /usr/lib/gcc-lib/i486-linux/2.7.2.1/include + /usr/include +End of search list. +# 1 "" +main(){printf("hello world\n";} + +on digital UNIX V3.2D-1 there is +mkropfbe@edusrv(1)$ echo 'main(){printf("hello world\n";}' |gcc -E -v - +Reading specs from /usr/local/lib/gcc-lib/alpha-dec-osf3.2/2.7.2/specs +gcc version 2.7.2 + /usr/local/lib/gcc-lib/alpha-dec-osf3.2/2.7.2/cpp -lang-c -v -undef +-D__GNUC__=2 -D__GNUC_MINOR__=7 -Dunix -D__osf__ -D__alpha -D__alpha__ +-D_LONGLONG -DSYSTYPE_BSD -D_SYSTYPE_BSD -D__unix__ -D__osf__ -D__alpha +-D__alpha__ -D_LONGLONG -D__SYSTYPE_BSD__ -D_SYSTYPE_BSD -D__unix +-D__SYSTYPE_BSD -Asystem(unix) -Asystem(xpg4) -Acpu(alpha) -Amachine(alpha) +-D__LANGUAGE_C__ -D__LANGUAGE_C -DLANGUAGE_C - GNU CPP version 2.7.2 #include +"..." search starts here: #include <...> search starts here: +/usr/local/include /usr/local/alpha-dec-osf3.2/include +/usr/local/lib/gcc-lib/alpha-dec-osf3.2/2.7.2/include /usr/include +End of search list. +# 1 "" +main(){printf("hello world\n";} diff --git a/kedit/ChangeLog b/kedit/ChangeLog new file mode 100644 index 0000000..92be832 --- /dev/null +++ b/kedit/ChangeLog @@ -0,0 +1,113 @@ +2000-02-14 Kurt Granroth + + * Converted UI to use XML merging instead of manual creation of + menus and toolbars + + +2000-01-29 Charles Samuels + + * Bug fixes + * KAboutData stuff + +1999-10-16 Harri Porten + + * made kedit Unicode clean (patch provided by Ming-Che Chuang + ) + +1999-05-23 Dirk A. Mueller + + * kedit.cpp: Switched to the Qt 2.0 DnD classes. You can drop + QUrlDrag on the Toplevelwidget, and QUrlDrag+QTextDrag on the + QMultiLineWidget. + +1999-02-11 Harri Porten + + * kedit.cpp: removed accelerator char & from tooltips. + * bug#87: attach all QMessageBoxes to their corresponding + dialog widget instead of 'this', ie. KEdit. This makes them always + stay on top and prevents screwed textcolors (reported and + solution provided by Alex Hayward ) + +1999-02-08 Harri Porten + + * kedit.cpp: quote filename for printing + * keditcl1.cpp: translate "Untitled" to trigger "Save As..." + dialog when saving. + +1998-10-12 Harri Porten + + * added an option to turn on/off saving of backup copies + +Thu Jun 25 19:12:44 MEST 1998 Matthias Ettrich + + * Word wrap fixed + +Fri Jan 9 18:04:16 MET 1998 Stefan Taferner + + * Added standard accelerator keys + +Sat Dec 6 03:17:49 1997 Bernd Johannes Wuebben + + * Finally implemented word wrap correctly. Should work fine now + under both auto-indent-mode and normal-mode. I expect the + implementation + to still have a little quirk here and there, but in general it should + work now. It was quite a bit of work for only a few lines of code. + Something is still amiss with the Qt mline widget -- it gave me lots + of problems and most of the implemntation turned out to be an ugly + trial and error procedure. + + * keditcl1.cpp: implemented control-k control-y emacs like kill buffer + threw out KEdit.cpp KEdit.h and introduced keditcl.h keditcl1.cpp + keditcl2.cpp + +Fri Oct 24 01:19:54 1997 Bernd Johannes Wuebben + + * kedit.cpp: lots of clean ups and fixes that were necessary because + of Qt 1.31. I replaced at message and query dialogs with the new + warning and information dialogs. + +Thu Sep 25 22:37:22 1997 Bernd Johannes Wuebben + + * non-modal search and replace dialogs + * centered about, search and replace dialogs + * bug fixes + +Sat Aug 30 23:27:51 1997 Teilnehmer 8 + + * added Klocale support + +Mon Aug 4 19:23:59 1997 Bernd Johannes Wuebben + + * Better about box with logo ( code from kreversi ) + +Sat Aug 2 22:55:53 1997 Bernd Johannes Wuebben + + * KEdit.cpp: various fixes + * kedit.cpp fixed the 'malformed URL' bug that popped up + since KURL had changed its behavior + +Thu Jul 24 20:13:53 1997 Bernd Johannes Wuebben + + * kedit.cpp: made kedit work with the new libs + +Mon Jul 21 22:43:07 1997 Bernd Johannes Wuebben + + * kedit.cpp: implemented mailing + +Sun Jul 20 16:59:27 1997 Bernd Johannes Wuebben + + * KEdit.cpp: Fixed permissions bug + Change line and column numbering to start at 1 + instead of 0 + +Mon Jun 16 18:33:56 1997 Bernd Johannes Wuebben + + * kedit.cpp: files dropped onto kedit are now opened with read and + write permissions. + +Thu May 22 15:02:23 1997 Bernd Johannes Wuebben + + * KEdit.cpp: the file open dialogs will now remember the last + directory visited. + diff --git a/kedit/KEdit.desktop b/kedit/KEdit.desktop new file mode 100644 index 0000000..f4e3abc --- /dev/null +++ b/kedit/KEdit.desktop @@ -0,0 +1,82 @@ +[Desktop Entry] +MimeType=text/plain; +GenericName=Simple Text Editor +GenericName[ar]=محرر نصوص بسيط +GenericName[bg]=Текстов редактор +GenericName[bs]=Jednostavni tekst editor +GenericName[ca]=Editor de text +GenericName[cs]=Jednoduchý textový editor +GenericName[cy]=Golygydd Testun Syml +GenericName[da]=Simpel teksteditor +GenericName[de]=Einfacher Texteditor +GenericName[el]=Απλός επεξεργαστής κειμένου +GenericName[eo]=Simpla Tekstredaktilo +GenericName[es]=Editor de texto sencillo +GenericName[et]=Lihtne tekstiredaktor +GenericName[eu]=Testu Editore Soila +GenericName[fa]=ویرایشگر سادۀ متن +GenericName[fi]=Tekstieditori +GenericName[fr]=Éditeur de texte élémentaire +GenericName[ga]=Eagarthóir Téacs Simplí +GenericName[he]=עורך טקסט פשוט +GenericName[hi]=सादा पाठ संपादक +GenericName[hu]=Egyszerű szövegszerkesztő +GenericName[is]=Einfaldur textaritill +GenericName[it]=Semplice editor di testi +GenericName[ja]=シンプルなテキストエディタ +GenericName[ka]=მარტივი ტექსტის რედაქტორი +GenericName[kk]=Қарапайым мәтін редакторы +GenericName[km]=កម្មវិធី​និពន្ធ​អត្ថបទ +GenericName[lt]=Paprastas teksto redaktorius +GenericName[mk]=Едноставен уредувач на текст +GenericName[ms]=Penyunting Teks Ringkas +GenericName[nb]=Enkelt skriveprogram +GenericName[nds]=Eenfach Texteditor +GenericName[ne]=सामान्य पाठ सम्पादक +GenericName[nl]=Eenvoudige teksteditor +GenericName[nn]=Enkelt skriveprogram +GenericName[pa]=ਸਧਾਰਨ ਪਾਠ ਸੰਪਾਦਕ +GenericName[pl]=Prosty edytor tekstu +GenericName[pt]=Editor de Texto Simples +GenericName[pt_BR]=Editor de Texto Simples +GenericName[ro]=Editor simplu de text +GenericName[ru]=Простой текстовый редактор +GenericName[sk]=Jednoduchý textový editor +GenericName[sl]=Preprost urejevalnik besedil +GenericName[sr]=Једноставни уређивач текста +GenericName[sr@Latn]=Jednostavni uređivač teksta +GenericName[sv]=Enkel texteditor +GenericName[ta]=சுலப உரை தொகுப்பான் +GenericName[tg]=Муҳаррири Оддии Матн +GenericName[tr]=Basit Metin Düzenleyici +GenericName[uk]=Простий редактор текстів +GenericName[uz]=Oddiy matn tahrirchi +GenericName[uz@cyrillic]=Оддий матн таҳрирчи +GenericName[wa]=Simpe aspougneu di tecse +GenericName[zh_CN]=简单文本编辑器 +GenericName[zh_TW]=簡單的文字編輯器 +Exec=kedit -caption "%c" %i %m %u +Icon=kedit +Path= +DocPath=kedit/index.html +Type=Application +Terminal=false +Name=KEdit +Name[af]=Kredigeer +Name[eo]=Redaktilo +Name[hi]=के-एडिट +Name[hr]=Uređivač +Name[lv]=KRediģēt +Name[ne]=केडीई सम्पादन +Name[pa]=ਕਸੰਪਦਾਕ +Name[pl]=Edytor +Name[sv]=Kedit +Name[ta]=கேதொகுப்பு +Name[tg]=KТаҳрир +Name[th]=แก้ไขข้อความ +Name[ven]=U sengulusa ha K +Name[xh]=Abahleli Be K +Name[zh_TW]=KDE 編輯器 +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;TextEditor; diff --git a/kedit/Makefile.am b/kedit/Makefile.am new file mode 100644 index 0000000..6870eb6 --- /dev/null +++ b/kedit/Makefile.am @@ -0,0 +1,35 @@ +# +# KEdit Makefile.am +# +# Copyright 1997 Bernd Johannes Wuebben, wuebben@math.cornell.edu +# +# + +INCLUDES = $(all_includes) + +bin_PROGRAMS = +lib_LTLIBRARIES = +kdeinit_LTLIBRARIES = kedit.la + +kedit_la_SOURCES = kedit.cpp ktextfiledlg.cpp misc.ui color.ui prefs.kcfgc +kedit_la_LIBADD = -lkdeprint $(LIB_KFILE) +kedit_la_LDFLAGS = -module -avoid-version $(KDE_PLUGIN) $(all_libraries) + +noinst_HEADERS = kedit.h ktextfiledlg.h\ + version.h misc.ui.h + +METASOURCES = AUTO + +SUBDIRS = pixmaps + +xdg_apps_DATA = KEdit.desktop +kde_kcfg_DATA = kedit.kcfg + +EXTRA_DIST = $(xdg_apps_DATA) + +rcdir = $(kde_datadir)/kedit +rc_DATA = keditui.rc + +messages: rc.cpp + $(XGETTEXT) rc.cpp *.cpp -o $(podir)/kedit.pot + diff --git a/kedit/README b/kedit/README new file mode 100644 index 0000000..909e9e5 --- /dev/null +++ b/kedit/README @@ -0,0 +1,192 @@ +kedit 0.7 +========= + +Fixed up word wrap in auto-indent and normal mode and implemented emacs +still ctrl-k ctrl-y kill-ring. KEdit should be quite usable now. + +kedit 0.5 +========= + +This is release 0.5 of KEdit. + +There are quite a number internal as external changes. The biggest +problem were a number of bugs that the underlying QMultiLineWidget +exhibits in Qt 1.2. For anything I started, be it find, replace, +word-wrap, indent-mode, loading, saving, I hit upon bugs in the +multiline widget and had to find work-arounds. This is the main +reason, why this new release took so long. However, the Trolls were +very responsive to my bug reports and helped me in finding work +arounds. The next release of qt, qt 1.3 should have a much better +multiline widget. Thanks, Trolls! + +One of the consequences of this is that find, find/replace, word-warp +and indent mode don't "feel right". They, as you will notice feel slow +and sluggish. We have to wait for qt 1.3 for this to improve. However +Qt 1.3 might well break some of the work arounds in place now, but I +will make a good effort to bring out a new version of kedit as soon as +qt 1.3 appears. + +I made so many changes, that I wouldn't be surprise if I broke some +basic functionality. Please test kedit and let me know immediately if +you think you found a bug. I will fix the problem as soon as +possible. + +Note: You need smgl-tools 0.99 if you want to regenerate the provided + documentation in ps, html, dvi format for the sgml source. + +Changes: + o adopted new kde look + o found workaround for faster loading and saving. + o find dialog working properly + o find/replace dialog working properly + o Indent Mode + o Goto Line + o Fill Column + o Word Wrap + o Documentation is now provided in sgml, ps, dvi, and html + o Rewrote the underlying kedit widget, so that it can now be used in + other applications such as kmail. + o rewrites, rewrites, rewrites .... still there is more + historical baggage left to get rid of.... + +TODO: + + o recently opened files list + o remember last directory the user opened a file in. + o Paragraph formatting + o Spell Checking (maybe) + o Option to turn backup file creation off. + o better support for net-files. + +Problems: + + o Help will only work with the next release of kdelibs. Alternatively + you can copy a copy of kedit.html, kedit.gif into + $(KDEDIR)/docs/HTML + + o kedit has currently problems to deal with color-scheme changes + without restarting kedit. I have made the necessary changes to + libkdecore to deal with this problem. You will however have to wait + for the next kdelibs release. At that time I will also bring out + a new version of kedit that will take advantage of those changes. + + +There is still lots to be done, but I hope you will find kedit a useful +little editor already. + +Best Regards, +Bernd + +wuebben@kde.org +wuebben@math.cornell.edu + +kedit+ 0.4.1 +============ + +Solved the "tab" problem. kedit+ is now Makefile proof. :-) + +kedit+ 0.4 +========== + +A few last minute changes to kedit+ 0.2 introduced an embarrassing bug, +which didn't let you "save as" an "Untitled" document. I fixed that +bug, and while I was at it I added colors to the Options dialog. +Now you can also set the fore- and background colors of kedit+. +Martin Konold suggested I bump the version number to something larger +than 0.3.1 which was the last release of kedit. + +Hope you will find this editor useful. + +I STILL NEED AN OPEN-FOLDER ICON !!!! PLEAE HELP :-) + +Best Regards, Bernd + +wuebben@kde.org +wuebben@math.cornell.edu + +kedit+ 0.2 +========== + +This is kedit+ a simple text editor for the KDE project. I have taken +Alex Sanda's kedit and turned it into what I believe to be +a useful little editor. I had to rewrite many parts of the original +kedit and added, as you will surely notice, many new features. +Nevertheless, it is still no emacs and will never be one ;-) + +I have tried to contact Alex, but haven't heard back from him. +Should kedit+ become kedit? kedit has not been developed for +about 4 month .... + + +HELP WANTED: I need an open-folder icon !!! + +I hope you like kedit+, the next Generation :-) + + +Bernd Wuebben +wuebben@kde.org +wuebben@math.cornell.edu + + +======================================================================== + + Kedit 0.3.1, small editor for the KDE project. + + +Kedit is a small, simple and almost featureless :) editor, just like +the well-known Notepad. It is suitable only for small editing tasks, or +as a simple textfile browser. + +Currently, kedit is in a very early development stage. It can load, +save/saveas files, and - of course - it can edit those files :) There is +some room for improvements, but I really want this editor to be small and +simple. + +Kedit can open multiple windows (so you can edit multiple files), without +having multiple copies of the whole program in memory. + + + +Changes +======= + +Version 0.3.1 (Martin Hartig, hartig@mathematik.uni-kl.de, 21.2.97) + +- usage of the kdehelp browser, HTML help text added + +Version 0.3 (Torben Weiss, weiss@kde.org, 4.2.97 ) + +- Drag and Drop added + +- Added network access. Can load any file kfm can. To use this feature you + must run kfm. If none is running kedit will start one on demand. + +- Can save files everywhere kfm can, this means right now that you can + write to ftp servers. + +- Using libkdecore and libkfm. This means you need libkde-0.61 and + kfm-0.51 or greater installed + +- Fixed some bugs + +- Works with any amount of windows now + +- Changed some key bindings, but not all + +- You can call + make + make install + + +TODO: + Implement search again (and maybe replace), including regexp + support. At the moment, only the search dialog has been implemented. + + Clean up some stuff, make it more user-friendly(tm). + + Keybindings: I'am sure, they are currently not kde-conform. + + Use (a not existing) KFileDialog that lets you enter URLs + + + Bernd diff --git a/kedit/TODO b/kedit/TODO new file mode 100644 index 0000000..b386630 --- /dev/null +++ b/kedit/TODO @@ -0,0 +1,6 @@ +o clean up what happens if you interrupt an ftp file load +o file_save_url need an error dialog +o save indent mode option +o key accel for end of document beginning of document +o Paragraph formatting + diff --git a/kedit/color.ui b/kedit/color.ui new file mode 100644 index 0000000..e171491 --- /dev/null +++ b/kedit/color.ui @@ -0,0 +1,129 @@ + +Color + + + Color + + + + 0 + 0 + 365 + 196 + + + + + unnamed + + + 0 + + + + spacer1 + + + Vertical + + + Expanding + + + + 41 + 111 + + + + + + kcfg_TextColor + + + false + + + + + + + + kcfg_BackgroundColor + + + false + + + + + + + + kcfg_CustomColor + + + Use &custom colors + + + + + textLabel1 + + + false + + + &Foreground color: + + + kcfg_TextColor + + + + + textLabel2 + + + false + + + &Background color: + + + kcfg_BackgroundColor + + + + + + + kcfg_CustomColor + toggled(bool) + textLabel1 + setEnabled(bool) + + + kcfg_CustomColor + toggled(bool) + textLabel2 + setEnabled(bool) + + + kcfg_CustomColor + toggled(bool) + kcfg_TextColor + setEnabled(bool) + + + kcfg_CustomColor + toggled(bool) + kcfg_BackgroundColor + setEnabled(bool) + + + + + kcolorbutton.h + + diff --git a/kedit/kedit.cpp b/kedit/kedit.cpp new file mode 100644 index 0000000..a255cd9 --- /dev/null +++ b/kedit/kedit.cpp @@ -0,0 +1,1377 @@ + /* + + $Id$ + + Copyright (C) 1997 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ktextfiledlg.h" +#include "kedit.h" +#include "misc.h" +#include "color.h" +#include "prefs.h" + +#include + + +QPtrList *TopLevel::windowList = 0; + +int default_open = TopLevel::OPEN_READWRITE; + +TopLevel::TopLevel (QWidget *, const char *name) + : KMainWindow ( 0,name ), kspellconfigOptions(0), + eframe(0), newWindow(false), kspell(0) +{ + if (!windowList) + { + windowList = new QPtrList; + windowList->setAutoDelete( FALSE ); + } + windowList->append( this ); + + statusbar_timer = new QTimer(this); + connect(statusbar_timer, SIGNAL(timeout()),this,SLOT(timer_slot())); + + connect(kapp,SIGNAL(kdisplayPaletteChanged()),this,SLOT(set_colors())); + + setupStatusBar(); + setupActions(); + + readSettings(); + + setupEditWidget(); + + if (!initialGeometrySet()) + resize( QSize(550, 400).expandedTo(minimumSizeHint())); + setupGUI(ToolBar | Keys | StatusBar | Create); + setAutoSaveSettings(); + + setAcceptDrops(true); + + setFileCaption(); +} + + +TopLevel::~TopLevel () +{ + windowList->remove( this ); +} + + +void TopLevel::setupEditWidget() +{ + if (!eframe) + { + eframe = new KEdit (this, "eframe"); + eframe->setOverwriteEnabled(true); + + connect(eframe, SIGNAL(CursorPositionChanged()),this, + SLOT(statusbar_slot())); + connect(eframe, SIGNAL(toggle_overwrite_signal()),this, + SLOT(toggle_overwrite())); + connect(eframe, SIGNAL(gotUrlDrop(QDropEvent*)), this, + SLOT(urlDrop_slot(QDropEvent*))); + connect(eframe, SIGNAL(undoAvailable(bool)),undoAction, + SLOT(setEnabled(bool))); + connect(eframe, SIGNAL(redoAvailable(bool)),redoAction, + SLOT(setEnabled(bool))); + connect(eframe, SIGNAL(copyAvailable(bool)),cutAction, + SLOT(setEnabled(bool))); + connect(eframe, SIGNAL(copyAvailable(bool)),copyAction, + SLOT(setEnabled(bool))); + connect( eframe, SIGNAL(selectionChanged()),this, + SLOT(slotSelectionChanged())); + connect( eframe, SIGNAL(modificationChanged( bool)), + SLOT(setFileCaption())); + + undoAction->setEnabled(false); + redoAction->setEnabled(false); + cutAction->setEnabled(false); + copyAction->setEnabled(false); + + setCentralWidget(eframe); + eframe->setMinimumSize(200, 100); + } + + if( Prefs::wrapMode() == Prefs::EnumWrapMode::FixedColumnWrap ) + { + eframe->setWordWrap(QMultiLineEdit::FixedColumnWidth); + eframe->setWrapColumnOrWidth(Prefs::wrapColumn()); + } + else if( Prefs::wrapMode() == Prefs::EnumWrapMode::SoftWrap ) + { + eframe->setWordWrap(QMultiLineEdit::WidgetWidth); + } + else + { + eframe->setWordWrap(QMultiLineEdit::NoWrap); + } + + eframe->setFont( Prefs::font() ); + int w = eframe->fontMetrics().width("M"); + eframe->setTabStopWidth(8*w); + + eframe->setModified(false); + + setSensitivity(); + + eframe->setFocus(); + + set_colors(); + + /* + right_mouse_button = new QPopupMenu; + + right_mouse_button->insertItem (i18n("Open..."), + this, SLOT(file_open())); + right_mouse_button->insertItem (SmallIcon("filesave"),i18n("Save"), + this, SLOT(file_save())); + right_mouse_button->insertItem (SmallIcon("filesaveas"),i18n("Save As..."), + this, SLOT(file_save_as())); + right_mouse_button->insertSeparator(-1); + right_mouse_button->insertItem(i18n("Copy"), + this, SLOT(copy())); + right_mouse_button->insertItem(i18n("Paste"), + this, SLOT(paste())); + right_mouse_button->insertItem(i18n("Cut"), + this, SLOT(cut())); + right_mouse_button->insertItem(i18n("Select All"), + this, SLOT(select_all())); + eframe->installRBPopup(right_mouse_button); + */ +} + + +void TopLevel::slotSelectionChanged() +{ + bool state = eframe->hasSelectedText(); + cutAction->setEnabled( state ); + copyAction->setEnabled( state ); +} + + +void TopLevel::setupActions() +{ + // setup File menu + KStdAction::openNew(this, SLOT(file_new()), actionCollection()); + KStdAction::open(this, SLOT(file_open()), actionCollection()); + recent = KStdAction::openRecent(this, SLOT(openRecent(const KURL&)), + actionCollection()); + KStdAction::save(this, SLOT(file_save()), actionCollection()); + KStdAction::saveAs(this, SLOT(file_save_as()), actionCollection()); + KStdAction::close(this, SLOT(file_close()), actionCollection()); + KStdAction::print(this, SLOT(print()), actionCollection()); + KStdAction::mail(this, SLOT(mail()), actionCollection()); + KStdAction::quit(this, SLOT(close()), actionCollection()); + + // setup edit menu + undoAction = KStdAction::undo(this, SLOT(undo()), actionCollection()); + redoAction = KStdAction::redo(this, SLOT(redo()), actionCollection()); + cutAction = KStdAction::cut(this, SLOT(cut()), actionCollection()); + copyAction = KStdAction::copy(this, SLOT(copy()), actionCollection()); + KStdAction::pasteText(this, SLOT(paste()), actionCollection()); + KStdAction::selectAll(this, SLOT(select_all()), actionCollection()); + KStdAction::find(this, SLOT(search()), actionCollection()); + KStdAction::findNext(this, SLOT(search_again()), actionCollection()); + KStdAction::replace(this, SLOT(replace()), actionCollection()); + + (void)new KAction(i18n("&Insert File..."), 0, this, SLOT(file_insert()), + actionCollection(), "insert_file"); + (void)new KAction(i18n("In&sert Date"), 0, this, SLOT(insertDate()), + actionCollection(), "insert_date"); + (void)new KAction(i18n("Cl&ean Spaces"), 0, this, SLOT(clean_space()), + actionCollection(), "clean_spaces"); + + // setup Tools menu + KStdAction::spelling(this, SLOT(spellcheck()), actionCollection()); + + // setup Go menu + KStdAction::gotoLine(this, SLOT(gotoLine()), actionCollection()); + + KStdAction::preferences(this, SLOT(showSettings()), actionCollection()); +} + +void TopLevel::setupStatusBar() +{ + statusBar()->insertItem("", ID_GENERAL, 10 ); + statusBar()->insertFixedItem( i18n("OVR"), ID_INS_OVR ); + statusBar()->insertFixedItem( i18n("Line:000000 Col: 000"), ID_LINE_COLUMN ); + + statusBar()->setItemAlignment( ID_GENERAL, AlignLeft|AlignVCenter ); + statusBar()->setItemAlignment( ID_LINE_COLUMN, AlignLeft|AlignVCenter ); + statusBar()->setItemAlignment( ID_INS_OVR, AlignLeft|AlignVCenter ); + + statusBar()->changeItem( i18n("Line: 1 Col: 1"), ID_LINE_COLUMN ); + statusBar()->changeItem( i18n("INS"), ID_INS_OVR ); +} + + +void TopLevel::saveProperties(KConfig* config) +{ + if(m_url.isEmpty() && !eframe->isModified()) + return; + + config->writeEntry("url",m_url.url()); + config->writeEntry("modified",eframe->isModified()); + + int line, col; + eframe->getCursorPosition(&line, &col); + config->writeEntry("current_line", line); + config->writeEntry("current_column", col); + + if(eframe->isModified()) + { + QString name = m_url.url(); + if (name.isEmpty()) + name = QString("kedit%1-%2").arg(getpid()).arg((long)this); + QString tmplocation = kapp->tempSaveName(m_url.url()); + config->writeEntry("saved_to",tmplocation); + saveFile(tmplocation, false, m_url.fileEncoding()); + } +} + + +void TopLevel::readProperties(KConfig* config){ + KURL url = config->readPathEntry("url"); + QString filename = config->readPathEntry("saved_to"); + + QString encoding = url.fileEncoding(); + int modified = config->readNumEntry("modified",0); + int line = config->readNumEntry("current_line", 0); + int col = config->readNumEntry("current_column", 0); + int result = KEDIT_RETRY; + + if(!filename.isEmpty()) + { + if (modified) + { + result = openFile(filename, OPEN_READWRITE, url.fileEncoding()); + } + else + { + result = openFile(filename, OPEN_READWRITE, url.fileEncoding()); + } + } + else + { + openURL(url, OPEN_READWRITE); + modified = false; + result = KEDIT_OK; + } + + if (result == KEDIT_OK) + { + m_url = url; + eframe->setModified(modified); + eframe->setCursorPosition(line, col); + setFileCaption(); + statusbar_slot(); + } +} + + +void TopLevel::undo() +{ + eframe->undo(); +} + + +void TopLevel::redo() +{ + eframe->redo(); +} + + +void TopLevel::copy() +{ + eframe->copy(); +} + + +void TopLevel::select_all() +{ + eframe->selectAll(); +} + + +void TopLevel::insertDate(){ + + int line, column; + + QString string; + QDate dt = QDate::currentDate(); + string = KGlobal::locale()->formatDate(dt); + + eframe->getCursorPosition(&line,&column); + eframe->insertAt(string,line,column); + eframe->setModified(TRUE); + + statusbar_slot(); +} + +void TopLevel::paste(){ + + eframe->paste(); + eframe->setModified(TRUE); + + statusbar_slot(); +} + + +void TopLevel::cut(){ + + eframe->cut(); + eframe->setModified(TRUE); + statusbar_slot(); + +} + + +void TopLevel::file_new() +{ + TopLevel *t = new TopLevel (); + t->show(); + return; +} + +void TopLevel::clean_space() +{ + eframe->cleanWhiteSpace(); +} + +void TopLevel::spellcheck() +{ + if (!eframe) return; + + if (kspell) return; // In progress + + statusBar()->changeItem(i18n("Spellcheck: Started."), ID_GENERAL); + + initSpellConfig(); + kspell = new KSpell(this, i18n("Spellcheck"), this, + SLOT( spell_started(KSpell *)), kspellconfigOptions); + + connect (kspell, SIGNAL ( death()), + this, SLOT ( spell_finished( ))); + + connect (kspell, SIGNAL (progress (unsigned int)), + this, SLOT (spell_progress (unsigned int))); + connect (kspell, SIGNAL (misspelling (const QString &, const QStringList &, unsigned int)), + eframe, SLOT (misspelling (const QString &, const QStringList &, unsigned int))); + connect (kspell, SIGNAL (corrected (const QString &, const QString &, unsigned int)), + eframe, SLOT (corrected (const QString &, const QString &, unsigned int))); + connect (kspell, SIGNAL (done(const QString&)), + this, SLOT (spell_done(const QString&))); +} + + +void TopLevel::spell_started( KSpell *) +{ + eframe->spellcheck_start(); + kspell->setProgressResolution(2); + kspell->check(eframe->text()); +} + + +void TopLevel::spell_progress (unsigned int percent) +{ + QString s; + s = i18n("Spellcheck: %1% complete").arg(percent); + + statusBar()->changeItem (s, ID_GENERAL); +} + + +void TopLevel::spell_done(const QString& newtext) +{ + eframe->spellcheck_stop(); + if (kspell->dlgResult() == 0) + { + eframe->setText( newtext); + statusBar()->changeItem (i18n("Spellcheck: Aborted."), ID_GENERAL); + } + else + { + statusBar()->changeItem (i18n("Spellcheck: Complete."), ID_GENERAL); + } + kspell->cleanUp(); +} + +// Replace ISpell with the name of the actual spell checker. +// TODO: Use %1 in the original string instead when string freeze is over. +QString TopLevel::replaceISpell(QString msg, int client) +{ + switch(client) + { + case KS_CLIENT_ISPELL: msg.replace("ISpell", "ispell"); break; + case KS_CLIENT_ASPELL: msg.replace("ISpell", "aspell"); break; + case KS_CLIENT_HSPELL: msg.replace("ISpell", "hspell"); break; + } + msg.replace("\n", "

"); + return ""+msg+""; +} + +void TopLevel::spell_finished( ) +{ + KSpell::spellStatus status = kspell->status(); + int client = kspellconfigOptions->client(); + delete kspell; + kspell = 0; + if (status == KSpell::Error) + { + KMessageBox::sorry(this, replaceISpell(i18n("ISpell could not be started.\n" + "Please make sure you have ISpell properly configured and in your PATH."), client)); + } + else if (status == KSpell::Crashed) + { + eframe->spellcheck_stop(); + statusBar()->changeItem (i18n("Spellcheck: Crashed."), ID_GENERAL); + KMessageBox::sorry(this, replaceISpell(i18n("ISpell seems to have crashed."), client)); + } +} + + +void TopLevel::file_open( void ) +{ + + while( 1 ) + { + KURL url = KTextFileDialog::getOpenURLwithEncoding( + QString::null, QString::null, this, + i18n("Open File")); + if( url.isEmpty() ) + { + return; + } + + KIO::UDSEntry entry; + KIO::NetAccess::stat(url, entry, this); + KFileItem fileInfo(entry, url); + if (fileInfo.size() > 2097152 && // 2MB large/small enough? + KMessageBox::warningContinueCancel(this, + i18n("The file you have requested is larger than KEdit is designed for. " + "Please ensure you have enough system resources available to safely load this file, " + "or consider using a program that is designed to handle large files such as KWrite."), + i18n("Attempting to Open Large File"), + KStdGuiItem::cont(), "attemptingToOpenLargeFile") == KMessageBox::Cancel) + { + return; + } + + TopLevel *toplevel; + if( !m_url.isEmpty() || eframe->isModified() ) + { + toplevel = new TopLevel(); + if( toplevel == 0 ) + { + return; + } + } + else + { + toplevel = this; + } + + QString tmpfile; + KIO::NetAccess::download( url, tmpfile, toplevel ); + + int result = toplevel->openFile( tmpfile, 0, url.fileEncoding()); + KIO::NetAccess::removeTempFile( tmpfile ); + + if( result == KEDIT_OK ) + { + if( toplevel != this ) { toplevel->show(); } + toplevel->m_url = url; + toplevel->setFileCaption(); + recent->addURL( url ); + toplevel->eframe->setModified(false); + toplevel->setGeneralStatusField(i18n("Done")); + toplevel->statusbar_slot(); + break; + } + else if( result == KEDIT_RETRY ) + { + if( toplevel != this ) { delete toplevel; } + } + else + { + if( toplevel != this ) { delete toplevel; } + break; + } + } + +} + +void TopLevel::file_insert() +{ + while( 1 ) + { + KURL url = KTextFileDialog::getOpenURLwithEncoding( + QString::null, QString::null, this, + i18n("Insert File"), "", KStdGuiItem::insert().text()); + if( url.isEmpty() ) + { + return; + } + + QString tmpfile; + KIO::NetAccess::download( url, tmpfile, this ); + int result = openFile( tmpfile, OPEN_INSERT, url.fileEncoding(), true ); + KIO::NetAccess::removeTempFile( tmpfile ); + + if( result == KEDIT_OK ) + { + recent->addURL( url ); + eframe->setModified(true); + setGeneralStatusField(i18n("Done")); + statusbar_slot(); + } + else if( result == KEDIT_RETRY ) + { + continue; + } + return; + } +} + +bool TopLevel::queryExit() +{ + // save recent files menu + config = kapp->config(); + recent->saveEntries( config ); + config->sync(); + + return true; +} + +bool TopLevel::queryClose() +{ + queryExit(); + int result; + + if ( !eframe->isModified() ) + return true; + + QString msg = i18n("" + "This document has been modified.\n" + "Would you like to save it?" ); + switch( KMessageBox::warningYesNoCancel( this, msg, QString::null, + KStdGuiItem::save(), KStdGuiItem::discard() ) ) + { + case KMessageBox::Yes: // Save, then exit + if ( m_url.isEmpty()) + { + file_save_as(); + if ( eframe->isModified() ) + return false; // Still modified? Don't exit! + } + else + { + result = saveURL(m_url); + if ( result == KEDIT_USER_CANCEL ) + return false; // Don't exit. + + if ( result != KEDIT_OK) + { + msg = i18n("" + "Could not save the file.\n" + "Exit anyways?"); + switch( KMessageBox::warningContinueCancel( this, msg, QString::null, KStdGuiItem::quit() ) ) + { + case KMessageBox::Continue: + return true; // Exit. + case KMessageBox::Cancel: + default: + return false; // Don't exit. + } + } + } + + case KMessageBox::No: // Don't save but exit. + return true; + + case KMessageBox::Cancel: // Don't save and don't exit. + default: + return false; // Don't exit... + } + + return true; // Exit. +} + + +void TopLevel::openRecent(const KURL& url) +{ + if (!m_url.isEmpty() || eframe->isModified()) + { + TopLevel *t = new TopLevel (0,0); + t->show(); + t->openRecent(url); + return; + } + openURL( url, OPEN_READWRITE ); +} + + +void TopLevel::file_close() +{ + if( eframe->isModified() ) + { + QString msg = i18n("This document has been modified.\n" + "Would you like to save it?" ); + switch( KMessageBox::warningYesNoCancel( this, msg, QString::null, + KStdGuiItem::save(), KStdGuiItem::discard() ) ) + { + case KMessageBox::Yes: // Save, then close + file_save(); + if (eframe->isModified()) + return; // Error during save. + break; + + case KMessageBox::No: // Don't save but close. + break; + + case KMessageBox::Cancel: // Don't save and don't close. + return; + break; + } + } + eframe->clear(); + eframe->setModified(false); + m_url = KURL(); + setFileCaption(); + statusbar_slot(); +} + + +void TopLevel::file_save() +{ + if (m_url.isEmpty()) + { + file_save_as(); + return; + } + + int result = KEDIT_OK; + + result = saveURL(m_url); // error messages are handled by saveFile + + if ( result == KEDIT_OK ){ + QString string; + string = i18n("Wrote: %1").arg(m_caption); + setGeneralStatusField(string); + } +} + + +void TopLevel::setGeneralStatusField(const QString &text){ + + statusbar_timer->stop(); + + statusBar()->changeItem(text,ID_GENERAL); + statusbar_timer->start(10000,TRUE); // single shot + +} + + +void TopLevel::file_save_as() +{ + KURL u; + while(true) + { + u = KTextFileDialog::getSaveURLwithEncoding( + m_url.url(), QString::null, this, + i18n("Save File As"), + m_url.fileEncoding()); + + if (u.isEmpty()) + return; + + if ( KIO::NetAccess::exists(u, false, this) ) + { + int result = KMessageBox::warningContinueCancel( this, + i18n( "A file named \"%1\" already exists. " + "Are you sure you want to overwrite it?" ).arg( u.prettyURL() ), + i18n( "Overwrite File?" ), + i18n( "Overwrite" ) ); + + if (result != KMessageBox::Continue) + continue; + } + break; + } + + int result = saveURL(u); // error messages are handled by saveFile + + if ( result == KEDIT_OK ) + { + m_url = u; + setFileCaption(); + QString string = i18n("Saved as: %1").arg(m_caption); + setGeneralStatusField(string); + recent->addURL( u ); + } +} + + + +void TopLevel::mail() +{ + // + // Default subject string + // + QString defaultsubject = name(); + int index = defaultsubject.findRev('/'); + if( index != -1) + defaultsubject = defaultsubject.right(defaultsubject.length() - index - 1 ); + + kapp->invokeMailer( QString::null, QString::null, QString::null, + defaultsubject, eframe->text() ); +} + +/* +void TopLevel::fancyprint(){ + + QPrinter prt; + char buf[200]; + if ( prt.setup(0) ) { + + int y =10; + QPainter p; + p.begin( &prt ); + p.setFont( eframe->font() ); + QFontMetrics fm = p.fontMetrics(); + + int numlines = eframe->numLines(); + for(int i = 0; i< numlines; i++){ + y += fm.ascent(); + QString line; + line = eframe->textLine(i); + line.replace( QRegExp("\t"), " " ); + strncpy(buf,line.local8Bit(),160); + for (int j = 0 ; j <150; j++){ + if (!isprint(buf[j])) + buf[j] = ' '; + } + buf[line.length()] = '\0'; + p.drawText( 10, y, buf ); + y += fm.descent(); + } + + p.end(); + } + return ; +} +*/ + +void TopLevel::helpselected(){ + + kapp->invokeHelp( ); + +} + + +void TopLevel::search(){ + + eframe->search(); + statusbar_slot(); +} + +void TopLevel::replace(){ + eframe->replace(); + statusbar_slot(); +} + + + +void TopLevel::showSettings() +{ + if(KConfigDialog::showDialog("settings")) + return; + + initSpellConfig(); + KConfigDialog* dialog = new SettingsDialog(this, "settings", Prefs::self(), kspellconfigOptions); + + connect(dialog, SIGNAL(settingsChanged()), this, SLOT(updateSettings())); + dialog->show(); +} + +void TopLevel::initSpellConfig() +{ + if (!kspellconfigOptions) + kspellconfigOptions = new KSpellConfig(0 , "SpellingSettings", 0, false ); +} + +void TopLevel::search_again() +{ + eframe->repeatSearch(); + statusbar_slot(); +} + +void TopLevel::setFileCaption() +{ + if (m_url.isEmpty()) + { + m_caption = i18n("[New Document]"); + } + else + { + if (m_url.isLocalFile()) + { + if (QDir::currentDirPath() == m_url.directory()) + m_caption = m_url.fileName(); + else + m_caption = m_url.path(); + } + else + { + KURL url(m_url); + url.setQuery(QString::null); + m_caption = url.prettyURL(); + } + QString encoding = m_url.fileEncoding(); + if (!encoding.isEmpty()) + m_caption += QString(" (%1)").arg(encoding); + } + setCaption(m_caption, eframe->isModified()); +} + + +void TopLevel::gotoLine() { + eframe->doGotoLine(); +} + +void TopLevel::statusbar_slot(){ + + QString linenumber; + + linenumber = i18n("Line: %1 Col: %2") + .arg(eframe->currentLine() + 1) + .arg(eframe->currentColumn() +1); + + statusBar()->changeItem(linenumber,ID_LINE_COLUMN); +} + +void TopLevel::print() +{ + bool aborted = false; + QString headerLeft = i18n("Date: %1").arg(KGlobal::locale()->formatDate(QDate::currentDate(),true)); + QString headerMid = i18n("File: %1").arg(m_caption); + QString headerRight; + + QFont printFont = eframe->font(); + QFont headerFont(printFont); + headerFont.setBold(true); + + QFontMetrics printFontMetrics(printFont); + QFontMetrics headerFontMetrics(headerFont); + + KPrinter *printer = new KPrinter; + if(printer->setup(this, i18n("Print %1").arg(m_caption))) { + // set up KPrinter + printer->setFullPage(false); + printer->setCreator("KEdit"); + if ( !m_caption.isEmpty() ) + printer->setDocName(m_caption); + + QPainter *p = new QPainter; + p->begin( printer ); + + QPaintDeviceMetrics metrics( printer ); + + int dy = 0; + + p->setFont(headerFont); + int w = printFontMetrics.width("M"); + p->setTabStops(8*w); + + int page = 1; + int lineCount = 0; + int maxLineCount = eframe->numLines(); + + + while(true) { + headerRight = QString("#%1").arg(page); + dy = headerFontMetrics.lineSpacing(); + QRect body( 0, dy*2, metrics.width(), metrics.height()-dy*2); + + p->drawText(0, 0, metrics.width(), dy, Qt::AlignLeft, headerLeft); + p->drawText(0, 0, metrics.width(), dy, Qt::AlignHCenter, headerMid); + p->drawText(0, 0, metrics.width(), dy, Qt::AlignRight, headerRight); + + QPen pen; + pen.setWidth(3); + p->setPen(pen); + + p->drawLine(0, dy+dy/2, metrics.width(), dy+dy/2); + + int y = dy*2; + while(lineCount < maxLineCount) { + QString text = eframe->textLine(lineCount); + if( text.isEmpty() ) + text = " "; // don't ignore empty lines + QRect r = p->boundingRect(0, y, body.width(), body.height(), + QPainter::ExpandTabs | QPainter::WordBreak, text); + + dy = r.height(); + + if (y+dy > metrics.height()) break; + + p->drawText(0, y, metrics.width(), metrics.height() - y, + QPainter::ExpandTabs | QPainter::WordBreak, text); + + y += dy; + lineCount++; + } + if (lineCount >= maxLineCount) + break; + + printer->newPage(); + page++; + } + + p->end(); + delete p; + } + delete printer; + if (aborted) + setGeneralStatusField(i18n("Printing aborted.")); + else + setGeneralStatusField(i18n("Printing complete.")); +} + + + +void TopLevel::setSensitivity (){ + +} + + +int TopLevel::saveURL( const KURL& _url ) +{ + if ( !_url.isValid() ) + { + KMessageBox::sorry(this, i18n("Malformed URL")); + return KEDIT_RETRY; + } + + // Just a usual file ? + if ( _url.isLocalFile() ) + { + return saveFile( _url.path(), true, _url.fileEncoding() ); + } + + KTempFile tmpFile; + tmpFile.setAutoDelete(true); + eframe->setModified( true ); + saveFile( tmpFile.name(), false, _url.fileEncoding() ); + + if (KIO::NetAccess::upload( tmpFile.name(), _url, this ) == false) + { + KMessageBox::error(this, "Could not save remote file"); + return KEDIT_RETRY; + } + + return true; +} + + +int TopLevel::openFile( const QString& _filename, int _mode, const QString &encoding, bool _undoAction ) +{ + QFileInfo info(_filename); + + if(info.isDir()) + { + KMessageBox::sorry(this, i18n("You have specified a folder")); + return KEDIT_RETRY; + } + + if(!info.exists() || !info.isFile()) + { + if ((_mode & OPEN_NEW) != 0) + return KEDIT_OK; + KMessageBox::sorry(this, i18n("The specified file does not exist")); + return KEDIT_RETRY; + } + + QFile file(_filename); + + if(!file.open(IO_ReadOnly)) + { + KMessageBox::sorry(this, i18n("You do not have read permission to this file.")); + return KEDIT_RETRY; + } + + QTextStream stream(&file); + QTextCodec *codec; + if (!encoding.isEmpty()) + codec = QTextCodec::codecForName(encoding.latin1()); + else + codec = QTextCodec::codecForLocale(); + stream.setCodec(codec); + + if ((_mode & OPEN_INSERT) == 0) + { + eframe->clear(); + } + if ( ! _undoAction ) + eframe->setUndoRedoEnabled(false); + + eframe->insertText( &stream ); + eframe->setModified(false); + + if ( !_undoAction) + eframe->setUndoRedoEnabled(true); + + return KEDIT_OK; + +} + + +int TopLevel::saveFile( const QString& _filename, bool backup, const QString& encoding ) +{ + QFileInfo info(_filename); + bool bSoftWrap = (Prefs::wrapMode() == Prefs::EnumWrapMode::SoftWrap); + + if(info.isDir()) + { + KMessageBox::sorry(this, i18n("You have specified a folder")); + return KEDIT_RETRY; + } + + if (backup && Prefs::backupCopies() && QFile::exists(_filename)) + { + if (!KSaveFile::backupFile(_filename)) + { + KMessageBox::sorry(this, i18n("Unable to make a backup of the original file.")); + } + } + + // WABA: We don't use KSaveFile because it doesn't preserve hard/soft + // links when saving. Most applications don't care about this, but an + // editor is supposed to preserve such things. + + QFile file(_filename); + if(!file.open(IO_WriteOnly)) + { + KMessageBox::sorry(this, i18n("Unable to write to file.")); + return KEDIT_RETRY; + } + + QTextStream textStream(&file); + QTextCodec *codec; + if (!encoding.isEmpty()) + codec = QTextCodec::codecForName(encoding.latin1()); + else + codec = QTextCodec::codecForLocale(); + textStream.setCodec(codec); + + eframe->saveText( &textStream, bSoftWrap ); + file.close(); + + if(file.status()) + { + KMessageBox::sorry(this, i18n("Could not save file.")); + return KEDIT_RETRY; + } + eframe->setModified(false); + return KEDIT_OK; +} + + +void TopLevel::openURL( const KURL& _url, int _mode ) +{ + if ( !_url.isValid() ) + { + QString string; + string = i18n( "Malformed URL\n%1").arg(_url.url()); + + KMessageBox::sorry(this, string); + return; + } + + QString target; + int result = KEDIT_OK; + if (KIO::NetAccess::download(_url, target, this)) + { + result = openFile(target, _mode, _url.fileEncoding()); + } + else + { + if ((_mode & OPEN_NEW) == 0) + { + KMessageBox::error(this, i18n("Cannot download file.")); + return; + } + } + if (result == KEDIT_OK) + { + m_url = _url; + setFileCaption(); + recent->addURL(_url); + eframe->setModified(false); + setGeneralStatusField(i18n("Done")); + } +} + +void TopLevel::urlDrop_slot(QDropEvent* e) { + + dropEvent(e); +} + +void TopLevel::dragEnterEvent(QDragEnterEvent* e) +{ + e->accept(KURLDrag::canDecode(e)); +} + +void TopLevel::dropEvent(QDropEvent* e) +{ + + KURL::List list; + + // This should never happen, but anyway... + if(!KURLDrag::decode(e, list)) + return; + + bool first = true; + for ( KURL::List::ConstIterator it = list.begin(); it != list.end(); ++it) + { + // Load the first file in this window + if ( first && !eframe->isModified() ) + { + openURL( *it, OPEN_READWRITE ); + } + else + { + setGeneralStatusField(i18n("New Window")); + TopLevel *t = new TopLevel (); + t->show (); + setGeneralStatusField(i18n("New Window Created")); + t->openURL( *it, OPEN_READWRITE ); + setGeneralStatusField(i18n("Load Command Done")); + } + first = false; + } +} + +void TopLevel::timer_slot(){ + + statusBar()->changeItem("",ID_GENERAL); + +} + + +void TopLevel::set_colors() +{ + QPalette mypalette = (eframe->palette()).copy(); + + QColorGroup ncgrp( mypalette.active() ); + + if (Prefs::customColor()) + { + ncgrp.setColor(QColorGroup::Text, Prefs::textColor()); + ncgrp.setColor(QColorGroup::Base, Prefs::backgroundColor()); + } + else + { + ncgrp.setColor(QColorGroup::Text, KGlobalSettings::textColor()); + ncgrp.setColor(QColorGroup::Base, KGlobalSettings::baseColor()); + } + + mypalette.setActive(ncgrp); + mypalette.setDisabled(ncgrp); + mypalette.setInactive(ncgrp); + + eframe->setPalette(mypalette); +} + + +void TopLevel::updateSettings( void ) +{ + readSettings(); + setupEditWidget(); +} + +void TopLevel::readSettings( void ) +{ + recent->loadEntries( kapp->config() ); +} + + +void TopLevel::toggle_overwrite(){ + + if(eframe->isOverwriteMode()){ + statusBar()->changeItem("OVR",ID_INS_OVR); + } + else{ + statusBar()->changeItem("INS",ID_INS_OVR); + } + +} + +static const char description[] = I18N_NOOP("KDE text editor"); + +static const KCmdLineOptions options[] = +{ + { "encoding ", I18N_NOOP("Encoding to use for the following documents"), 0 }, + { "+file", I18N_NOOP("File or URL to open"), 0 }, + KCmdLineLastOption +}; + +extern "C" KDE_EXPORT int kdemain (int argc, char **argv) +{ + bool have_top_window = false; + + KAboutData aboutData( "kedit", I18N_NOOP("KEdit"), + KEDITVERSION, description, KAboutData::License_GPL, + "(c) 1997-2000, Bernd Johannes Wuebben"); + aboutData.addAuthor("Bernd Johannes Wuebben",0, "wuebben@kde.org"); + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); + + KApplication a; + //CT KIO::Job::initStatic(); + if ( a.isRestored() ) + { + int n = 1; + while (TopLevel::canBeRestored(n)) + { + TopLevel *tl = new TopLevel(); + tl->restore(n); + n++; + have_top_window = true; + } + } + else + { + have_top_window = false; + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + const QString encoding = args->getOption("encoding"); + const bool doEncoding = args->isSet("encoding") && + QTextCodec::codecForName(encoding.latin1()); + + for(int i = 0; i < args->count(); i++) + { + TopLevel *t = new TopLevel; + t->show (); + have_top_window = true; + + KURL url = args->url(i); + + if(doEncoding) + url.setFileEncoding(encoding); + + t->openURL( url, default_open | TopLevel::OPEN_NEW ); + } + args->clear(); + } + + if(!have_top_window) + { + TopLevel *t = new TopLevel (); + t->show (); + } + + return a.exec (); +} + +SettingsDialog::SettingsDialog(QWidget *parent, const char *name,KConfigSkeleton *config, KSpellConfig *_spellConfig) + : KConfigDialog(parent, name, config), + spellConfig(_spellConfig), spellConfigChanged(false) +{ + // Font + QWidget *font = new QWidget(0, "FontSetting"); + QVBoxLayout *topLayout = new QVBoxLayout(font, 0, KDialog::spacingHint()); + KFontChooser *mFontChooser = new KFontChooser(font, "kcfg_Font", false, QStringList(), false, 6); + topLayout->addWidget(mFontChooser); + addPage(font, i18n("Font"), "fonts", i18n("Editor Font")); + + // Color + Color *color = new Color(0, "ColorSettings"); + addPage(color, i18n("Color"), "colorize", i18n("Text Color in Editor Area")); + + // Spelling + addPage(spellConfig, i18n("Spelling"), + "spellcheck", i18n("Spelling Checker")); + connect(spellConfig, SIGNAL(configChanged()), this, SLOT(slotSpellConfigChanged())); + + // Miscellaneous + Misc *miscOptions = new Misc(0, "MiscSettings"); + addPage(miscOptions, i18n("Miscellaneous"), "misc"); +} + +void SettingsDialog::updateSettings() +{ + spellConfig->writeGlobalSettings(); +} + +void SettingsDialog::updateWidgets() +{ + spellConfig->readGlobalSettings(); + spellConfigChanged = false; +} + +void SettingsDialog::updateWidgetsDefault() +{ +} + +bool SettingsDialog::hasChanged() +{ + return spellConfigChanged; +} + +bool SettingsDialog::isDefault() +{ + return true; +} + +void SettingsDialog::slotSpellConfigChanged() +{ + spellConfigChanged = true; + updateButtons(); +} + +#include "kedit.moc" + diff --git a/kedit/kedit.h b/kedit/kedit.h new file mode 100644 index 0000000..a39eb4d --- /dev/null +++ b/kedit/kedit.h @@ -0,0 +1,229 @@ +/* + + $Id$ + + Copyright (C) 1997 Bernd Johannes Wuebben + wuebben@math.cornell.edu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + +#ifndef _KEDIT_H_ +#define _KEDIT_H_ + +#include +#include + +#include "version.h" + +#include + +class KEdit; +class KSpell; +class KSpellConfig; +class QTimer; +class KAction; +class KRecentFilesAction; + +namespace KIO { class Job; } + +// StatusBar field IDs +#define ID_LINE_COLUMN 1 +#define ID_INS_OVR 2 +#define ID_GENERAL 3 + +class TopLevel : public KMainWindow +{ + Q_OBJECT + +public: + enum { KEDIT_OK = 0, + KEDIT_OS_ERROR = 1, + KEDIT_USER_CANCEL = 2 , + KEDIT_RETRY = 3, + KEDIT_NOPERMISSIONS = 4}; + + enum { OPEN_READWRITE = 1, + OPEN_READONLY = 2, + OPEN_INSERT = 4, + OPEN_NEW = 8 }; + + TopLevel( QWidget *parent=0, const char *name=0 ); + ~TopLevel(); + + /** + * Reads a file into the edit widget. + * + * @return KEDIT_OK on success + */ + int openFile( const QString& _filename, int _mode, const QString &encoding, bool _undoAction = false ); + + /** + * Saves the edit widget to a file. + * + * @return KEDIT_OK on success + */ + int saveFile( const QString& _filename, bool backup, const QString &encoding); + + /** + * Works like openFile but is able to open remote files + */ + void openURL( const KURL& _url, int _mode ); + + /** + * Saves the current text to the URL '_url'. + * + * @return KEDIT::KEDIT_OK on success + */ + + int saveURL( const KURL& _url ); + + /** + * Only show the window when the following load action is successful. + **/ + void setNewWindow() { newWindow = true; } + + /** + * set url + */ + void setUrl(const KURL &url) { m_url = url; } + + /// List of all windows + static QPtrList *windowList; + //QPopupMenu *right_mouse_button; + + bool queryExit( void ); + bool queryClose( void ); + +protected: + void setSensitivity(); + void setupEditWidget(); + void setupStatusBar(); + void setupActions(); + void initSpellConfig(); + +private: + KSpellConfig *kspellconfigOptions; + +public: // Should not be! + KEdit *eframe; +private: + KURL m_url; + QString m_caption; + + bool newWindow; + int statusID, toolID, indentID; + QTimer *statusbar_timer; + KRecentFilesAction *recent; + KAction *cutAction; + KAction *copyAction; + KAction *undoAction; + KAction *redoAction; + + int open_mode; + + KConfig *config; + + KSpell *kspell; // Current spell checking object + + /* + * The source, the destination of the copy, and the open mode + * for each job being run (job ptr is the dict key). + */ + QPtrDict m_sNet; + QPtrDict m_sLocal; + QPtrDict m_openMode; + + // Session management + void saveProperties(KConfig*); + void readProperties(KConfig*); + +public slots: + void openRecent(const KURL&); + void gotoLine(); + void mail(); + void setGeneralStatusField(const QString &string); + void undo(); + void redo(); + void copy(); + void paste(); + void cut(); + void insertDate(); + void print(); + void select_all(); + void clean_space(); + void timer_slot(); + void file_open(); + void file_new(); + void file_insert(); + void setFileCaption(); + void statusbar_slot(); + void file_close(); + void file_save(); + void file_save_as(); + void helpselected(); + void search(); + void replace(); + void search_again(); + void toggle_overwrite(); + + void spellcheck(); + void spell_started ( KSpell *); + void spell_progress (unsigned int percent); + void spell_done(const QString&); + void spell_finished(); + + void urlDrop_slot(QDropEvent* e); + + void set_colors(); + +protected: + /// Drag and Drop + void dragEnterEvent(QDragEnterEvent* e); + void dropEvent(QDropEvent* e); + +private slots: + void updateSettings(); + void readSettings(); + void showSettings(); + void slotSelectionChanged(); + QString replaceISpell(QString msg, int client); +}; + +class SettingsDialog: public KConfigDialog { +Q_OBJECT + +public: + SettingsDialog(QWidget *parent, const char *name,KConfigSkeleton *config, KSpellConfig *_spellConfig); + +protected slots: + void updateSettings(); + void updateWidgets(); + void updateWidgetsDefault(); + void slotSpellConfigChanged(); + +protected: + bool hasChanged(); + bool isDefault(); + +private: + KSpellConfig *spellConfig; + bool spellConfigChanged; +}; + + +#endif + diff --git a/kedit/kedit.kcfg b/kedit/kedit.kcfg new file mode 100644 index 0000000..a647737 --- /dev/null +++ b/kedit/kedit.kcfg @@ -0,0 +1,45 @@ + + + kstandarddirs.h + + + + + KGlobalSettings::fixedFont() + + + + + + false + + + + KGlobalSettings::textColor() + + + + KGlobalSettings::baseColor() + + + + + + + + + SoftWrap + + + + 79 + + + + true + + + diff --git a/kedit/keditui.rc b/kedit/keditui.rc new file mode 100644 index 0000000..f071204 --- /dev/null +++ b/kedit/keditui.rc @@ -0,0 +1,10 @@ + + + +

&Edit + + + + + + diff --git a/kedit/ktextfiledlg.cpp b/kedit/ktextfiledlg.cpp new file mode 100644 index 0000000..1e1a322 --- /dev/null +++ b/kedit/ktextfiledlg.cpp @@ -0,0 +1,212 @@ +// -*- c++ -*- +/* This file is part of the KDE libraries + Copyright (C) 2001 Wolfram Diestel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ktextfiledlg.h" + +KTextFileDialog::KTextFileDialog(const QString& startDir, + const QString& filter, + QWidget *parent, const char* name, + bool modal) + : KFileDialog(startDir, filter, parent, name, modal) +{ + /* + // insert encoding action into toolbar + KSelectAction *mEncoding = new KSelectAction( + i18n( "Set &Encoding" ), 0, this, + SLOT( slotSetEncoding() ), this, + "encoding" ); + + QStringList encodings = KGlobal::charsets()->descriptiveEncodingNames(); + encodings.prepend( i18n( "Default encoding" ) ); + mEncoding->setItems( encodings ); + mEncoding->setCurrentItem(0); + QStringList::Iterator it; + int i = 0; + for( it = encodings.begin(); it != encodings.end(); ++it) { + if ( (*it).contains( encodingStr ) ) { + mEncoding->setCurrentItem( i ); + break; + } + i++; + } + + KToolBar *tb = toolBar(); + mEncoding->plug( tb, 7 ); + */ + + KAction* mEncoding = new KAction( + i18n("Select Encoding..."), 0, + this, SLOT( slotShowEncCombo() ), this, "encoding"); + + mEncoding->setIcon( QString::fromLatin1("charset") ); + + KToolBar *tb = toolBar(); + mEncoding->plug( tb, pathComboIndex() - 1 ); +} + +KTextFileDialog::~KTextFileDialog() {} + +void KTextFileDialog::setEncoding(const QString& encoding) { + enc = encoding; +} + + + +void KTextFileDialog::slotShowEncCombo() +{ + // Modal widget asking the user about charset + // + KDialogBase *encDlg; + QLabel *label; + QComboBox *encCombo; + QVBox *vbox; + + // Create widgets, and display using geometry management + encDlg = new KDialogBase( this, + "Encoding Dialog", true, i18n("Select Encoding"), + KDialogBase::Ok | KDialogBase::Cancel ); + vbox = new QVBox( encDlg ); + vbox->setSpacing( KDialog::spacingHint() ); + encDlg->setMainWidget( vbox ); + label = new QLabel( vbox ); + label->setAlignment( AlignLeft | AlignVCenter ); + label->setText(i18n("Select encoding for text file: ")); + + encCombo = new QComboBox(vbox); + encCombo->setInsertionPolicy(QComboBox::NoInsertion); + encCombo->insertItem(i18n("Default Encoding")); + + QStringList encodings = KGlobal::charsets()->descriptiveEncodingNames(); + encodings.prepend( i18n( "Default encoding" ) ); + encCombo->insertStringList( encodings ); + encCombo->setCurrentItem(0); + QStringList::Iterator it; + int i = 1; + for( it = encodings.begin(); it != encodings.end(); ++it) { + + if ( (*it).contains( encoding() ) ) { + encCombo->setCurrentItem( i ); + break; + } + + i++; + } + + connect( encDlg->actionButton( KDialogBase::Ok ), SIGNAL(clicked()), + encDlg, SLOT(accept()) ); + connect( encDlg->actionButton( KDialogBase::Cancel ), SIGNAL(clicked()), + encDlg, SLOT(reject()) ); + + encDlg->setMinimumSize( 300, 120); + + if ( encDlg->exec() == QDialog::Accepted ) { + // set encoding + if (encCombo->currentItem() == 0) { // Default + setEncoding(""); + } else { + setEncoding(KGlobal::charsets()-> + encodingForName(encCombo->currentText())); + } + } + + + delete encDlg; +} + + +KURL KTextFileDialog::getOpenURLwithEncoding( + const QString& startDir, + const QString& filter, + QWidget *parent, + const QString& caption, + const QString& encoding, + const QString& buttontext) +{ + KTextFileDialog dlg(startDir, filter, parent, "filedialog", true); + dlg.setEncoding(encoding); + dlg.setOperationMode( Opening ); + + dlg.setCaption(caption.isNull() ? i18n("Open") : caption); + dlg.ops->clearHistory(); + if (!buttontext.isEmpty()) + dlg.okButton()->setText(buttontext); + dlg.exec(); + + KURL url = dlg.selectedURL(); + if (url.isValid()) { + if ( url.isLocalFile() ) + KRecentDocument::add( url.path(-1) ); + else + KRecentDocument::add( url.url(-1), true ); + } + + // append encoding to the URL params + url.setFileEncoding(dlg.encoding()); + + return url; +} + +KURL KTextFileDialog::getSaveURLwithEncoding( + const QString& dir, const QString& filter, + QWidget *parent, + const QString& caption, + const QString& encoding) +{ + KTextFileDialog dlg(dir, filter, parent, "filedialog", true); + dlg.setEncoding(encoding); + dlg.setOperationMode( Saving ); + + dlg.setCaption(caption.isNull() ? i18n("Save As") : caption); + dlg.setKeepLocation( true ); + + dlg.exec(); + + KURL url = dlg.selectedURL(); + if (url.isValid()) { + if ( url.isLocalFile() ) + KRecentDocument::add( url.path(-1) ); + else + KRecentDocument::add( url.url(-1) ); + } + + // append encoding to the URL params + url.setFileEncoding(dlg.encoding()); + + return url; +} + +#include "ktextfiledlg.moc" + + + + + + + diff --git a/kedit/ktextfiledlg.h b/kedit/ktextfiledlg.h new file mode 100644 index 0000000..ba15be2 --- /dev/null +++ b/kedit/ktextfiledlg.h @@ -0,0 +1,74 @@ +// -*- c++ -*- +/* This file is part of the KDE libraries + Copyright (C) 2001 Wolfram Diestel + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __KTEXTFILEDLG_H__ +#define __KTEXTFILEDLG_H__ + +#include + +class QComboBox; +class QTextCodec; +class QString; +class KURL; + +/** + * Provides filedialog with a tollbar button for + a char encoding selection. The selected encoding + is returned as parameter charset in the query part + of the URL. This is helps to save the charset together with + the filename in the recent files list. + */ +class KTextFileDialog : public KFileDialog +{ + Q_OBJECT + + public: + KTextFileDialog(const QString& startDir, const QString& filter, + QWidget *parent, const char *name, + bool modal); + + ~KTextFileDialog(); + + static KURL getOpenURLwithEncoding( + const QString& startDir = QString::null, + const QString& filter= QString::null, + QWidget *parent= 0, + const QString& caption = QString::null, + const QString& encoding = QString::null, + const QString& buttonText = QString::null); + + static KURL getSaveURLwithEncoding( + const QString& dir, const QString& filter, + QWidget *parent, + const QString& caption, + const QString& encoding = QString::null); + + QString &encoding() { return enc; } + void setEncoding(const QString& encoding); + + protected slots: + void slotShowEncCombo(); + + private: + QString enc; +}; + + +#endif diff --git a/kedit/misc.ui b/kedit/misc.ui new file mode 100644 index 0000000..2a30333 --- /dev/null +++ b/kedit/misc.ui @@ -0,0 +1,123 @@ + +Misc + + + Misc + + + + 0 + 0 + 300 + 164 + + + + + unnamed + + + 0 + + + + textLabel3 + + + &Word wrap: + + + kcfg_WrapMode + + + + + kcfg_WrapColumn + + + false + + + 999999999 + + + + + kcfg_BackupCopies + + + Make &backup when saving a file + + + true + + + + + + Disable Wrapping + + + + + Soft Wrapping + + + + + At Specified Column + + + + kcfg_WrapMode + + + + + spacer2 + + + Vertical + + + Expanding + + + + 20 + 101 + + + + + + wrapLabel + + + false + + + Wrap &column: + + + kcfg_WrapColumn + + + + + + + kcfg_WrapMode + activated(int) + Misc + settingsWrapMode(int) + + + + misc.ui.h + + + settingsWrapMode( int mode ) + + + diff --git a/kedit/misc.ui.h b/kedit/misc.ui.h new file mode 100644 index 0000000..339c944 --- /dev/null +++ b/kedit/misc.ui.h @@ -0,0 +1,14 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ +void Misc::settingsWrapMode( int mode ) +{ + bool state = ((mode == 2) ? true : false); + kcfg_WrapColumn->setEnabled( state ); + wrapLabel->setEnabled( state ); +} diff --git a/kedit/pixmaps/Makefile.am b/kedit/pixmaps/Makefile.am new file mode 100644 index 0000000..798615d --- /dev/null +++ b/kedit/pixmaps/Makefile.am @@ -0,0 +1,2 @@ +KDE_ICON = kedit + diff --git a/kedit/pixmaps/hi16-app-kedit.png b/kedit/pixmaps/hi16-app-kedit.png new file mode 100644 index 0000000..d212377 Binary files /dev/null and b/kedit/pixmaps/hi16-app-kedit.png differ diff --git a/kedit/pixmaps/hi22-app-kedit.png b/kedit/pixmaps/hi22-app-kedit.png new file mode 100644 index 0000000..6c0c574 Binary files /dev/null and b/kedit/pixmaps/hi22-app-kedit.png differ diff --git a/kedit/pixmaps/hi32-app-kedit.png b/kedit/pixmaps/hi32-app-kedit.png new file mode 100644 index 0000000..5dbf6bc Binary files /dev/null and b/kedit/pixmaps/hi32-app-kedit.png differ diff --git a/kedit/pixmaps/hi48-app-kedit.png b/kedit/pixmaps/hi48-app-kedit.png new file mode 100644 index 0000000..21d42dc Binary files /dev/null and b/kedit/pixmaps/hi48-app-kedit.png differ diff --git a/kedit/pixmaps/hi64-app-kedit.png b/kedit/pixmaps/hi64-app-kedit.png new file mode 100644 index 0000000..64a1ad0 Binary files /dev/null and b/kedit/pixmaps/hi64-app-kedit.png differ diff --git a/kedit/prefs.kcfgc b/kedit/prefs.kcfgc new file mode 100644 index 0000000..0e2e195 --- /dev/null +++ b/kedit/prefs.kcfgc @@ -0,0 +1,7 @@ +# Code generation options for kconfig_compiler +File=kedit.kcfg +#IncludeFiles=defines.h +ClassName=Prefs +Singleton=true +#CustomAdditions=true +#Mutators=Zoom diff --git a/kedit/version.h b/kedit/version.h new file mode 100644 index 0000000..c1b3b2a --- /dev/null +++ b/kedit/version.h @@ -0,0 +1,2 @@ +#define KEDITVERSION "1.3" + diff --git a/kfloppy/KFloppy.desktop b/kfloppy/KFloppy.desktop new file mode 100644 index 0000000..113a24d --- /dev/null +++ b/kfloppy/KFloppy.desktop @@ -0,0 +1,96 @@ +[Desktop Entry] +GenericName=Floppy Formatter +GenericName[af]=Sagteskyf Formateerder +GenericName[ar]=مهئ الأقراص المرنة +GenericName[az]=Disket Şəkilləndirici +GenericName[bg]=Форматиране на дискети +GenericName[br]=Furmader pladennig +GenericName[bs]=Formatiranje disketa +GenericName[ca]=Formatador de disquet +GenericName[cs]=Formátovač disket +GenericName[cy]=Fformatio Disg Meddal +GenericName[da]=Disketteformatering +GenericName[de]=Diskettenformatierer +GenericName[el]=Εργαλείο διαμόρφωσης δισκέτας +GenericName[eo]=Formatilo por disketoj +GenericName[es]=Formateador de disquetes +GenericName[et]=Diskettide vormindamise utiliit +GenericName[eu]=Diskete Eratzailea +GenericName[fa]=قالب‌بندی‌کنندۀ فلاپی +GenericName[fi]=Levykkeiden alustusohjelma +GenericName[fr]=Outil de formatage de disquette +GenericName[ga]=Uirlis Fhormáidithe Dioscaí Boga +GenericName[gl]=Formatador de Disquetes +GenericName[he]=מאתחל תקליטונים +GenericName[hi]=फ़्लॉपी फार्मेटर +GenericName[hr]=Formatiranje disketa +GenericName[hu]=Floppy-formázó +GenericName[id]=Pemformat disket +GenericName[is]=Tól til að forsníða disklinga +GenericName[it]=Formattatore di dischetti +GenericName[ja]=フロッピーをフォーマット +GenericName[ka]=დისკეტის დამფორმატებელი +GenericName[kk]=Иілгіш дискін пішімдеу +GenericName[km]=កម្មវិធី​ធ្វើទ្រង់ទ្រាយ​ថាស់ទន់ +GenericName[ko]=플로피 디스크를 포맷해주는 도구 +GenericName[lt]=Diskelio formatavimas +GenericName[lv]=Diskešu Formatētājs +GenericName[mk]=Форматирање на дискети +GenericName[ms]=Pengformat Cakera Liut +GenericName[mt]=Għodda biex tifformattja floppies +GenericName[nb]=Diskettformaterer +GenericName[nds]=Diskettformaterer +GenericName[ne]=फ्लपी ढाँचाकर्ता +GenericName[nl]=Diskettes formatteren +GenericName[nn]=Formaterer diskettar +GenericName[pa]=ਫਲਾਪੀ ਫਾਰਮਿਟਰ +GenericName[pl]=Program formatujący dyskietki +GenericName[pt]=Formatação de Disquetes +GenericName[pt_BR]=Formatador de disquetes +GenericName[ro]=Formator floppy-disc-uri +GenericName[ru]=Форматирование дискет +GenericName[sk]=Formátovanie diskiet +GenericName[sl]=Formatiranje disket +GenericName[sr]=Форматирање дискета +GenericName[sr@Latn]=Formatiranje disketa +GenericName[sv]=Formatera disketter +GenericName[ta]=நெகிழ்வட்டு வடிவமைப்பான் +GenericName[tg]=Шаклбанднамоии Диски Нарм +GenericName[th]=เครื่องมือฟอร์แมตแผ่นฟลอปปี้้ +GenericName[tr]=Disket Biçimlendirici +GenericName[uk]=Відформатувати дискету +GenericName[uz]=Disketni formatlagich +GenericName[uz@cyrillic]=Дискетни форматлагич +GenericName[ven]=Muvhekanyi wa Floppy +GenericName[vi]=Trình định dạng đĩa +GenericName[wa]=Usteye po-z abwesner des plaketes +GenericName[xh]=Floppy formata +GenericName[zh_CN]=软盘格式化程序 +GenericName[zh_TW]=軟碟格式化程式 +GenericName[zu]=Umakhi we-floppy +Name=KFloppy +Name[af]=Kfloppie +Name[eo]=Disketingo +Name[hi]=के-फ़्लॉपी +Name[lv]=KMīkstnis +Name[ne]=केडीई फ्लपी +Name[pa]=ਕਫਲਾਪੀ +Name[pl]=Dyskietka +Name[pt_BR]=Disquete +Name[sv]=Kfloppy +Name[ta]=கேநெகிழ்வட்டு +Name[tg]=KДиски Нарм +Name[th]=ฟอร์แมตฟลอปปี้ +Name[tr]=Disket Biçimlendirici +Name[wa]=KPlakete +Name[zh_TW]=KDE 軟碟 +MimeType= +DocPath=kfloppy/index.html +Exec=kfloppy -caption "%c" %i %m +Icon=kfloppy +Path= +Type=Application +Terminal=false +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Utility;X-KDE-Utilities-Peripherals; diff --git a/kfloppy/Makefile.am b/kfloppy/Makefile.am new file mode 100644 index 0000000..83b0411 --- /dev/null +++ b/kfloppy/Makefile.am @@ -0,0 +1,23 @@ +kfloppy_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kfloppy_LDADD = $(LIB_KDEUI) -lm +INCLUDES = $(all_includes) + +####### Files + +bin_PROGRAMS = kfloppy + +noinst_HEADERS = floppy.h +kfloppy_SOURCES = main.cpp format.cpp floppy.cpp + +METASOURCES = format.moc floppy.moc + +KDE_ICON = kfloppy + +xdg_apps_DATA = KFloppy.desktop + +servicedata_DATA = floppy_format.desktop +servicedatadir = $(kde_datadir)/konqueror/servicemenus + +messages: + $(XGETTEXT) $(kfloppy_SOURCES) -o $(podir)/kfloppy.pot + diff --git a/kfloppy/README b/kfloppy/README new file mode 100644 index 0000000..79c40ce --- /dev/null +++ b/kfloppy/README @@ -0,0 +1,23 @@ +KFloppy 2.1 +=========== + +KFloppy was "done and feature complete and bug free", for systems +running Linux. Other KDE platforms had an app that put up a warning +box and was then totally inert. I've restructured the whole thing, +cleaned up the code somewhat, and modularized it. + +Currently KFloppy is tested on a FBSD machine with a floppy drive +and a zip drive. It should still behave on Linux, but I haven't tried. + +KFloppy 0.2 +=========== + + KFloppy formats disks and puts a DOS or ext2fs filesystem on +them. + +Best Regards, +Bernd Wuebben +wuebben@kde.org + + + diff --git a/kfloppy/TODO b/kfloppy/TODO new file mode 100644 index 0000000..6df5f2b --- /dev/null +++ b/kfloppy/TODO @@ -0,0 +1,47 @@ +2005-06-07 + +As I am wirting an answer to an email about the to-do in KFloppy, +better have it in the source too. + + + +The biggest challenge was to support non-legacy (USB, IDE...) floppy drives. +I have opened a way to it with what has the working title "user-given devices". +(A better title for the feature would be a good thing too. +It just mean that instead of selecting "Primary" or "Secondary" as floppy drive, +you can give a device, like /dev/sda4 ) + +The "user-given device" is pretty raw currently, allowing nearly no comfort for +the user. So if you have an external drive (may a ZIP drive), you could try to +make this mode better. + +A little variant would be to support the device like /dev/fd0u2880 for +formatting. Currently it does not work with Full Format, +as a "user-given device" is supposed not to be low-level formatable. +(I do not know any Linux or BSD tool that can low-level format +non-legacy drives.) + +Another thing that I have very recently discovered is that +extended floppy drives will not work in "superfloppy" format +(disks without partition table), as neither mkdosfs nor BSD's newfs allow this +without a special parameter. (I have not checked the other tools used.) + +Before I forget it: in the "user-given device" mode, it would be nice if there +was support from KDE (for example devices:/ ) to know what devices are really +flopy drives (not that a user roasts an umounted partition of his harddisk. + +A much easier task would be perhaps to catch more errors from +the external programs so that it is displayed to the user. +(Also to catch anything error message having the string "error" in it, +which is currently not done.) + +That is I think the list of what users could benefit. + +Internally, when the Qt4 switch is done, it would need a review to see how +to improve the way how the classes calling the external applications are +handled. + +Of course, when modifying, care must taken not to break the BSD part of the +code. (Perhaps we need a way on Linux to be able to compile the BSD part, +as there is nothing BSD specific in the code, only the external BSD programs +are specific.) diff --git a/kfloppy/debug.h b/kfloppy/debug.h new file mode 100644 index 0000000..e0080da --- /dev/null +++ b/kfloppy/debug.h @@ -0,0 +1,65 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 2003 Adriaan de Groot + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program in a file called COPYING; if not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + +*/ + +#ifndef DEBUG_H +#define DEBUG_H + +/** + * \file debug.h + * + * \brief Debugging definitions for KFloppy. + * + * It also tries to map operating systems + * into families, so you can use ANY_LINUX or ANY_BSD + * in the code to differentiate those families. + * What happens on other systems is anyone's guess. + */ + + +#define KFAREA (2002) + +#ifndef NDEBUG +#define DEBUGSETUP kdDebug(KFAREA) << (__PRETTY_FUNCTION__) << endl +#define DEBUGS(a) kdDebug(KFAREA) << " " << a << endl +#else +#define DEBUGSETUP +#define DEBUGS(a) +#endif + + +// Detect vaguely what OS we're working with. Map variants +// to one known kind. +// +// +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#define ANY_BSD (1) +#else +#if defined(linux) || defined(LINUX) || defined (__linux) || defined(__linux__) +#define ANY_LINUX (1) +#endif +#endif + + + +#endif + diff --git a/kfloppy/floppy.cpp b/kfloppy/floppy.cpp new file mode 100644 index 0000000..043f2f0 --- /dev/null +++ b/kfloppy/floppy.cpp @@ -0,0 +1,741 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 1997 Bernd Johannes Wuebben + Copyright (C) 2004, 2005 Nicolas GOUTTE + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "floppy.h" +#include "format.h" + +FloppyData::FloppyData(QWidget * parent, const char * name) + : KDialog( parent, name ), + formatActions(0L), m_canLowLevel(false), m_canZeroOut( false ) +{ + + formating = false; + //abort = false; + blocks = 0; + + QVBoxLayout* ml = new QVBoxLayout( this, 10 ); + + QHBoxLayout* h1 = new QHBoxLayout( ml ); + + QVBoxLayout* v1 = new QVBoxLayout( h1 ); + h1->addSpacing( 5 ); + + QGridLayout* g1 = new QGridLayout( v1, 3, 2 ); + + deviceComboBox = new KComboBox( false, this, "ComboBox_1" ); + label1 = new QLabel( deviceComboBox, i18n("Floppy &drive:"), this ); + g1->addWidget( label1, 0, 0, AlignLeft ); + g1->addWidget( deviceComboBox, 0, 1 ); + + // Make the combo box editable, so that the user can enter a device name + deviceComboBox->setEditable( true ); + + deviceComboBox->insertItem(i18n("Primary")); + deviceComboBox->insertItem(i18n("Secondary")); + + const QString deviceWhatsThis = i18n("Select the floppy drive."); + + QWhatsThis::add(label1, deviceWhatsThis); + QWhatsThis::add(deviceComboBox, deviceWhatsThis); + + + densityComboBox = new KComboBox( false, this, "ComboBox_1" ); + label2 = new QLabel( densityComboBox, i18n("&Size:"), this); + g1->addWidget( label2, 1, 0, AlignLeft ); + g1->addWidget( densityComboBox, 1, 1 ); + +#if defined(ANY_LINUX) + densityComboBox->insertItem( i18n( "Auto-Detect" ) ); +#endif + densityComboBox->insertItem(i18n("3.5\" 1.44MB")); + densityComboBox->insertItem(i18n("3.5\" 720KB")); + densityComboBox->insertItem(i18n("5.25\" 1.2MB")); + densityComboBox->insertItem(i18n("5.25\" 360KB")); + + const QString densityWhatsThis = + i18n("This allows you to select the " + "floppy disk's size and density."); + + QWhatsThis::add(label2, densityWhatsThis); + QWhatsThis::add(densityComboBox, densityWhatsThis); + + + filesystemComboBox = new KComboBox( false, this, "ComboBox_2" ); + label3 = new QLabel( filesystemComboBox, i18n("F&ile system:"), this); + g1->addWidget( label3, 2, 0, AlignLeft ); + g1->addWidget( filesystemComboBox, 2, 1 ); + g1->setColStretch(1, 1); + +#if defined(ANY_LINUX) + QWhatsThis::add( label3, + i18n( "Linux", "KFloppy supports three file formats under Linux: MS-DOS, Ext2, and Minix" ) ); +#elif defined(ANY_BSD) + QWhatsThis::add( label3, + i18n( "BSD", "KFloppy supports three file formats under BSD: MS-DOS, UFS, and Ext2" ) ); +#endif + // If you modify the user visible string, change them also (far) below + + QString userFeedBack; + uint numFileSystems = 0; + +#if defined(ANY_LINUX) + QWhatsThis::add( filesystemComboBox, + i18n( "Linux", "KFloppy supports three file formats under Linux: MS-DOS, Ext2, and Minix" ) ); + if (FATFilesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("DOS")); + ++numFileSystems; + userFeedBack += i18n( "Linux", "Program mkdosfs found." ); + } + else { + userFeedBack += i18n( "Linux", "Program mkdosfs not found. MSDOS formatting not available." ); + } + userFeedBack += "
"; + if (Ext2Filesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("ext2")); + ++numFileSystems; + userFeedBack += i18n( "Program mke2fs found." ); + } + else { + userFeedBack += i18n( "Program mke2fs not found. Ext2 formatting not available" ); + } + userFeedBack += "
"; + if (MinixFilesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("Minix")); + ++numFileSystems; + userFeedBack += i18n( "Linux", "Program mkfs.minix found." ); + } + else { + userFeedBack += i18n( "Linux", "Program mkfs.minix not found. Minix formatting not available" ); + } +#elif defined(ANY_BSD) + QWhatsThis::add( filesystemComboBox, + i18n( "BSD", "KFloppy supports two file formats under BSD: MS-DOS and UFS" ) ); + if (FATFilesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("DOS")); + ++numFileSystems; + userFeedBack += i18n( "BSD", "Program newfs_msdos found." ); + } + else { + userFeedBack += i18n( "BSD", "Program newfs_msdos not found. MSDOS formatting not available." ); + } + userFeedBack += "
"; + if (UFSFilesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("UFS")); + ++numFileSystems; + userFeedBack += i18n( "BSD", "Program newfs found." ); + } + else { + userFeedBack += i18n( "BSD", "Program newfs not found. UFS formatting not available." ); + } + userFeedBack += "
"; + if (Ext2Filesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("ext2")); + ++numFileSystems; + userFeedBack += i18n( "Program mke2fs found." ); + } + else { + userFeedBack += i18n( "Program mke2fs not found. Ext2 formatting not available" ); + } +#endif + + v1->addSpacing( 10 ); + + buttongroup = new QButtonGroup( 3, Qt::Vertical, i18n("&Formatting"), this, "ButtonGroup_1" ); + + + quick = new QRadioButton( i18n( "Q&uick format" ), buttongroup, "RadioButton_2" ); + QWhatsThis::add( quick, + i18n("Quick format is only a high-level format:" + " it creates only a file system.") ); + + zerooutformat = new QRadioButton( i18n( "&Zero out and quick format"), buttongroup, "RadioButton_ZeroOutFormat" ); + QWhatsThis::add( zerooutformat, + i18n("This first erases the floppy by writing zeros and then it creates the file system.") ); + + fullformat = new QRadioButton( i18n( "Fu&ll format"), buttongroup, "RadioButton_3" ); + QWhatsThis::add( fullformat, + i18n("Full format is a low-level and high-level format. It erases everything on the disk.") ); + + v1->addWidget( buttongroup ); + + // ### TODO: we need some user feedback telling why full formatting is disabled. + userFeedBack += "
"; + m_canLowLevel = FDFormat::runtimeCheck(); + if (m_canLowLevel){ + fullformat->setChecked(true); + userFeedBack += i18n( "Program fdformat found." ); + } + else { + fullformat->setDisabled(true); + quick->setChecked(true); + userFeedBack += i18n( "Program fdformat not found. Full formatting disabled." ); + } + userFeedBack += "
"; + m_canZeroOut = DDZeroOut::runtimeCheck(); + if ( m_canZeroOut ) + { + zerooutformat->setChecked( true ); + userFeedBack += i18n( "Program dd found." ); + } + else { + zerooutformat->setDisabled(true); + userFeedBack += i18n( "Program dd not found. Zeroing-out disabled." ); + } + + verifylabel = new QCheckBox( this, "CheckBox_Integrity" ); + verifylabel->setText(i18n( "&Verify integrity" )); + verifylabel->setChecked(true); + v1->addWidget( verifylabel, AlignLeft ); + QWhatsThis::add( verifylabel, + i18n("Check this if you want the floppy disk to be checked after formatting." + " Please note that the floppy will be checked twice if you have selected full formatting.") ); + + labellabel = new QCheckBox( this, "Checkbox_Label" ); + labellabel->setText(i18n( "Volume la&bel:") ); + labellabel->setChecked(true); + v1->addWidget( labellabel, AlignLeft ); + QWhatsThis::add( labellabel, + i18n("Check this if you want a volume label for your floppy." + " Please note that Minix does not support labels at all.") ); + + QHBoxLayout* h2 = new QHBoxLayout( v1 ); + h2->addSpacing( 20 ); + + lineedit = new KLineEdit( this, "Lineedit" ); + // ### TODO ext2 supports 16 characters. Minix has not any label. UFS? + lineedit->setText(i18n( "Volume label, maximal 11 characters", "KDE Floppy" ) ); + lineedit->setMaxLength(11); + h2->addWidget( lineedit, AlignRight ); + QWhatsThis::add( lineedit, + i18n("This is for the volume label." + " Due to a limitation of MS-DOS the label can only be 11 characters long." + " Please note that Minix does not support labels, whatever you enter here.") ); + + connect(labellabel,SIGNAL(toggled(bool)),lineedit,SLOT(setEnabled(bool))); + + QVBoxLayout* v3 = new QVBoxLayout( h1 ); + + formatbutton = new KPushButton( this, "PushButton_3" ); + formatbutton->setText(i18n( "&Format") ); + formatbutton->setAutoRepeat( false ); + if (!numFileSystems) + formatbutton->setDisabled(false); // We have not any helper program for creating any file system + connect(formatbutton,SIGNAL(clicked()),this,SLOT(format())); + v3->addWidget( formatbutton ); + QWhatsThis::add( formatbutton, + i18n("Click here to start formatting.") ); + + v3->addStretch( 1 ); + + //Setup the Help Menu + helpMenu = new KHelpMenu(this, KGlobal::instance()->aboutData(), false); + + helpbutton = new KPushButton( KStdGuiItem::help(), this ); + helpbutton->setAutoRepeat( false ); + helpbutton->setPopup(helpMenu->menu()); + v3->addWidget( helpbutton ); + + quitbutton = new KPushButton( KStdGuiItem::quit(), this ); + quitbutton->setAutoRepeat( false ); + connect(quitbutton,SIGNAL(clicked()),this,SLOT(quit())); + v3->addWidget( quitbutton ); + + ml->addSpacing( 10 ); + + frame = new QLabel( this, "NewsWindow" ); + frame->setFrameStyle(QFrame::Panel | QFrame::Sunken); + frame->setAlignment(WordBreak|ExpandTabs); + QWhatsThis::add( frame, + i18n("This is the status window, where error messages are displayed.") ); + + QString frameText( userFeedBack ); + frameText.prepend( "" ); + frameText.append( "" ); + frame->setText( frameText ); + + ml->addWidget( frame ); + + progress = new KProgress( this, "Progress" ); + progress->setDisabled( true ); + ml->addWidget( progress ); + + QWhatsThis::add(progress, + i18n("Shows progress of the format.")); + + readSettings(); + setWidgets(); + + if (!numFileSystems) { + QString errorMessage; + errorMessage += ""; + errorMessage += i18n("KFloppy cannot find any of the needed programs for creating file systems; please check your installation.

Log:"); + errorMessage += "
"; + errorMessage += userFeedBack; + errorMessage += "
"; + KMessageBox::error( this, errorMessage ); + } +} + + +FloppyData::~FloppyData() +{ + delete formatActions; +} + +void FloppyData::closeEvent(QCloseEvent*) +{ + quit(); +} + +void FloppyData::keyPressEvent(QKeyEvent *e) +{ + switch(e->key()) { + case Qt::Key_F1: + kapp->invokeHelp(); + break; + default: + KDialog::keyPressEvent(e); + return; + } +} + +void FloppyData::show() { + setCaption(i18n("KDE Floppy Formatter")); + KDialog::show(); +} + +bool FloppyData::findDevice() +{ + // Note: this function does not handle user-given devices + + drive=-1; + if( deviceComboBox->currentText() == i18n("Primary") ) + { + drive=0; + } + else if( deviceComboBox->currentText() == i18n("Secondary") ) + { + drive=1; + } + + blocks=-1; + + if( densityComboBox->currentText() == i18n("3.5\" 1.44MB")){ + blocks = 1440; + } + else + if( densityComboBox->currentText() == i18n("3.5\" 720KB")){ + blocks = 720; + } + else + if( densityComboBox->currentText() == i18n("5.25\" 1.2MB")){ + blocks = 1200; + } + else + if( densityComboBox->currentText() == i18n("5.25\" 360KB")){ + blocks = 360; + } +#if defined(ANY_LINUX) + else { // For Linux, anything else is Auto + blocks = 0; + } +#endif + + return true; +} + +bool FloppyData::setInitialDevice(const QString& dev) +{ + + QString newDevice = dev; + + KURL url( newDevice ); + if( url.isValid() && ( url.protocol() == "media" || url.protocol() == "system" ) ) { + QString name = url.fileName(); + + DCOPRef mediamanager( "kded", "mediamanager" ); + DCOPReply reply = mediamanager.call("properties(QString)", name); + if (!reply.isValid()) { + kdError() << "Invalid reply from mediamanager" << endl; + } else { + QStringList properties = reply; + newDevice = properties[5]; + } + } + + int drive = -1; + if ( newDevice.startsWith("/dev/fd0") ) + drive = 0; + if ( newDevice.startsWith("/dev/fd1")) + drive = 1; + + // ### TODO user given devices + + bool ok = (drive>=0); + if (ok) + deviceComboBox->setCurrentItem(drive); + return ok; +} + +void FloppyData::quit(){ + if (formatActions) formatActions->quit(); + writeSettings(); + kapp->quit(); + delete this; +} + +void FloppyData::setEnabled(bool b) +{ + if (b) + unsetCursor(); + else + setCursor(QCursor(WaitCursor)); + label1->setEnabled(b); + deviceComboBox->setEnabled(b); + label2->setEnabled(b); + densityComboBox->setEnabled(b); + label3->setEnabled(b); + filesystemComboBox->setEnabled(b); + buttongroup->setEnabled(b); + quick->setEnabled(b); + fullformat->setEnabled(b && m_canLowLevel); + zerooutformat->setEnabled(b && m_canZeroOut); + verifylabel->setEnabled(b); + labellabel->setEnabled(b); + lineedit->setEnabled(b && labellabel->isChecked() ); + helpbutton->setEnabled(b); + quitbutton->setEnabled(b); + formatbutton->setEnabled(b); + progress->setDisabled( b ); // The other way round! +} + +void FloppyData::reset() +{ + DEBUGSETUP; + + formating = false; + + if (formatActions) + { + formatActions->quit(); + delete formatActions; + formatActions = 0L; + } + + progress->setValue(0); + formatbutton->setText(i18n("&Format")); + setEnabled(true); +} + +void FloppyData::format(){ + + if(formating){ + //abort = true; + reset(); + return; + } + + frame->clear(); + + const QString currentComboBoxDevice ( deviceComboBox->currentText() ); + const bool userDevice = ( currentComboBoxDevice.startsWith ("/dev/") ); + +#ifdef ANY_BSD + if ( userDevice && filesystemComboBox->currentText() != i18n("UFS")) + { + KMessageBox::error( this, i18n("BSD", "Formatting with BSD on a user-given device is only possible with UFS") ); + return; + } + // no "else" ! +#endif + if ( userDevice && ( quick->isChecked() || zerooutformat->isChecked() ) ) + { + if (KMessageBox::warningContinueCancel( this, + i18n("Formatting will erase all data on the device:
%1
" + "(Please check the correctness of the device name.)
" + "Are you sure you wish to proceed?
").arg( currentComboBoxDevice ) + , i18n("Proceed?") ) != KMessageBox::Continue) + { + return; + } + } + else if ( userDevice ) + { + // The user has selected full formatting on a user-given device. That is not supported yet! + KMessageBox::error( this, "Full formatting of a user-given device is not possible!" ); + return; + } + else + { + if (KMessageBox::warningContinueCancel( this, + i18n("Formatting will erase all data on the disk.\n" + "Are you sure you wish to proceed?"), i18n("Proceed?") ) != + KMessageBox::Continue) + { + return; + } + } + + // formatbutton->setText(i18n("A&bort")); + setEnabled(false); + + // Erase text box + frame->setText( QString::null ); + + if ( !userDevice ) + { + if ( !findDevice() ) + { + reset(); + return; + } + } + + if (formatActions) delete formatActions; + formatActions = new KFActionQueue(this); + + connect(formatActions,SIGNAL(status(const QString &,int)), + this,SLOT(formatStatus(const QString &,int))); + connect(formatActions,SIGNAL(done(KFAction *,bool)), + this,SLOT(reset())); + + if ( quick->isChecked()) + { + formating=false; + // No fdformat to push + } + else if ( zerooutformat->isChecked() ) + { + DDZeroOut* f = new DDZeroOut( this ); + if ( userDevice ) + { + f->configureDevice( currentComboBoxDevice ); + } + else + { + f->configureDevice( drive, blocks ); + } + formatActions->queue(f); + } + else if ( userDevice ) + { + // We should not have got here, assume quick format + formating=false; + // No fdformat to push + } + else + { + FDFormat *f = new FDFormat(this); + f->configureDevice(drive,blocks); + f->configure(verifylabel->isChecked()); + formatActions->queue(f); + } + + if ( filesystemComboBox->currentText() == i18n("DOS") ) + { + FATFilesystem *f = new FATFilesystem(this); + f->configure(verifylabel->isChecked(), + labellabel->isChecked(), + lineedit->text()); + if ( userDevice ) + { + f->configureDevice( currentComboBoxDevice ); + } + else + { + f->configureDevice(drive,blocks); + } + formatActions->queue(f); + } + + else if ( filesystemComboBox->currentText() == i18n("ext2") ) + { + Ext2Filesystem *f = new Ext2Filesystem(this); + f->configure(verifylabel->isChecked(), + labellabel->isChecked(), + lineedit->text()); + if ( userDevice ) + { + f->configureDevice( currentComboBoxDevice ); + } + else + { + f->configureDevice(drive,blocks); + } + formatActions->queue(f); + } + +#ifdef ANY_BSD + else if ( filesystemComboBox->currentText() == i18n("UFS") ) + { + FloppyAction *f = new UFSFilesystem(this); + f->configureDevice(drive,blocks); + formatActions->queue(f); + } +#endif + +#ifdef ANY_LINUX + else if ( filesystemComboBox->currentText() == i18n("Minix") ) + { + MinixFilesystem *f = new MinixFilesystem(this); + f->configure(verifylabel->isChecked(), + labellabel->isChecked(), + lineedit->text()); + if ( userDevice ) + { + f->configureDevice( currentComboBoxDevice ); + } + else + { + f->configureDevice(drive,blocks); + } + formatActions->queue(f); + } +#endif + + + + formatActions->exec(); +} + +void FloppyData::formatStatus(const QString &s,int p) +{ + kdDebug(2002) << "FloppyData::formatStatus: " << s << " : " << p << endl; + if (!s.isEmpty()) + { + const QString oldText ( frame->text() ); + if ( oldText.isEmpty() ) + { + frame->setText( s ); + } + else + { + frame->setText( oldText + '\n' + s ); + } + } + + if ((0<=p) && (p<=100)) + progress->setValue(p); +} + +void FloppyData::writeSettings(){ + + config = kapp->config(); + config->setGroup("GeneralData"); + + densityconfig = densityComboBox->currentText().stripWhiteSpace(); + filesystemconfig = filesystemComboBox->currentText().stripWhiteSpace(); + driveconfig = deviceComboBox->currentText().stripWhiteSpace(); + + quickformatconfig = quick->isChecked(); + + labelnameconfig = lineedit->text().stripWhiteSpace(); + + labelconfig = labellabel->isChecked(); + + verifyconfig = verifylabel->isChecked(); + + config->writeEntry("CreateLabel",labelconfig); + config->writeEntry("Label",labelnameconfig); + + + config->writeEntry("QuickFormat",quickformatconfig); + config->writeEntry("FloppyDrive",driveconfig); + config->writeEntry("Density",densityconfig); + config->writeEntry("Filesystem",filesystemconfig); + config->writeEntry("Verify",verifyconfig); + config->sync(); + +} + +void FloppyData::readSettings(){ + + config = kapp->config(); + config->setGroup("GeneralData"); + + verifyconfig = config->readNumEntry("Verify", 1); + labelconfig = config->readNumEntry("CreateLabel",1); + labelnameconfig = config->readEntry( "Label", i18n("Volume label, maximal 11 characters", "KDE Floppy") ); + quickformatconfig = config->readNumEntry("QuickFormat",0); + driveconfig = config->readEntry( "FloppyDrive", i18n("Primary") ); +#if defined(ANY_LINUX) + densityconfig = config->readEntry( "Density", i18n( "Auto-Detect" ) ); +#else + densityconfig = config->readEntry( "Density", i18n("3.5\" 1.44MB") ); +#endif + filesystemconfig = config->readEntry( "Filesystem", i18n("DOS") ); + +} + +void FloppyData::setWidgets(){ + + labellabel->setChecked(labelconfig); + verifylabel->setChecked(verifyconfig); + quick->setChecked(quickformatconfig || !m_canLowLevel); + fullformat->setChecked(!quickformatconfig && m_canLowLevel); + lineedit->setText(labelnameconfig); + + for(int i = 0 ; i < deviceComboBox->count(); i++){ + if ( deviceComboBox->text(i) == driveconfig){ + deviceComboBox->setCurrentItem(i); + } + } + + for(int i = 0 ; i < filesystemComboBox->count(); i++){ + if ( filesystemComboBox->text(i) == filesystemconfig){ + filesystemComboBox->setCurrentItem(i); + } + } + + for(int i = 0 ; i < densityComboBox->count(); i++){ + if ( densityComboBox->text(i) == densityconfig){ + densityComboBox->setCurrentItem(i); + } + } +} + +#include "floppy.moc" diff --git a/kfloppy/floppy.h b/kfloppy/floppy.h new file mode 100644 index 0000000..2d4d519 --- /dev/null +++ b/kfloppy/floppy.h @@ -0,0 +1,128 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 1997 Bernd Johannes Wuebben + Copyright (C) 2004, 2005 Nicolas GOUTTE + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef FloppyData_included +#define FloppyData_included + +#include + +class QCheckBox; +class QLineEdit; +class QLabel; +class QRadioButton; +class QComboBox; +class QButtonGroup; +class QGroupBox; + +class KProgress; +class KConfig; +class KPushButton; +class KHelpMenu; +class KFAction; +class KFActionQueue; + +class FloppyData : public KDialog +{ + Q_OBJECT + +public: + FloppyData(QWidget* parent = 0, const char * name = 0); + virtual ~FloppyData(); + + /// Need to overload normal show() in order to mangle caption + void show(); + /// Maps combobox selection to drive and density + bool findDevice(); + /// set default device + bool setInitialDevice(const QString& dev); + /** Override closeEvent() in order to properly close + the entire application.*/ + void closeEvent(QCloseEvent*); + /// Writing the user-visible settings. + void writeSettings(); + /// Reading the user-visible settings. + void readSettings(); + /// Map stored settings to widget status + void setWidgets(); + /// A kind of QString::find() + int findKeyWord(QString &, const QString &); + /// Enable/disable all UI elements + void setEnabled(bool); + +public slots: + void quit(); + void format(); + void reset(); + + void formatStatus(const QString &,int); + +protected slots: + +private: + int verifyconfig; + int labelconfig; + QString labelnameconfig; + int quickformatconfig; + QString driveconfig; + QString densityconfig; + QString filesystemconfig; + KConfig *config; + + int drive; + /// Number of blocks of the floppy (typically 1440) + int blocks; + + bool formating; + //bool abort; + + QGroupBox* outerframe; + QLabel* label1; + QLabel* label2; + QLabel* label3; + QButtonGroup* buttongroup; + QCheckBox* verifylabel; + QCheckBox* labellabel; + QLineEdit* lineedit; + QRadioButton* quick; + QRadioButton* zerooutformat; + KPushButton* quitbutton; + KPushButton* helpbutton; + QRadioButton* fullformat; + KPushButton* formatbutton; + QLabel* frame; + QComboBox* deviceComboBox; + QComboBox* filesystemComboBox; + QComboBox* densityComboBox; + KProgress* progress; + KHelpMenu* helpMenu; + + KFActionQueue *formatActions; + + bool m_canLowLevel; ///< Low level formatting is possible (i.e. was fdformat found?) + bool m_canZeroOut; ///< Is zero-out possible (i.e. was dd found?) +protected: + void keyPressEvent(QKeyEvent *e); + +}; + +#endif // FloppyData_included diff --git a/kfloppy/floppy_format.desktop b/kfloppy/floppy_format.desktop new file mode 100644 index 0000000..b780ac9 --- /dev/null +++ b/kfloppy/floppy_format.desktop @@ -0,0 +1,54 @@ +[Desktop Action Format] +Exec=kfloppy %u +Icon=kfloppy +Name=Format +Name[ar]=تهيئة +Name[bg]=Форматиране +Name[br]=Furmadiñ +Name[ca]=Dona format +Name[cs]=Formátovat +Name[cy]=Fformat +Name[de]=Formatieren +Name[el]=Διαμόρφωση +Name[eo]=Formato +Name[es]=Formatear +Name[et]=Vorminda +Name[fa]=قالب‌بندی +Name[fr]=Formater +Name[ga]=Formáid +Name[he]=פורמט +Name[hu]=Formázás +Name[is]=Forsníða +Name[it]=Formatta +Name[ja]=フォーマット +Name[ka]=ფორმატი +Name[kk]=Дискетаны пішімдеу +Name[km]=ធ្វើ​ទ្រង់ទ្រាយ +Name[lt]=Formatas +Name[nds]=Formateren +Name[ne]=ढाँचा +Name[nl]=Formatteren +Name[nn]=Formater +Name[pa]=ਫਾਰਮਿਟ +Name[pl]=Formatuj +Name[pt]=Formatar +Name[pt_BR]=Formatar +Name[ru]=Форматирование дискет +Name[rw]=Imiterere +Name[sk]=Formátovanie +Name[sl]=Formatiraj +Name[sr]=Форматирај +Name[sr@Latn]=Formatiraj +Name[tr]=Biçimlendir +Name[uk]=Форматування +Name[uz]=Formatlash +Name[uz@cyrillic]=Форматлаш +Name[wa]=Abwesner +Name[zh_CN]=格式化 +Name[zh_TW]=格式化 + +[Desktop Entry] +Actions=Format; +ServiceTypes=media/floppy_unmounted,media/floppy5_unmounted +X-KDE-Priority=TopLevel +X-KDE-MediaNotifierHide=true diff --git a/kfloppy/format.cpp b/kfloppy/format.cpp new file mode 100644 index 0000000..6d76de3 --- /dev/null +++ b/kfloppy/format.cpp @@ -0,0 +1,996 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 2002 Adriaan de Groot + Copyright (C) 2004, 2005 Nicolas GOUTTE + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "format.h" + +static QString extPath = QString::null; + +/* static */ QString findExecutable(const QString &e) +{ + if (extPath.isEmpty()) + { + QString path = getenv("PATH"); + if (!path.isEmpty()) path.append(":"); + path.append("/usr/sbin:/sbin"); + extPath = path; + } + + return KGlobal::dirs()->findExe(e, extPath); +} + + + +KFAction::KFAction(QObject *parent) : + QObject(parent) +{ + DEBUGSETUP; +} + +KFAction::~KFAction() +{ + DEBUGSETUP; + quit(); +} + +/* slot */ void KFAction::quit() +{ + DEBUGSETUP; +} + +/* slot */ void KFAction::exec() +{ + DEBUGSETUP; +} + +class KFActionQueue_p +{ +public: + QPtrList list; +} ; + +KFActionQueue::KFActionQueue(QObject *parent) : + KFAction(parent), + d(new KFActionQueue_p) +{ + DEBUGSETUP; + d->list.setAutoDelete(true); +} + +KFActionQueue::~KFActionQueue() +{ + DEBUGSETUP; + delete d; +} + +void KFActionQueue::queue(KFAction *p) +{ + DEBUGSETUP; + + d->list.append(p); + DEBUGS(p->name()); +} + +/* virtual */ void KFActionQueue::exec() +{ + DEBUGSETUP; + + actionDone(0L,true); +} + +/* slot */ void KFActionQueue::actionDone(KFAction *p,bool success) +{ + DEBUGSETUP; + + if (p) + { + if (d->list.first()==p) + { + d->list.removeFirst(); + // delete p; /* auto-delete */ + } + else + { + DEBUGS( "Strange pointer received."); + emit done(this,false); + return; + } + } + else + { + DEBUGS("Starting action queue."); + } + + if (!success) + { + DEBUGS("Action failed."); + emit done(this,false); + return; + } + + KFAction *next = d->list.first(); + if (!next) + { + emit done(this,true); + } + else + { + kdDebug(KFAREA) << "Running action " << next->name() << endl; + QObject::connect(next,SIGNAL(done(KFAction *,bool)), + this,SLOT(actionDone(KFAction *,bool))); + // Propagate signals + QObject::connect(next,SIGNAL(status(const QString &,int)), + this,SIGNAL(status(const QString &,int))); + QTimer::singleShot(0,next,SLOT(exec())); + } +} + + + + +// Here we have names of devices. The variable +// names are basically the linux device names, +// replace with whatever your OS needs instead. +// +// +#ifdef ANY_LINUX + +const char *fd0H1440[] = { "/dev/fd0u1440", "/dev/floppy/0u1440", "/dev/fd0h1440", "/dev/fd0H1440", "/dev/fd0", 0L } ; +const char *fd0D720[] = { "/dev/fd0u720", "/dev/floppy/0u720", "/dev/fd0D720", "/dev/fd0h720", "/dev/fd0", 0L }; +const char *fd0h1200[] = { "/dev/fd0h1200", "/dev/floppy/0h1200", "/dev/fd0", 0L }; +const char *fd0h360[] = { "/dev/fd0u360", "/dev/floppy/0u360", "/dev/fd0h360", "/dev/fd0d360", "/dev/fd0", 0L }; + +const char *fd1H1440[] = { "/dev/fd1u1440", "/dev/floppy/1u1440","/dev/fd1h1440", "/dev/fd1H1440", "/dev/fd1", 0L } ; +const char *fd1D720[] = { "/dev/fd1u720", "/dev/floppy/1u720", "/dev/fd1D720", "/dev/fd1h720", "/dev/fd1", 0L }; +const char *fd1h1200[] = { "/dev/fd1h1200", "/dev/floppy/1h1200", "/dev/fd1", 0L }; +const char *fd1h360[] = { "/dev/fd1u360", "/dev/floppy/1u360","/dev/fd1h360", "/dev/fd1d360", "/dev/fd1", 0L }; + +const char *fd0auto[] = { "/dev/fd0", 0L }; +const char *fd1auto[] = { "/dev/fd1", 0L }; + +#endif + + +#ifdef ANY_BSD +const char *fd0[] = { "/dev/fd0", 0L } ; +const char *fd1[] = { "/dev/fd1", 0L } ; +#endif + +// Next we have a table of device names and characteristics. +// These are ordered according to 2*densityIndex+deviceIndex, +// ie. primary (0) 1440K (0) is first, then secondary (1) 1440K is +// second, down to secondary (1) 360k (4) in position 3*2+1=7. +// +// +// Note that the data originally contained in KFloppy was +// patently false, so most of this is fake. I guess noone ever +// formatted a 5.25" floppy. +// +// The flags field is unused in this implementation. +// +// +fdinfo fdtable[] = +{ +#ifdef ANY_LINUX + // device drv blks trk flg + { fd0H1440, 0, 1440, 80, 0 }, + { fd1H1440, 1, 1440, 80, 0 }, + { fd0D720, 0, 720, 80, 0 }, + { fd1D720, 1, 720, 80, 0 }, + { fd0h1200, 0, 1200, 80, 0 }, + { fd1h1200, 1, 1200, 80, 0 }, + { fd0h360, 0, 360, 40, 0 }, + { fd1h360, 1, 360, 40, 0 }, + { fd0auto, 0, 0, 80, 0 }, + { fd1auto, 1, 0, 80, 0 }, +#endif + +#ifdef ANY_BSD + // Instead of the number of tracks, which is + // unneeded, we record the + // number of F's printed during an fdformat + { fd0, 0, 1440, 40, 0 }, + { fd1, 1, 1440, 40, 0 }, + { fd0, 0, 720, 40, 0 }, + { fd1, 1, 720, 40, 0 }, + { fd0, 0, 1200, 40, 0}, + { fd1, 1, 1200, 40, 0}, + { fd0, 0, 360, 40, 0}, + { fd1, 1, 360, 40, 0}, +#endif + { 0L, 0, 0, 0, 0 } +} ; + + +FloppyAction::FloppyAction(QObject *p) : + KFAction(p), + deviceInfo(0L), + theProcess(0L) +{ + DEBUGSETUP; +} + +void FloppyAction::quit() +{ + DEBUGSETUP; + delete theProcess; + theProcess=0L; + + KFAction::quit(); +} + +bool FloppyAction::configureDevice( const QString& newDeviceName ) +{ + deviceInfo = 0; // We have not any idea what the device is + deviceName = newDeviceName; + return true; // No problem! +} + +bool FloppyAction::configureDevice(int drive,int density) +{ + DEBUGSETUP; + const char *devicename = 0L; + + deviceInfo=0L; + deviceName = QString::null; + + if ((drive<0) || (drive>1)) + { + emit status(i18n("Unexpected drive number %1.").arg(drive),-1); + return false; + } + + fdinfo *deviceinfo = fdtable; + for ( ; deviceinfo && (deviceinfo->devices) ; deviceinfo++) + { + if (deviceinfo->blocks != density) + continue; + } + if (!deviceinfo) + { + emit status(i18n("Unexpected density number %1.").arg(density),-1); + return false; + } + + deviceinfo = fdtable; + for ( ; deviceinfo && (deviceinfo->devices) ; deviceinfo++) + { + if (deviceinfo->blocks != density) + continue; + if (deviceinfo->drive == drive) + break; + } + + if (!deviceinfo || !deviceinfo->devices) + { + emit status(i18n("Cannot find a device for drive %1 and density %2.") + .arg(drive).arg(density),-1); + return false; + } + + for (const char **devices=deviceinfo->devices ; + *devices ; devices++) + { + if (access(*devices,W_OK)>=0) + { + kdDebug(KFAREA) << "Found device " << *devices << endl; + devicename=*devices; + break; + } + } + + if (!devicename) + { + const QString str = i18n( + "Cannot access %1\nMake sure that the device exists and that " + "you have write permission to it.").arg(deviceinfo->devices[0]); + emit status(str,-1); + return false; + } + + deviceName = devicename; + deviceInfo = deviceinfo; + + return true; +} + +void FloppyAction::processDone(KProcess *p) +{ + DEBUGSETUP; + + if (p!=theProcess) + { + DEBUGS(" Strange process exited."); + return; + } + + if (p->normalExit()) + { + if (p->exitStatus() == 0) + { + emit status(QString::null,100); + emit done(this,true); + } + else + { + emit status(i18n("The program %1 terminated with an error.").arg(theProcessName),100); + emit done(this,false); + } + } + else + { + emit status(i18n("The program %1 terminated abnormally.").arg(theProcessName),100); + emit done(this,false); + } +} + +void FloppyAction::processStdOut(KProcess *, char *b, int l) +{ + Q_UNUSED(b); + Q_UNUSED(l); + kdDebug(KFAREA) << "stdout:" << QString::fromLatin1(b,l) << endl; +} + +void FloppyAction::processStdErr(KProcess *p, char *b, int l) +{ + processStdOut(p,b,l); +} + +bool FloppyAction::startProcess() +{ + DEBUGSETUP; + + connect(theProcess,SIGNAL(processExited(KProcess *)), + this,SLOT(processDone(KProcess *))); + connect(theProcess,SIGNAL(receivedStdout(KProcess *,char *,int)), + this,SLOT(processStdOut(KProcess *,char *,int))); + connect(theProcess,SIGNAL(receivedStderr(KProcess *,char *,int)), + this,SLOT(processStdErr(KProcess *,char *,int))); + + theProcess->setEnvironment( "LC_ALL", "C" ); // We need the untranslated output of the tool + return theProcess->start(KProcess::NotifyOnExit, + KProcess::AllOutput); +} + + +/* static */ QString FDFormat::fdformatName = QString::null; + +FDFormat::FDFormat(QObject *p) : + FloppyAction(p), + doVerify(true) +{ + DEBUGSETUP; + theProcessName = QString::fromLatin1("fdformat"); + setName("FDFormat"); +} + +/* static */ bool FDFormat::runtimeCheck() +{ + fdformatName = findExecutable("fdformat"); + return (!fdformatName.isEmpty()); +} + +bool FDFormat::configure(bool v) +{ + doVerify=v; + return true; +} + +/* virtual */ void FDFormat::exec() +{ + DEBUGSETUP; + + if ( !deviceInfo || deviceName.isEmpty() ) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done(this,false); + return; + } + + if (fdformatName.isEmpty()) + { + emit status(i18n("Cannot find fdformat."),-1); + emit done(this,false); + return; + } + + if (theProcess) delete theProcess; + theProcess = new KProcess; + + formatTrackCount=0; + + *theProcess << fdformatName ; + + // Common to Linux and BSD, others may differ + if (!doVerify) + { + *theProcess << "-n"; + } + +#ifdef ANY_BSD + *theProcess + << "-y" + << "-f" + << QString::number(deviceInfo->blocks) ; +#elif defined(ANY_LINUX) + // No Linux-specific flags +#endif + + // Common to Linux and BSD, others may differ + *theProcess << deviceName; + + if (!startProcess()) + { + emit status(i18n("Could not start fdformat."),-1); + emit done(this,false); + } + + // Now depend on fdformat running and producing output. +} + +// Parse some output from the fdformat process. Lots of +// #ifdefs here to account for variations in the basic +// fdformat. Uses gotos to branch to whatever error message we +// need, since the messages can be standardized across OSsen. +// +// +void FDFormat::processStdOut(KProcess *, char *b, int l) +{ + DEBUGSETUP; + QString s; + +#ifdef ANY_BSD + if (b[0]=='F') + { + formatTrackCount++; + emit status(QString::null, + formatTrackCount * 100 / deviceInfo->tracks); + } + else if (b[0]=='E') + { + emit status(i18n("Error formatting track %1.").arg(formatTrackCount),-1); + } + else + { + s = QString::fromLatin1(b,l); + if (s.contains("ioctl(FD_FORM)")) + { + emit status (i18n( + "Cannot access floppy or floppy drive.\n" + "Please insert a floppy and make sure that you " + "have selected a valid floppy drive."),-1); + return; + } + if (s.find("/dev/")>=0) + { + emit status(s,-1); + return; + } + DEBUGS(s); + } +#elif defined(ANY_LINUX) + s = QString::fromLatin1(b,l); + DEBUGS(s); + QRegExp regexp( "([0-9]+)" ); + if ( s.startsWith( "bad data at cyl" ) || ( s.find( "Problem reading cylinder" ) != -1 ) ) + { + if ( regexp.search( s ) > -1 ) + { + const int track = regexp.cap(1).toInt(); + emit status(i18n("Low-level formatting error at track %1.").arg(track), -1); + } + else + { + // This error should not happen + emit status(i18n("Low-level formatting error: %1").arg(s), -1); + } + return; + } + else if (s.find("ioctl(FDFMTBEG)")!=-1) + { + emit status (i18n( + "Cannot access floppy or floppy drive.\n" + "Please insert a floppy and make sure that you " + "have selected a valid floppy drive."),-1); + return; + } + else if (s.find("busy")!=-1) // "Device or resource busy" + { + emit status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."),-1); + return; + } + // Be careful to leave "iotcl" as last before checking numbers + else if (s.find("ioctl")!=-1) + { + emit status(i18n("Low-level format error: %1").arg(s),-1); + return; + } + // Check for numbers at last (as /dev/fd0u1440 has numbers too) + else if ( regexp.search(s) > -1 ) + { + // Normal track number (formatting or verifying) + const int p = regexp.cap(1).toInt(); + if ((p>=0) && (ptracks)) + { + emit status(QString::null, + p * 100 / deviceInfo->tracks); + } + } +#endif + return; +} + + +/* static */ QString DDZeroOut::m_ddName = QString::null; + +DDZeroOut::DDZeroOut(QObject *p) : + FloppyAction(p) +{ + kdDebug(KFAREA) << (__PRETTY_FUNCTION__) << endl; + theProcessName = QString::fromLatin1("dd"); + setName("DD"); +} + +/* static */ bool DDZeroOut::runtimeCheck() +{ + m_ddName = findExecutable("dd"); + return (!m_ddName.isEmpty()); +} + +/* virtual */ void DDZeroOut::exec() +{ + kdDebug(KFAREA) << (__PRETTY_FUNCTION__) << endl; + + if ( deviceName.isEmpty() ) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done( this, false ); + return; + } + + if ( m_ddName.isEmpty() ) + { + emit status( i18n("Cannot find dd."), -1 ); + emit done( this, false ); + return; + } + + delete theProcess; + theProcess = new KProcess; + + *theProcess << m_ddName ; + + *theProcess << "if=/dev/zero" ; + *theProcess << "of="+deviceName; + + if ( !startProcess() ) + { + emit status( i18n("Could not start dd."), -1 ); + emit done( this, false ); + } + +} + +void DDZeroOut::processDone(KProcess *p) +{ + kdDebug(KFAREA) << (__PRETTY_FUNCTION__) << endl; + + if (p!=theProcess) + { + kdDebug(KFAREA) << "Strange process exited." << endl; + return; + } + + /** + * As we do not give a number of blocks to dd(1), it will stop + * with the error "No space left on device" + * + * ### TODO: really check if the exit is not on an other error and then abort the formatting + */ + emit status(QString::null,100); + emit done(this,true); +} + + + +/* static */ QString FATFilesystem::newfs_fat = QString::null ; + +FATFilesystem::FATFilesystem(QObject *parent) : + FloppyAction(parent) +{ + DEBUGSETUP; + runtimeCheck(); + theProcessName=newfs_fat; + setName("FATFilesystem"); +} + +/* static */ bool FATFilesystem::runtimeCheck() +{ + DEBUGSETUP; + +#ifdef ANY_BSD + newfs_fat = findExecutable("newfs_msdos"); +#elif defined(ANY_LINUX) + newfs_fat = findExecutable("mkdosfs"); +#else + return false; +#endif + + return !newfs_fat.isEmpty(); +} + +bool FATFilesystem::configure(bool v,bool l,const QString &lbl) +{ + doVerify=v; + doLabel=l; + if (l) + label=lbl.simplifyWhiteSpace(); + else + label=QString::null; + + return true; +} + +void FATFilesystem::exec() +{ + DEBUGSETUP; + + + if ( +#ifdef ANY_BSD // BSD needs the deviceInfo for the block count + !deviceInfo || +#endif + deviceName.isEmpty()) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done(this,false); + return; + } + + if (newfs_fat.isEmpty()) + { + emit status(i18n("Cannot find a program to create FAT filesystems."),-1); + emit done(this,false); + return; + } + + if (theProcess) delete theProcess; + KProcess *p = theProcess = new KProcess; + + *p << newfs_fat; +#ifdef ANY_BSD + *p << "-f" << QString::number(deviceInfo->blocks); + if (doLabel) + { + *p << "-L" << label ; + } +#else +#ifdef ANY_LINUX + if (doLabel) + { + *p << "-n" << label ; + } + if (doVerify) + { + *p << "-c"; + } +#endif +#endif + *p << deviceName ; + + if (!startProcess()) + { + emit status(i18n("Cannot start FAT format program."),-1); + emit done(this,false); + } +} + +void FATFilesystem::processStdOut(KProcess *, char *b, int l) +{ +#ifdef ANY_BSD + // ### TODO: do some checks +#elif defined(ANY_LINUX) + QString s ( QString::fromLatin1( b, l ) ); + kdDebug(KFAREA) << s << endl; + if (s.find("mounted file system")!=-1) // "/dev/fd0 contains a mounted file system + { + emit status(i18n("Floppy is mounted.\nYou need to unmount the floppy first."),-1); + return; + } + else if (s.find("busy")!=-1) // "Device or resource busy" + { + emit status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."),-1); + return; + } +# if 0 + else if ( s.find( "mkdosfs" ) != -1 ) // DEBUG: get the program header and show it! + { + emit status( s, -1 ); + return; + } +# endif +#endif +} + + + + +#ifdef ANY_BSD + +/* static */ QString UFSFilesystem::newfs = QString::null ; + +UFSFilesystem::UFSFilesystem(QObject *parent) : + FloppyAction(parent) +{ + DEBUGSETUP; + runtimeCheck(); + theProcessName=newfs; + setName("UFSFilesystem"); +} + +/* static */ bool UFSFilesystem::runtimeCheck() +{ + DEBUGSETUP; + + newfs = findExecutable("newfs"); + + return !newfs.isEmpty(); +} + +void UFSFilesystem::exec() +{ + DEBUGSETUP; + + if ( deviceName.isEmpty() ) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done(this,false); + return; + } + + if (newfs.isEmpty()) + { + emit status(i18n("BSD", "Cannot find a program to create UFS filesystems."),-1); + emit done(this,false); + return; + } + + if (theProcess) delete theProcess; + KProcess *p = theProcess = new KProcess; + + *p << newfs; + + // ### TODO: is it still needed? (FreeBSD 5.3's man page says: "For backward compatibility.") + if ( deviceInfo ) + *p << "-T" << QString("fd%1").arg(deviceInfo->blocks); + + *p << deviceName; + + if (!startProcess()) + { + emit status(i18n("BSD", "Cannot start UFS format program."),-1); + emit done(this,false); + } +} +#endif + + + +/* static */ QString Ext2Filesystem::newfs = QString::null ; + +Ext2Filesystem::Ext2Filesystem(QObject *parent) : + FloppyAction(parent) +{ + DEBUGSETUP; + runtimeCheck(); + theProcessName="mke2fs"; + setName("Ext2Filesystem"); +} + +/* static */ bool Ext2Filesystem::runtimeCheck() +{ + DEBUGSETUP; + + newfs = findExecutable("mke2fs"); + + return !newfs.isEmpty(); +} + +bool Ext2Filesystem::configure(bool v,bool l,const QString &lbl) +{ + doVerify=v; + doLabel=l; + if (l) + { + label=lbl.stripWhiteSpace(); + } + else + { + label=QString::null; + } + + return true; +} + +void Ext2Filesystem::exec() +{ + DEBUGSETUP; + + if ( +#ifdef ANY_BSD // BSD needs the deviceInfo for the block count + !deviceInfo || +#endif + deviceName.isEmpty() ) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done(this,false); + return; + } + + if (newfs.isEmpty()) + { + emit status(i18n("Cannot find a program to create ext2 filesystems."),-1); + emit done(this,false); + return; + } + + if (theProcess) delete theProcess; + KProcess *p = theProcess = new KProcess; + + *p << newfs; + *p << "-q"; + if (doVerify) *p << "-c" ; + if (doLabel) *p << "-L" << label ; + + *p << deviceName ; + + if (!startProcess()) + { + emit status(i18n("Cannot start ext2 format program."),-1); + emit done(this,false); + } +} + +void Ext2Filesystem::processStdOut(KProcess *, char *b, int l) +{ +#ifdef ANY_BSD + // ### TODO: do some checks +#elif defined(ANY_LINUX) + QString s ( QString::fromLatin1( b, l ) ); + kdDebug(KFAREA) << s << endl; + if (s.find("mounted")!=-1) // "/dev/fd0 is mounted; will not make a filesystem here!" + { + emit status(i18n("Floppy is mounted.\nYou need to unmount the floppy first."),-1); + return; + } + else if (s.find("busy")!=-1) // "Device or resource busy" + { + emit status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."),-1); + return; + } +#endif +} + + + +#ifdef ANY_LINUX +/* static */ QString MinixFilesystem::newfs = QString::null ; + +MinixFilesystem::MinixFilesystem(QObject *parent) : + FloppyAction(parent) +{ + DEBUGSETUP; + runtimeCheck(); + theProcessName="mkfs.minix"; + setName("Minix2Filesystem"); +} + +/* static */ bool MinixFilesystem::runtimeCheck() +{ + DEBUGSETUP; + + newfs = findExecutable("mkfs.minix"); + + return !newfs.isEmpty(); +} + +bool MinixFilesystem::configure(bool v,bool l,const QString &lbl) +{ + doVerify=v; + doLabel=l; + if (l) + { + label=lbl.stripWhiteSpace(); + } + else + { + label=QString::null; + } + + return true; +} + +void MinixFilesystem::exec() +{ + DEBUGSETUP; + + if ( deviceName.isEmpty() ) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done(this,false); + return; + } + + if (newfs.isEmpty()) + { + emit status(i18n("Cannot find a program to create Minix filesystems."),-1); + emit done(this,false); + return; + } + + if (theProcess) delete theProcess; + KProcess *p = theProcess = new KProcess; + + *p << newfs; + + // Labeling is not possible + if (doVerify) *p << "-c" ; + + *p << deviceName ; + + if (!startProcess()) + { + emit status(i18n("Cannot start Minix format program."),-1); + emit done(this,false); + } +} + +void MinixFilesystem::processStdOut(KProcess *, char *b, int l) +{ + QString s ( QString::fromLatin1( b, l ) ); + kdDebug(KFAREA) << s << endl; + if (s.find("mounted")!=-1) // "mkfs.minix: /dev/fd0 is mounted; will not make a filesystem here!" + { + emit status(i18n("Floppy is mounted.\nYou need to unmount the floppy first."),-1); + return; + } + else if (s.find("busy")!=-1) // "Device or resource busy" + { + emit status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."),-1); + return; + } +} + +#endif + +#include "format.moc" diff --git a/kfloppy/format.h b/kfloppy/format.h new file mode 100644 index 0000000..0200d22 --- /dev/null +++ b/kfloppy/format.h @@ -0,0 +1,426 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 2002 Adriaan de Groot + Copyright (C) 2004, 2005 Nicolas GOUTTE + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef FORMAT_H +#define FORMAT_H + +/** \file format.h + * This file defines a hierarchy of classes that + * can run a sequence of external programs (like + * fdformat, mkisofs, etc.) in sequence. Stdout + * and stderr of those programs can be captured + * and analyzed in order to provide feedback to + * the user. + * + *
    + *
  • KFAction: Base class, just for performing some action. + *
  • KFActionQueue: Provides sequencing of KFActions + *
  • FloppyAction: Weird name; handles running a program, + * understands FD device names. This can be + * considered the "useful" base class of + * programming actions. + *
  • FDFormat: Runs fdformat(1) under BSD or Linux. + *
  • FATFilesystem: Creates an msdos (FAT) filesystem. + *
  • Ext2Filesystem: Creates ext2 filesystems. + *
  • MinixFilesystem: Creates Minix filesystems, under Linux. + *
  • UFSFilesystem: Creates UFS filesystem, under BSD. + *
+ * + * \note Maybe this is overkill, since for floppies all you need is + * fdformat(1) and some create-filesystem program like newfs(1) + * or mke2fs(1). However, for Zip disks, should they ever be supported, + * this is quite useful since you need to dd, fdisk, disklabel, and + * newfs them. +*/ + +#include "debug.h" +#include + +/** + * \brief Abstract base class of actions to be undertaken. + * + * Basically you can create a KFActionStack (See below) + * and push a bunch of actions on it, then run exec() + * on the stack and wait for the done() signal. +*/ +class KFAction : public QObject +{ +Q_OBJECT + +public: + KFAction(QObject *parent = 0L); + virtual ~KFAction(); + +public slots: + /** + * Exec() should return quickly to ensire that the GUI + * thread stays alive. quit() should abort the action. + */ + virtual void exec(); + /** + * Quit aborts the action. No done() signal should + * be emitted. + */ + virtual void quit(); + +signals: + /** + * done() should always be emitted with this as first + * parameter, to avoid sender() magic and the like. + * @p success indicates whether the action was + * successful. + */ + void done(KFAction *me,bool success); + + /** + * Emit this signal to inform the user of interesting + * changes; setting msg to an empty string doesn't + * change any visible user message. @p progress + * indicates the action's progress (if that can be determined) + * and sending -1 leaves the visible indicator unchanged. + */ + void status(const QString &msg, int progress); + + /** error() displays a box. It interrupts + * the user's work and should be used with care. + */ + void error(const QString &msg, const QString &details); +} ; + + +/** + * Acts as a queue and executes the actions in the + * queue in FIFO order. + */ +class KFActionQueue : public KFAction +{ +Q_OBJECT + +public: + KFActionQueue(QObject *parent = 0L); + virtual ~KFActionQueue(); + + /** + * Add a KFAction to the queue. When exec() is called, + * the actions are called one after the other (if each + * action is successful; if any action fails, the whole + * queue fails and the unsuccessful action is the last + * one run.) Actions become the property of the queue + * action. Note that queues can be nested. + */ + void queue(KFAction *); + + virtual void exec(); + +protected slots: + void actionDone(KFAction *,bool); + +private: + class KFActionQueue_p *d; +} ; + + +/* +** The remainder of the Actions are concrete ones and +** might better go off to live in another header file, +** but this is only needed if the number of supported +** formats grows enormously. +*/ + +/** + * Description structure for floppy devices. + * devices is a list of possible device names (yay + * /dev/ consistency) while drive,blocks denotes + * fd0 or fd1, and the size of the disk (ought to + * be 1440, 1200, 720 or 360. I've never seen a 2880 + * floppy drive). + * + * Tracks is pretty bogus; see the internal code for its use. + * Similarly, flags are internal too. + */ + +typedef struct { const char **devices; + int drive; + int blocks; + int tracks; + int flags; } fdinfo; + +class KProcess; + +/** + * Concrete action for running a single external program. + */ + +class FloppyAction : public KFAction +{ +Q_OBJECT + +public: + FloppyAction(QObject *parent = 0L); + + /** + * Kills the running process, if one exists. + */ + virtual void quit(); + + /** + * ConfigureDevice() needs to be called prior to exec() + * or exec() will fail; this indicates which drive and + * density to use. + * + * \param driveno Number of drive (0 or 1) + * \param density Floppy density (in Kilobytes) + * \note This same function needs to be + * called on all subclasses in order to configure them + * for which drive to use, _along_ with their local + * configuration functions. + */ + + bool configureDevice(int driveno, int density ); + + /** + * \brief Configure the device with a device name + * + * This is an alternate to FloppyAction::configureDevice + * for user-given devices. + * + * \note It does not work for each type of FloppyAction yet + */ + bool configureDevice( const QString& newDeviceName ); + +protected: + fdinfo *deviceInfo; ///< Configuration info (Pointer into list of "/dev/..." entries) + QString deviceName; ///< Name of the device + +protected slots: + /** + * \brief Provide handling of the exit of the external program + */ + virtual void processDone(KProcess *); + /** + * \brief Provide handling of stdout + */ + virtual void processStdOut(KProcess *, char *, int); + /** + * \brief Provide handling stderr. + * + * The default implementation just sends stderr on + * to processStdOut(), so you need reimplement only + * FloppyAction::processStdOut if you choose. + */ + virtual void processStdErr(KProcess *, char *, int); + +protected: + KProcess *theProcess; + QString theProcessName; ///< human-readable + + /** + * Sets up connections, calls KProcess::run(). + * You need to *theProcess << program << args ; first. + */ + + bool startProcess(); +} ; + +/** + * Concrete class that runs fdformat(1) + */ + +class FDFormat : public FloppyAction +{ +public: + FDFormat(QObject *parent = 0L); + + virtual void exec(); + + + /** + * Concrete classes can provide a runtimeCheck + * function (heck, this is static, so the name + * is up to you) that checks if the required + * applications are available. This way, the + * calling application can decide not to use + * actions whose prerequisites are absent anyway. + */ + static bool runtimeCheck(); + + /** @p verify instructs fdformat(1) to verify the + * medium as well. + */ + + bool configure(bool verify); + + virtual void processStdOut(KProcess *, char *,int); + +protected: + static QString fdformatName; ///< path to executable. + int formatTrackCount; ///< How many tracks formatted. + bool doVerify; +} ; + +/** + * Zero out disk by runnind dd(1) + * \bug As dd terminates with the error "No space left on device", KFloppy aborts + */ +class DDZeroOut : public FloppyAction +{ +public: + DDZeroOut(QObject *parent = 0L); + + virtual void exec(); + + /** + * Concrete classes can provide a runtimeCheck + * function (heck, this is static, so the name + * is up to you) that checks if the required + * applications are available. This way, the + * calling application can decide not to use + * actions whose prerequisites are absent anyway. + */ + static bool runtimeCheck(); + +protected: + /** + * \brief Provide handling of the exit of the external program + */ + virtual void processDone(KProcess *); +protected: + static QString m_ddName; ///< path to executable. +} ; + + +/** + * Create an msdos (FAT) filesystem on the floppy. + */ +class FATFilesystem : public FloppyAction +{ +public: + FATFilesystem(QObject *parent = 0L); + + virtual void exec(); + + static bool runtimeCheck(); + + /** + * newfs_msdos(1) doesn't support an additional verify, + * but Linux mkdosfs(1) does. Enable additional medium + * verify with @p verify. Disks can be labeled (@p label) with the + * remaining parameters (@p l). + */ + bool configure(bool verify, bool label, const QString &l); + + /// Parse output + virtual void processStdOut(KProcess*, char* b, int l); + +protected: + static QString newfs_fat; + + bool doVerify,doLabel; + QString label; + +} ; + +/** + * Format with Ext2 + */ +class Ext2Filesystem : public FloppyAction +{ +public: + Ext2Filesystem(QObject *parent = 0L); + + virtual void exec(); + + static bool runtimeCheck(); + + /// Same args as FATFilesystem::configure + bool configure(bool verify, bool label, const QString &l); + + /// Parse output + virtual void processStdOut(KProcess*, char* b, int l); + +protected: + static QString newfs; + + bool doVerify,doLabel; + QString label; +} ; + +#ifdef ANY_BSD + +/** + * \brief Format with UFS + * \note BSD only + */ +class UFSFilesystem : public FloppyAction +{ +public: + UFSFilesystem(QObject *parent = 0L); + + virtual void exec(); + + static bool runtimeCheck(); + +protected: + static QString newfs; + + bool doVerify,doLabel; + QString label; +} ; +#endif + +#ifdef ANY_LINUX +/** + * \brief Format with Minix + * \note Linux only + */ +class MinixFilesystem : public FloppyAction +{ +public: + MinixFilesystem(QObject *parent = 0L); + + virtual void exec(); + + static bool runtimeCheck(); + + /// Same args as FATFilesystem::configure + bool configure(bool verify, bool label, const QString &l); + + /// Parse output + virtual void processStdOut(KProcess*, char* b, int l); +protected: + static QString newfs; + + bool doVerify,doLabel; + QString label; +} ; +#endif + +/** + * Utility function that looks for executables in $PATH + * and in /sbin and /usr/sbin. + */ + +QString findExecutable(const QString &); + +#endif + diff --git a/kfloppy/hi128-app-kfloppy.png b/kfloppy/hi128-app-kfloppy.png new file mode 100644 index 0000000..ded3594 Binary files /dev/null and b/kfloppy/hi128-app-kfloppy.png differ diff --git a/kfloppy/hi16-app-kfloppy.png b/kfloppy/hi16-app-kfloppy.png new file mode 100644 index 0000000..3b272fb Binary files /dev/null and b/kfloppy/hi16-app-kfloppy.png differ diff --git a/kfloppy/hi22-app-kfloppy.png b/kfloppy/hi22-app-kfloppy.png new file mode 100644 index 0000000..c0b2fe3 Binary files /dev/null and b/kfloppy/hi22-app-kfloppy.png differ diff --git a/kfloppy/hi32-app-kfloppy.png b/kfloppy/hi32-app-kfloppy.png new file mode 100644 index 0000000..a1bfb30 Binary files /dev/null and b/kfloppy/hi32-app-kfloppy.png differ diff --git a/kfloppy/hi48-app-kfloppy.png b/kfloppy/hi48-app-kfloppy.png new file mode 100644 index 0000000..b53fc09 Binary files /dev/null and b/kfloppy/hi48-app-kfloppy.png differ diff --git a/kfloppy/hi64-app-kfloppy.png b/kfloppy/hi64-app-kfloppy.png new file mode 100644 index 0000000..c03b4b3 Binary files /dev/null and b/kfloppy/hi64-app-kfloppy.png differ diff --git a/kfloppy/main.cpp b/kfloppy/main.cpp new file mode 100644 index 0000000..f6aa98f --- /dev/null +++ b/kfloppy/main.cpp @@ -0,0 +1,79 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 1997 Bernd Johannes Wuebben + Copyright (C) 2004, 2005 Nicolas GOUTTE + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include +#include + +#include "floppy.h" + + +static const char description[] = + I18N_NOOP("KDE Floppy Disk Utility"); + +static const KCmdLineOptions options[] = +{ + { "+[device]", I18N_NOOP("Default device"), 0 }, + KCmdLineLastOption +}; + +int main( int argc, char *argv[] ) +{ + KAboutData aboutData("kfloppy", + I18N_NOOP("KFloppy"), + KDE_VERSION_STRING, description, KAboutData::License_GPL, + "(c) 1997, Bernd Johannes Wuebben\n" + "(c) 2001, Chris Howells\n" + "(c) 2002, Adriaan de Groot\n" + "(c) 2004, 2005, Nicolas Goutte", + I18N_NOOP("KFloppy helps you format floppies with the filesystem of your choice.") + ); + + aboutData.addAuthor("Bernd Johannes Wuebben", I18N_NOOP("Author and former maintainer"), "wuebben@kde.org"); + aboutData.addCredit("Chris Howells", I18N_NOOP("User interface re-design"), "howells@kde.org"); + aboutData.addCredit("Adriaan de Groot", I18N_NOOP("Add BSD support"), "groot@kde.org"); + aboutData.addCredit("Nicolas Goutte", I18N_NOOP("Make KFloppy work again for KDE 3.4"), "goutte@kde.org"); + + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + QString device; + if (args->count()) { + device = args->arg(0); + } + args->clear(); + + KApplication a; + + FloppyData* floppy = new FloppyData(); + a.setMainWidget(floppy); + bool autoformat = floppy->setInitialDevice(device); + floppy->show(); + if (autoformat) + floppy->format(); + return a.exec(); +} + diff --git a/kfloppy/zip.cpp b/kfloppy/zip.cpp new file mode 100644 index 0000000..8a0ff29 --- /dev/null +++ b/kfloppy/zip.cpp @@ -0,0 +1,305 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 2002 by Adriaan de Groot + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +#include +#include + +#include "debug.h" +#include "zip.moc" + +#include +#include +#include +#include + +#include +#include +#include + +ZipFormat::ZipFormat(QWidget *w,const char *n) : + DiskFormat(w,n), + zeroWholeDisk(0L), + p(0L), + formatStep(0), + statusTimer(0L) +{ + DEBUGSETUP; + + QGridLayout *grid = new QGridLayout(this,1,1,10); + + zeroWholeDisk = new QCheckBox(i18n("Zero entire disk"),this); + QWhatsThis::add(zeroWholeDisk, + i18n("Try to write zeroes to the entire disk " + "before adding a filesystem, in order " + "to check the disk's integrity.")); + grid->addWidget(zeroWholeDisk,0,0); + enableSoftUpdates = new QCheckBox(i18n("Enable softupdates"),this); + grid->addWidget(enableSoftUpdates,1,0); + + // Remember the stretch at the bottom to clear + // up layour problems when this widget is smaller + // than others in the stack. + // + grid->addRowSpacing(2,10); + grid->setRowStretch(2,100); + + endInit(); +} + +const char fslabel[] = I18N_NOOP("UFS Zip100"); + +FilesystemList ZipFormat::FSLabels() const +{ + FilesystemList l; + // THis isn't a basic format anywhere, I don't think. + l.append(new FilesystemData(i18n(fslabel),0xefc87329,(DiskFormat *)this)); + return l; +} + +/* static */ bool ZipFormat::runtimeCheck() +{ + DEBUGSETUP; + dd = findExecutable("dd"); + newfs = findExecutable("newfs"); + return !newfs.isEmpty() && !dd.isEmpty(); +} + +/* static */ QString ZipFormat::dd; +/* static */ QString ZipFormat::newfs; + +/* virtual slot */ void ZipFormat::setEnabled(bool b) +{ + zeroWholeDisk->setEnabled(b); + enableSoftUpdates->setEnabled(b); +} + +/* virtual */ void ZipFormat::readSettings(KConfig *c) +{ + c->setGroup(fslabel); + zeroWholeDisk->setChecked( + c->readBoolEntry("ZeroDisk",false)); + enableSoftUpdates->setChecked( + c->readBoolEntry("SoftUpdates",false)); +} + +/* virtual */ void ZipFormat::writeSettings(KConfig *c) +{ + c->setGroup(fslabel); + c->writeEntry("ZeroDisk",zeroWholeDisk->isChecked()); + c->writeEntry("SoftUpdates",enableSoftUpdates->isChecked()); +} + +void ZipFormat::quit() +{ + DEBUGSETUP; + if (p) delete p; + if (statusTimer) delete statusTimer; + + p=0L; + statusTimer=0L; +} + +/* virtual slot */ void ZipFormat::format(FilesystemData *f) +{ + DEBUGSETUP; + + if (f->magic()!=0xefc87329) + { + complainAboutFormat(f); + return; + } + + formatStep=0; + + if (p) delete p; + p = new KProcess(); + + if (statusTimer) delete statusTimer; + statusTimer = new QTimer(this); + + connect(p,SIGNAL(processExited(KProcess *)), + this,SLOT(transition())); + connect(p,SIGNAL(receivedStdout(KProcess *,char *,int)), + this,SLOT(processResult(KProcess *,char *,int))); + connect(p,SIGNAL(receivedStderr(KProcess *,char *,int)), + this,SLOT(processResult(KProcess *,char *,int))); + connect(statusTimer,SIGNAL(timeout()), + this,SLOT(statusRequest())); + + transition(); +} + +void ZipFormat::transition() +{ + DEBUGSETUP; + + switch(formatStep) + { + case 0 : + // We're using a larger block size to speed up writing. + // So instead of 196608 blocks of 512b, use 12288 blocks + // of 8k instead. + // + // For newfs we need to set the real number of blocks. + // + if (zeroWholeDisk->isChecked()) + { + // Zeroing whole disk takes about 2 min. + // No point in making a dizzy display of it. + statusTimer->start(10000); + QTimer::singleShot(1000,this, + SLOT(statusRequest())); + totalBlocks=12288; // 196608 * 512b = 12288 * 8192b ; + } + else + { + // Takes about 5 seconds. + statusTimer->start(1000); + totalBlocks=100; + } + + *p << dd + << "if=/dev/zero" + << "of=/dev/afd0c" + << "bs=8192" ; + *p << QString("count=%1").arg(totalBlocks); + if (!p->start(KProcess::NotifyOnExit,KProcess::AllOutput)) + { + emit statusMessage(i18n("Cannot start dd to zero disk.")); + emit formatDone(-1); + delete statusTimer; + delete p; + statusTimer=0L; + p=0L; + return; + } + + formatStep=1; + emit statusMessage(i18n("Zeroing disk...")); + break; + case 1 : + statusTimer->stop(); + // The dd for zeroing the disk has finished. + if (p->exitStatus()) + { + emit statusMessage(i18n("Zeroing disk failed.")); + emit formatDone(-1); + return; + } + + totalBlocks=196608; // Now use the real number of 512b blocks + + p->clearArguments(); + *p << newfs << "-T" << "zip100" ; + if (enableSoftUpdates->isChecked()) + { + *p << "-U" ; + } + *p << "/dev/afd0c" ; + if (!p->start(KProcess::NotifyOnExit,KProcess::AllOutput)) + { + emit statusMessage(i18n("Cannot start newfs.")); + emit formatDone(-1); + }; + formatStep=2; + emit statusMessage(i18n("Making filesystem...")); + break; + case 2 : + if (p->exitStatus()) + { + emit statusMessage(i18n("newfs failed.")); + emit formatDone(-1); + } + else + { + emit statusMessage(i18n("Disk formatted successfully.")); + emit formatDone(0); + } + break; + } +} + +void ZipFormat::processResult(KProcess *, char *b, int l) +{ + DEBUGSETUP; + +#ifdef DEBUG + QString o = QString::fromLatin1(b,l); + DEBUGS(QString(" %1").arg(o).latin1()); +#endif + + switch(formatStep) + { + case 1 : // These are messages from dd + if (strchr(b,'+')) + { + int currentblock=atoi(b); + emit setProgress(currentblock*100/totalBlocks); + if (totalBlocks>10000) + { + emit statusMessage(i18n("Zeroing block %1 of %2...") + .arg(currentblock) + .arg(totalBlocks)); + } + } + break; + case 2 : // These are messages from newfs + if ((b[0]==' ') && isdigit(b[1])) + { + int currentblock=atoi(b+1); + emit setProgress(currentblock*100/totalBlocks); + } + else + { + // This is the initial display message from + // newfs. It writes a first block to sector 32. + // + // + emit setProgress(1); + + // QString myBuf = QString::fromLatin1(b, l); + // DEBUGS(myBuf.latin1()); + } + break; + } +} + +void ZipFormat::statusRequest() +{ + if (formatStep!=1) // Not in dd mode? + return; + if (!p) // How can that happen? + return; + +#ifdef ANY_BSD + p->kill(SIGINFO); +#endif +} + + diff --git a/kfloppy/zip.h b/kfloppy/zip.h new file mode 100644 index 0000000..0054c50 --- /dev/null +++ b/kfloppy/zip.h @@ -0,0 +1,106 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 2002 by Adriaan de Groot + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#ifndef _ZIP_FORMAT_H +#define _ZIP_FORMAT_H + +/** + * \file zip.h + * + * This file defines the ZipFormat class, a DiskFormat + * for KFloppy that deals with Zip disks and UFS under + * FreeBSD (and probably other BSD's, as well). + * + * \todo Add device selector to zip class + * \note This class is not used by KFloppy + * \bug This class assumes thatthe Zip disk has 100MB. It does not support 250MB and 750MB + */ + +#include "format.h" + +class QCheckBox; +class QTimer; +class KProcess; +class KConfig; + +class ZipFormat : public DiskFormat +{ +Q_OBJECT + +public: + ZipFormat(QWidget *w, const char *n); + + // All the virtuals we need to make + // a concrete DiskFormat class. See + // format.h for details. + // + virtual FilesystemList FSLabels() const; + virtual void setEnabled(bool); + virtual void format(FilesystemData *); + virtual void quit(); + virtual void readSettings(KConfig *); + virtual void writeSettings(KConfig *); + + /** Check for dd and newfs, which we + * need to do the formatting. + */ + static bool runtimeCheck(); + +protected: + QCheckBox *zeroWholeDisk; + QCheckBox *enableSoftUpdates; + + static QString newfs,dd; + + KProcess *p; ///< dd or newfs, doing the real work + int formatStep; ///< keeps track of what phase we are in + + // Variables for the zeroing phase + int totalBlocks; + QTimer *statusTimer; + +protected slots: + /** + * transition() realises the state machine we use + * to handle the different phases of the format: + * startup, dd and newfs. + */ + void transition(); + + /** + * processResult() reads output + * from either dd or newfs and interprets it. + */ + void processResult(KProcess *,char *,int); + + /** + *statusRequest() + * sends dd a SIGINFO to get it to print out block counts, + * which then triggers processResult() so that we can keep + * the progress bar moving. + */ + void statusRequest(); +}; + +#endif diff --git a/kgpg/AUTHORS b/kgpg/AUTHORS new file mode 100644 index 0000000..32f771a --- /dev/null +++ b/kgpg/AUTHORS @@ -0,0 +1 @@ +y0k0 diff --git a/kgpg/ChangeLog b/kgpg/ChangeLog new file mode 100644 index 0000000..7cf0cf2 --- /dev/null +++ b/kgpg/ChangeLog @@ -0,0 +1,310 @@ +Version 1.2.1 + +Bugfixes: +-Don't crash on keyserver operation +-Don't mix gpg output comments in decrypted text +-Disabling/enabling a key now works +-Fix some UTF-8 issues +-Setting Trust now works correctly + + +Version 1.2 + +-You can now choose encoding when saving/loading text in editor +-New option to hide/show expired/disabled keys in key manager +-Add color for revoked keys +-Make colors configurable +-Rewrote text signing and decryption processes. +-User can now choose the left click behaviour (open key manager or editor) +-Fixed bug in text encryption (gpg errors were included in encrypted text) +-System tray icon animates itself when KGpg is processing a task +-Added a Tooltip to applet's icon to say if KGpg is busy and what it is doing +-shredding doesn't freeze the ui anymore +-encrypting several files now processes one file after another instead of all at once, keeping the interface much more responsive +-verifying a signed text now tells if the key is trusted or not +-multi file decryption now works +-dropping a signed text over the applet automatically verfies it +-If there is a public key in clipboard, trying to decrypt it asks if user wants to import it +-Can now change the editor font +-Can now store more than 3 keyservers +-added sign clipboard +-added incremental search line in Key Manager and Public Key selection dialog +-allow selecting several key for import in the search results of key server operation +-added entry to open editor from key manager +-fixed popup never disappearing when a wrong passphrase was entered 3 times. +-fixed "import missing key" always disabled with non english languages +-comments exported in public keys should be fixed (I cannot reproduce) +-added statusbar with feedback info + + +Version 1.1 + +-photo id's are now displayed inside the key list view +-support for multiple photo id's +-fixed bug hiding key when user answered no to delete secret key +-improved feedback on key creation +-added select all action to kgpg editor +-fixed utf8 problem with some key names +-fixed problem with quotes when signing from the editor +-revocation certificate: create & print +-animated logo while key creation is in progress +-added a search function to find a key in the keyring +-splitted email & key name in two different columns for easier sorting +-folder encryption (initial support) +-integrate KAddress Book facilities (export key to address book) +-key import gives more infos +-use of gpg-agent can be enabled/disabled from settings dialog +-fixed message after exporting a key to keyserver +-changed default keyservers +-rewrote settings dialog to use kautoconfigdialog +-key signing now lets you select how carefully you checked that the key really belongs to the person +-improved keyserver operations +-when verifying a text/file and signature is missing, ask user to import missing key from keyserver +-new in keymanager: import missing signatures +-changed applet behaviour to follow KDE ui styleguides +-default key & keyserver are now stored in gpg's configuration file. +-moved keyserver management into Kgpg's configuration dialog +-added checkbox to stop asking autostart when user closes kgpg +-added multi file encryption +-toolbar in key manager can now be configured +-added gpg-agent support +-speed up key manager +-fix display of keys with local characters encodings +-added trust color to keymanager +-added option to save files as .pgp instead of .gpg +-new key properties dialog, allows to change expiration, ownertrust, passphrase +-allow multi key operations in keymanager: deleting, exporting and signing of several keys at once is now possible + + +Version 1.0.0 +-fixed message box when verifying a signature with a non english gpg +-only one key manager can now be opened (Olivier Goffart) +-fixed orphaned gpg threads when opening private key selection dialog +-fixed crash on remote file drops +-added warning on remote file decryption +-fix decryption of non ascii armored files in kgpg's editor +-fix deletion of temporary files created when dropping remote files in KGpg +-added honor-http-proxy to keyserver dialog to allow passing through firewalls (Fabian Wenzel <f.wenzel@gmx.net>) + +version 0.9.5 +-added keyboard shortcuts to key manager +-added popup dialog indicating that a file en/decryption is in progress +-added "on the fly" custom option for encryption +-rewrote & improved (speed, security) enc/decryption/signing functions +-fixed bugs in keyserver searching (display of mail adresses, command lines interpreted as keys) +-rearranged option dialog +-fixed special characters problem in key generation wizard +-fixed bug preventing servicemenus to appear on some systems +-when encryption/decryption fails, you can now see the log output in an error box +-fixed problem when opening a public key +-hide expired secret keys from encryption/signing selection dialog +-new icons based on icons from malte_gell@t-online.de (Malte Gell) +-many small GUI improvements +-kgpg has now been turned to a system tray applet + + +version 0.9.4 + +-fixed crash when decrypting from Kgpg's editor file menu +-added GUI keyserver support (manage keyserver, key import/export/search) +-show photo/toolbar in key manager is now saved & restored +-new command line mode to open keyserver dialog +-fixed problems with keys having no e-mail adress +-new button to show/hide options in the key selection dialog +-added gpg option to hide user id in encrypted blocks +-fixed small bug preventing key generation with expiration date in years + +version 0.9.3 + +-automatic mimetype detection & installation (for encrypted files and signature files) +-new in options dialog: easy install/remove of service menus to sign / decrypt a file +-new command line mode to verify a signature: Left click on a .sig file to check signature validity +-fixed clipboard encryption +-disabled html display in Kgpg's editor +-a few small bugfixes +-password length for a new key must now be greater than 5 characters. +-in decryption dialog, password only ask for keys for which you have a secret key. +-fixed error message appearing when encryption was successful +-fixed key export (export failed in some cases) + +version 0.9.2 + +-fixed bug preventing encryption when several options were checked +-fixed signing of keys whith expiration date +-some keys (created with pgp 7.x) were not displayed in Key manager. fixed +-added new config options: add/remove decrypt menu, choose between displaying E-Mail or Key name first in lists + +version 0.9.1.1 + +-fixed bug preventing correct encryption of texts with " (Olivier Goffart <ogoffart@tiscalinet.be>) + +version 0.9.1 + +-compilation fixes +-corrected file extension with ASCII encryption (now is .asc) +-Kgpg now listens to GnuPG's status messages, which greatly improves reliability +-signing keys and signature deletion can now be performed through GUI +-Drag & Drop support in key manager: drop a key to import, drag a key into a text editor or on your desktop to export +-Support for Photo ID +-now displays signatures revocation certificates +-many small improvements/fixes +-fixed bug preventing secret key export + +version 0.9 + +-fixed security bug in key generation wizard +-fixed detection of file shredding results +-rewrote key manager & key selection dialog +-MD5 sum checking rewritten for easier use +-centralised all encrypt/decrypt functions into one library file (kgpginterface) for easy reuse +-fixed bug with filenames containing whitespaces +-key manager can now be used as a standalone application +-added new -s 'filename' option on command line to decrypt a file & open it in kgpg +-added italian translation + +version 0.8.2 + +-fixed debian rules permissions +-fixed makefile for installation in a user chosen directory + +version 0.8.1 + +-fixed compilation bug + +version 0.8 + +-i18n fixes +-added option to send key by e-mail in export key dialog +-added new option to easily decrypt clipboard content -> kgpg can be added as a + klipper action (see kgpg's handbook for more infos about activating this option) +-added support for symetrical encryption for files +-corrected bug when kgpg was called from konqueror (when left-clicking on a gpg file, + kgpg did not always close itself correctly after file decryption) +-removed "decrypt file" entry in konqueror service menu. Now, use left-click or "Open + with kgpg" on an encrypted file to decrypt. +-added a Handbook (documentation) +-fixed Makefile + added files for debian compilation (thanks Ralf Nolden <nolden@kde.org>) +-added option to Edit a key (console mode) in key management +-added a link to GnuPG man page in help menu + +version 0.7: + +-fixed tips database installation (hopefully) +-pgp compatibility: --pgp6 is now used if gpg version>=1.2.0 +-code cleanup +-many small usability bugfixes +-added "sign/verify" button to clearsign/verify a text in the editor +-corrected lots of bugs in the way "new file", "save" and "save as" behaved +-added "save as" icon in toolbar +-switched display of key id's to short id's for more convenience +-only trusted keys can now be set to default key + + +version 0.6.1: + +-corrected a compilation problem with KDE prior to KDE 3.1 beta + + +version 0.6: + +-default key is now in bold +-signing a key now asks if you want your signature to be exportable +-md5 checksum now uses gpg instead of md5sum +-key info now tells if a signature is local or not, and if there is a subkey +-new encryption option for pgp 5.x compatibility +-various crash fixes (mostly related to the default options dialog) +-new dialog for key generation, automatically pops up on first run if no key is found. +-made ready for internationalization. added french & german translation (courtesty Christoph +Thielecke <crissi99@gmx.de> +-added KTips + +version 0.5.1 + +-fixed bug preventing secret key import +-fixed messy code preventing key signing + + +version 0.5 + +-fixed possible crash with key names containing "pub" +-default keys are now displayed with a red icon +-expired/revoked key are now hidden from encryption dialog +-untrusted keys are now hidden when required +-added new configuration icon +-most key operation are now based on key id and not on email adress, which should solve problems +with same name keys + + +version 0.4.3 + +-speed improvements +-encryption/decryption from konqueror is more straightforward +-ability to define special key for file encryption +-enable default key definition to ensure messages are also encrypted with your key +-you now have 3 trials in case you type a wrong passphrase +-fixed possible crash when no key selected for encryption +-fixed multi key encryption bug +-added what's this help texts in main dialogs + + +version 0.4.2 + +-you can now choose location to export a public key +-key management window now displays the key owner name in statusbar +-key info now displays key type (RSA, DSA, ...) +-fixed crash when decrypting message encrypted with several keys +-allow encryption with multiple keys + +version 0.4.1: + +-Bugfix release: +-corrected error when encrypting a text with "$" from the editor +-refresh key list after key generation +-you can now choose a location for decrypting a file + +version 0.4 + +-Big changes: +-kgpg can now be used from inside konqueror using a new menu entry allowing you to encrypt/decrypt +files. +-dropped file mode. All file operations can now be performed through konqueror +-a few minor improvements & code cleaning + + +version 0.3.1 +-Added option to shred source file after encryption +-File signature options: Create a detached signature, verify a signed file, checking file MD5 sum +-added icons in keys lists, toolbar & popup menu in key management window. +-export secret key + + +version 0.3 +-Drag&drop now works !!! You can drop local or REMOTE text files in the editor to have them +decrypted automatically +-More infos on keys: now displays key signatures, key ID,... +-New key managment features: enables you to sign keys and generate new keys. +-Some minor improvements +-New icon + +version 0.2.1 + +-In the file browser, you can now double click on a file to encrypt/decrypt it +-You can drag a file in the editor window to open/decrypt it +-Now displays keys trust and validity +-New option to allow encryption with untrusted keys +-Choose if you want armored encryption or not +-Export your public keys +-And many small interface improvements + +version 0.2 + +-Completeley rewrote GUI +-bugfix for messages > 130 characters +-added import/delete keys +-new file mode to encrypt/decrypt files +-ability to open/save files from the editor + + +version 0.1 + +-initial release diff --git a/kgpg/INSTALL b/kgpg/INSTALL new file mode 100644 index 0000000..f895580 --- /dev/null +++ b/kgpg/INSTALL @@ -0,0 +1,160 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code + 2. ./configure + 3. make + 4. make install (as root) + +To uninstall: make uninstall + +You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/kgpg/Makefile.am b/kgpg/Makefile.am new file mode 100644 index 0000000..6b1628d --- /dev/null +++ b/kgpg/Makefile.am @@ -0,0 +1,46 @@ +SUBDIRS = icons +bin_PROGRAMS = kgpg + +## INCLUDES were found outside kdevelop specific part + +INCLUDES = $(all_includes) + +kgpg_SOURCES = kgpgoptions.cpp listkeys.cpp popuppublic.cpp kgpgview.cpp \ + kgpg.cpp main.cpp keygener.cpp kgpginterface.cpp keyservers.cpp keyserver.ui \ + searchres.ui kgpgeditor.cpp detailedconsole.cpp kgpglibrary.cpp kgpgwizard.ui \ + keyproperties.ui conf_encryption.ui conf_decryption.ui conf_gpg.ui dcopiface.skel \ + keyinfowidget.cpp groupedit.ui kgpgrevokewidget.ui newkey.ui adduid.ui keyexport.ui \ + sourceselect.ui kgpgsettings.kcfgc conf_servers.ui conf_ui2.ui conf_misc.ui +kgpg_LDADD = $(LIB_KIO) $(LIB_KABC) -lkutils -lkdeprint + +pics_DATA= kgpg_anim.gif kgpg_docked.png kgpg_docked.gif kgpg_blank.png kgpg_fill.png +picsdir=$(kde_datadir)/kgpg/pics + +servicedir = $(kde_datadir)/konqueror/servicemenus +service_DATA = encryptfile.desktop encryptfolder.desktop + +autostartdir = $(datadir)/autostart +autostart_DATA = kgpg.desktop + +xdg_apps_DATA = kgpg.desktop +kde_kcfg_DATA = kgpg.kcfg + +METASOURCES = AUTO + +# the library search path. +kgpg_LDFLAGS = $(all_libraries) $(KDE_RPATH) + +appsdir = $(kde_datadir)/kgpg +apps_DATA = kgpg.rc listkeys.rc tips + +KDE_ICON = kgpg + +messages: rc.cpp + $(PREPARETIPS) > tips.cpp + LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \ + if test -n "$$LIST"; then \ + $(XGETTEXT) $$LIST -o $(podir)/kgpg.pot; \ + fi + rm -f tips.cpp + + diff --git a/kgpg/adduid.ui b/kgpg/adduid.ui new file mode 100644 index 0000000..b7e5b1b --- /dev/null +++ b/kgpg/adduid.ui @@ -0,0 +1,64 @@ + +AddUid + + + AddUid + + + + 0 + 0 + 357 + 170 + + + + + unnamed + + + 0 + + + + kLineEdit1 + + + + + kLineEdit2 + + + + + kLineEdit3 + + + + + textLabel1 + + + Name (minimum 5 characters): + + + + + textLabel2 + + + Email: + + + + + textLabel3 + + + Comment (optional): + + + + + + diff --git a/kgpg/conf_decryption.ui b/kgpg/conf_decryption.ui new file mode 100644 index 0000000..bec30e9 --- /dev/null +++ b/kgpg/conf_decryption.ui @@ -0,0 +1,69 @@ + +Decryption + + + Decryption + + + + 0 + 0 + 388 + 233 + + + + + + + + unnamed + + + 0 + + + + kcfg_CustomDecrypt + + + true + + + + + spacer3_2 + + + Vertical + + + Expanding + + + + 21 + 155 + + + + + + textLabel1_4_2 + + + Custom decryption command: + + + <qt><b>Custom Decryption Command:</b><br /> + <p>This option allows the user to specify a custom command to be executed by GPG when decryption occurs. (This is recommended for advanced users only).</p> + </qt> + + + + + + use_agent_toggled( bool isOn ) + + + diff --git a/kgpg/conf_encryption.ui b/kgpg/conf_encryption.ui new file mode 100644 index 0000000..c4d9f7f --- /dev/null +++ b/kgpg/conf_encryption.ui @@ -0,0 +1,321 @@ + +Encryption +bj@altern.org + + + Encryption + + + + 0 + 0 + 538 + 389 + + + + Encryption + + + + unnamed + + + 0 + + + + kcfg_PgpCompatibility + + + PGP 6 compatibility + + + Alt+6 + + + <qt><b>PGP 6 compatibility:</b><br /> + <p>Checking this option forces GnuPG to output encrypted packets that are as compliant with PGP (Pretty Good Privacy) 6 standards as possible thus allowing GnuPG users to inter operate with PGP 6 users.</p></qt> + + + + + kcfg_AsciiArmor + + + + 0 + 0 + + + + ASCII armored encryption + + + <qt><b>ASCII armored encryption:</b> <br /> + <p>Checking this option outputs all encrypted files in a format that can be opened by a text editor and as such the output is suitable for placing in the body of an e-mail message.</p></qt> + + + + + kcfg_HideUserID + + + Hide user id + + + <qt><b>Hide user ID:</b><br /> + <p>Checking this option will remove the keyid of the recipient from all encrypted packets. The advantage: traffic analysis of the encrypted packets cannot be performed as easily because the recipient is unknown. The disadvantage: the receiver of the encrypted packets is forced to try all secret keys before being able to decrypt the packets. This can be a lengthy process depending on the number of secret keys the receiver holds.</p></qt> + + + + + kcfg_ShredSource + + + Shred source file + + + <qt><b>Shred source file:</b><br /> + <p>Checking this option will shred (overwrite several times before erasing) the files you have encrypted. This way, it is almost impossible that the source file is recovered. But <b>you must be aware that this is not 100% secure</b> on all file systems, and that parts of the file may have been saved in a temporary file or in the spooler of your printer if you previously opened it in an editor or tried to print it. Only works on files (not on folders).</p></qt> + + + + + kcfg_AllowUntrustedKeys + + + Allow encryption with untrusted keys + + + <qt><b>Allow encryption with untrusted keys:</b> <br /> + <p>When importing a public key, the key is usually marked as untrusted and as such cannot be used unless it is signed by the default key (Thus, making it 'trusted'). Checking this box enables any key to be used even if it is untrusted.</p></qt> + + + + + spacer7 + + + Vertical + + + Expanding + + + + 20 + 72 + + + + + + layout3 + + + + unnamed + + + + kcfg_AllowCustomEncryptionOptions + + + + 0 + 0 + 0 + 0 + + + + Custom encryption command: + + + <qt><b>Custom encryption command:</b> <br /> + <p>When activated, an entry field will be shown in the key selection dialog, enabling you to enter a custom command for encryption. This option is recommended for experienced users only.</p></qt> + + + + + kcfg_CustomEncryptionOptions + + + false + + + + 3 + 0 + 0 + 0 + + + + + + + + kcfg_PgpExtension + + + Use *.pgp extension for encrypted files + + + <qt><b>Use *.pgp extension for encrypted files:</b><br /> + <p>Checking this option will append a .pgp extension to all encrypted files instead of a .gpg extension. This option will maintain compatibility with users of PGP (Pretty Good Privacy) software.</p></qt> + + + + + textLabel1 + + + Encrypt files with: + + + + + kcfg_FileKey + + + Panel + + + 1 + + + true + + + <qt><b>Encrypt files with:</b><br /> +<p>Checking this option and selecting a key will force any file encryption operation to use the selected key. KGpg will not query for a recipient and the default key will be bypassed.</p></qt> + + + + + clear_fkey + + + + 0 + 1 + 0 + 0 + + + + ... + + + + + change_fkey + + + + 0 + 1 + 0 + 0 + + + + Change... + + + + + textLabel1_2 + + + Always encrypt with: + + + + + alwaysKey + + + Panel + + + 1 + + + true + + + <qt><b>Always encrypt with:</b><br /> +<p>This ensures all files/messages will also be encrypted with the chosen key. However, if the "Encrypt files with:" option is selected that chosen key will override the "Always encrypt with:" selection.</p></qt> + + + + + change_akey + + + + 0 + 1 + 0 + 0 + + + + Change... + + + + + clear_akey + + + + 0 + 1 + 0 + 0 + + + + ... + + + + + + + kcfg_AllowCustomEncryptionOptions + toggled(bool) + Encryption + allow_custom_option_toggled(bool) + + + + kcfg_AsciiArmor + kcfg_AllowUntrustedKeys + kcfg_PgpCompatibility + kcfg_HideUserID + kcfg_ShredSource + alwaysKey + change_akey + kcfg_FileKey + change_fkey + kcfg_AllowCustomEncryptionOptions + kcfg_CustomEncryptionOptions + kcfg_PgpExtension + + + conf_encryption.ui.h + + + allow_custom_option_toggled( bool isOn ) + + + + klineedit.h + kpushbutton.h + + diff --git a/kgpg/conf_encryption.ui.h b/kgpg/conf_encryption.ui.h new file mode 100644 index 0000000..15310b6 --- /dev/null +++ b/kgpg/conf_encryption.ui.h @@ -0,0 +1,22 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ + + +void Encryption::allow_custom_option_toggled( bool isOn) +{ +kcfg_CustomEncryptionOptions->setEnabled(isOn); +} diff --git a/kgpg/conf_gpg.ui b/kgpg/conf_gpg.ui new file mode 100644 index 0000000..9cbf931 --- /dev/null +++ b/kgpg/conf_gpg.ui @@ -0,0 +1,219 @@ + +GPGConf + + + GPGConf + + + + 0 + 0 + 550 + 315 + + + + <qt><b>Global Settings:</b><br /> + <p></p> + </qt> + + + + unnamed + + + 0 + + + + groupBox2 + + + GnuPG Home + + + + unnamed + + + + textLabel1_5_2 + + + Configuration file: + + + + + textLabel1_5_2_2 + + + Home location: + + + + + gpg_conf_path + + + true + + + Panel + + + 1 + + + true + + + + + changeHome + + + Change... + + + + + gpg_home_path + + + true + + + Panel + + + 1 + + + true + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 190 + 20 + + + + + + + + spacer5 + + + Vertical + + + Expanding + + + + 21 + 54 + + + + + + use_agent + + + &Use GnuPG agent + + + + + groupBox2_2 + + + Additional Keyring + + + + unnamed + + + + kcfg_PubKeyring + + + Pu&blic: + + + + + kcfg_PrivKeyring + + + Private: + + + + + layout1 + + + + unnamed + + + + kcfg_PubKeyringUrl + + + false + + + + + kcfg_PrivKeyringUrl + + + false + + + + + + + kcfg_OnlyAdditional + + + false + + + Use only this keyring + + + + + + + + + klineedit.h + klineedit.h + kurlrequester.h + klineedit.h + kpushbutton.h + kurlrequester.h + klineedit.h + kpushbutton.h + + diff --git a/kgpg/conf_misc.ui b/kgpg/conf_misc.ui new file mode 100644 index 0000000..bfeb9c8 --- /dev/null +++ b/kgpg/conf_misc.ui @@ -0,0 +1,413 @@ + +MiscConf + + + MiscConf + + + + 0 + 0 + 454 + 334 + + + + + unnamed + + + 0 + + + + miscWidget + + + + tab + + + Global Settings + + + + unnamed + + + + kcfg_AutoStart + + + Start KGpg automatically at login + + + false + + + <qt><b>Start KGpg automatically at KDE startup:</b><br /> +<p>If checked KGpg will start automatically each time that KDE starts up.</p></qt> + + + + + kcfg_UseMouseSelection + + + + 0 + 0 + + + + Use mouse selection instead of clipboard + + + <qt><b>Use mouse selection instead of clipboard:</b> <br /> + <p>If checked, clipboard operations in KGpg will use the selection clipboard, that means highlighting a text to copy, and middle button (or right+left together) to paste. If this option is not checked, the clipboard will work with Key shortcuts (Ctrl-c, Ctrl-v).</p></qt> + + + + + kcfg_RemoteFileWarn + + + + 0 + 0 + + + + Display warning before creating temporary files +(only occurs on remote files operations) + + + <qt><b>Display warning before creating temporary files:</b><br /> + <p></p></qt> + + + + + groupShred + + + Shredder + + + + unnamed + + + + spacer7 + + + Horizontal + + + Expanding + + + + 91 + 20 + + + + + + pushShredder + + + Install Shredder + + + + + textLabel6 + + + KGpg allows you to create a shredder on your desktop. +It will shred (overwrite several times before erasing) the +files you drop on it, making it almost impossible to recover +the original file. + + + WordBreak|AlignJustify|AlignTop + + + + + shredInfo + + + textLabel5 + + + AlignTop + + + + + + + spacer8 + + + Vertical + + + Expanding + + + + 20 + 71 + + + + + + + + TabPage + + + Applet && Menus + + + + unnamed + + + + textLabel1_2 + + + Left mouse click opens (restart KGpg to apply): + + + + + + Key Manager + + + + + Editor + + + + kcfg_LeftClick + + + + 3 + 0 + 0 + 0 + + + + + + spacer3 + + + Vertical + + + Expanding + + + + 21 + 91 + + + + + + groupBox11 + + + Konqueror Service Menus + + + + unnamed + + + + textLabel1 + + + + 1 + 0 + 0 + 0 + + + + Sign file service menu: + + + <qt><b>Sign file service menu:</b><br /> + <p></p> + </qt> + + + + + textLabel1_3 + + + + 1 + 0 + 0 + 0 + + + + Decrypt file service menu: + + + <qt><b>Decrypt file service menu:</b><br /> + <p></p> + </qt> + + + + + + Disable + + + + + Enable with All Files + + + + kcfg_SignMenu + + + + 1 + 0 + 0 + 0 + + + + + + + Disable + + + + + Enable with All Files + + + + + Enable with Encrypted Files + + + + kcfg_DecryptMenu + + + + + + + groupBox3 + + + System Tray Applet + + + + unnamed + + + + textLabel1_3_2 + + + Event on unencrypted file drop: + + + <qt><b>Event on unencrypted file drop:</b><br /> + <p></p> + </qt> + + + + + textLabel1_2_2 + + + Event on encrypted file drop: + + + <qt><b>Event on encrypted file drop:</b><br /> + <p></p> + </qt> + + + + + + Encrypt + + + + + Sign + + + + + Ask + + + + kcfg_UnencryptedDropEvent + + + + + + Decrypt & Save + + + + + Decrypt & Open in Editor + + + + + Ask + + + + kcfg_EncryptedDropEvent + + + + + + + + + + + diff --git a/kgpg/conf_servers.ui b/kgpg/conf_servers.ui new file mode 100644 index 0000000..022eca7 --- /dev/null +++ b/kgpg/conf_servers.ui @@ -0,0 +1,118 @@ + +ServerConf + + + ServerConf + + + + 0 + 0 + 427 + 248 + + + + + unnamed + + + 0 + + + + server_default + + + + 1 + 0 + 0 + 0 + + + + Set as Default + + + + + server_add + + + + 1 + 0 + 0 + 0 + + + + Add... + + + + + server_del + + + + 1 + 0 + 0 + 0 + + + + Delete + + + + + ServerBox + + + + 7 + 5 + 0 + 0 + + + + + + layout2 + + + + unnamed + + + + textLabel1_4 + + + <b>INFORMATION</b>: +Only the default server will be stored in GnuPG's configuration file, +all others will be stored for use by KGpg only. + + + + + kcfg_UseProxy + + + Honor HTTP proxy when available + + + + + + + + + kpushbutton.h + klistbox.h + + diff --git a/kgpg/conf_ui2.ui b/kgpg/conf_ui2.ui new file mode 100644 index 0000000..98e622b --- /dev/null +++ b/kgpg/conf_ui2.ui @@ -0,0 +1,178 @@ + +UIConf + + + UIConf + + + + 0 + 0 + 541 + 439 + + + + + unnamed + + + 0 + + + + tabWidget3 + + + + tab + + + Key Colors + + + + unnamed + + + + kcfg_ColorUnknown + + + + + + + + textLabel1_3_3 + + + Unknown keys: + + + + + kcfg_ColorRev + + + + + + + 30 + 30 + 30 + + + + + + textLabel1_4 + + + Trusted keys: + + + + + textLabel1_4_2 + + + Expired/disabled keys: + + + + + textLabel1_2_3 + + + Revoked keys: + + + + + kcfg_ColorBad + + + + + + + 172 + 0 + 0 + + + + + + kcfg_ColorGood + + + + + + + 144 + 255 + 0 + + + + + + spacer5 + + + Vertical + + + Expanding + + + + 21 + 210 + + + + + + spacer4 + + + Horizontal + + + Expanding + + + + 140 + 20 + + + + + + + + TabPage + + + Editor Font + + + + + + + + + + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + kcolorbutton.h + + diff --git a/kgpg/dcopiface.h b/kgpg/dcopiface.h new file mode 100644 index 0000000..d9b3455 --- /dev/null +++ b/kgpg/dcopiface.h @@ -0,0 +1,35 @@ +/*************************************************************************** + kgpg.h - description + ------------------- + begin : Mon Jul 21 2003 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGDCOPIF_H +#define KGPGDCOPIF_H + +#include + +class KeyInterface : virtual public DCOPObject +{ + K_DCOP + k_dcop: + virtual void showKeyInfo(QString keyID) =0; + virtual bool importRemoteKey(QString keyID)=0; + virtual void showOptions()=0; + virtual void showKeyServer()=0; + virtual void showKeyManager()=0; +}; + +#endif // KGPGDCOPIF_H + diff --git a/kgpg/detailedconsole.cpp b/kgpg/detailedconsole.cpp new file mode 100644 index 0000000..985ca01 --- /dev/null +++ b/kgpg/detailedconsole.cpp @@ -0,0 +1,65 @@ +/*************************************************************************** + detailledconsole.cpp - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "kgpgoptions.h" +#include "detailedconsole.h" + + +KDetailedConsole::KDetailedConsole(QWidget *parent, const char *name,const QString &boxLabel,const QString &errormessage) + : KDialogBase(parent,name,true,i18n("Sorry"),KDialogBase::Details|KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok) +{ + QWidget *page = new QWidget( this ); + setMainWidget(page); + QVBoxLayout *vbox=new QVBoxLayout(page,0, spacingHint() ); + + QLabel *lab1=new QLabel(page); + lab1->setText(boxLabel); + + QVGroupBox *detailsGroup = new QVGroupBox( i18n("Details"), page); + (void) new QLabel(errormessage,detailsGroup); + //labdetails->setMinimumSize(labdetails->sizeHint()); + setDetailsWidget(detailsGroup); + vbox->addWidget(lab1); + +} + +KDetailedConsole::~KDetailedConsole() +{} + +KDetailedInfo::KDetailedInfo(QWidget *parent, const char *name , const QString &boxLabel,const QString &errormessage,QStringList keysList) + : KDialogBase(Swallow, i18n("Info"),KDialogBase::Details|KDialogBase::Ok, KDialogBase::Ok,parent,name,true) +{ + bool checkboxResult; + KMessageBox::createKMessageBox(this, QMessageBox::Information, + boxLabel, keysList,QString::null,&checkboxResult, 0,errormessage); +} + +KDetailedInfo::~KDetailedInfo() +{} + +//#include "detailedconsole.moc" diff --git a/kgpg/detailedconsole.h b/kgpg/detailedconsole.h new file mode 100644 index 0000000..5d0e669 --- /dev/null +++ b/kgpg/detailedconsole.h @@ -0,0 +1,43 @@ +/*************************************************************************** + detailledconsole.h - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KDETAILED_H +#define KDETAILED_H + +#include + +class KDetailedConsole : public KDialogBase +{ +public: + + KDetailedConsole(QWidget *parent=0, const char *name=0,const QString &boxLabel=QString::null,const QString &errormessage=QString::null); + ~KDetailedConsole(); + +}; + + +class KDetailedInfo : public KDialogBase +{ +public: + + KDetailedInfo(QWidget *parent=0, const char *name=0,const QString &boxLabel=QString::null,const QString &errormessage=QString::null,QStringList keysList=QStringList()); + ~KDetailedInfo(); + +}; + +#endif // KDETAILED_H + diff --git a/kgpg/encryptfile.desktop b/kgpg/encryptfile.desktop new file mode 100644 index 0000000..c117c30 --- /dev/null +++ b/kgpg/encryptfile.desktop @@ -0,0 +1,62 @@ +[Desktop Entry] +ServiceTypes=all/allfiles +ExcludeServiceTypes=kdedevice/* +Actions=encrypt + +[Desktop Action encrypt] +Name=Encrypt File +Name[ar]=تشفير ملف +Name[bg]=Шифроване на файл +Name[br]=E&nrinegañ ar restr +Name[bs]=Šifriraj datoteku +Name[ca]=Xifra fitxer +Name[cs]=Zašifrovat soubor +Name[cy]=Cêl-ysgrifo Ffeil +Name[da]=Indkod fil +Name[de]=Datei verschlüsseln +Name[el]=Κρυπτογράφηση αρχείου +Name[eo]=Ĉifri dosieron +Name[es]=Cifrar archivo +Name[et]=Krüpti fail +Name[eu]=Fitxategiak Zifratu +Name[fa]=رمزبندی پرونده +Name[fi]=Salaa tiedosto +Name[fr]=Chiffrer le fichier +Name[ga]=Criptigh Comhad +Name[he]=הצפן קובץ +Name[hi]=एनक्रिप्ट फ़ाइल +Name[hu]=Fájl titkosítása +Name[is]=Dulrita skrá +Name[it]=Cifratura file +Name[ja]=ファイルを暗号化 +Name[ka]=დაილის დაშიფრვა +Name[kk]=Файлды шифрлау +Name[km]=អ៊ិនគ្រីប​ឯកសារ +Name[lt]=Šifruoti bylą +Name[mk]=Криптирај датотеки +Name[nb]=Krypter fil +Name[nds]=Dateiverslöteln +Name[ne]=फाइल गुप्तीकरण गर्नुहोस् +Name[nl]=Bestand versleutelen +Name[nn]=Krypter fil +Name[pa]=ਇੰਕਰਿਪਟ ਫਾਇਲ +Name[pl]=Zaszyfruj plik +Name[pt]=Cifrar Ficheiro +Name[pt_BR]=Criptografar Arquivo +Name[ro]=Criptează fişierul +Name[ru]=Зашифровать файл +Name[sk]=Šifrovať súbor +Name[sl]=Šifriraj datoteko +Name[sr]=Шифруј фајл +Name[sr@Latn]=Šifruj fajl +Name[sv]=Kryptera fil +Name[ta]=சங்கேத கோப்பு +Name[tg]=Рамзкунонии Файл +Name[tr]=Dosya Şifrele +Name[uk]=Зашифрувати файл +Name[wa]=Ecripter fitchî +Name[zh_CN]=加密文件 +Name[zh_TW]=加密檔案 +Icon=kgpg +Exec=kgpg -e %F + diff --git a/kgpg/encryptfolder.desktop b/kgpg/encryptfolder.desktop new file mode 100644 index 0000000..60083ba --- /dev/null +++ b/kgpg/encryptfolder.desktop @@ -0,0 +1,52 @@ +[Desktop Entry] +ServiceTypes=inode/directory +Actions=encrypt + +[Desktop Action encrypt] +Name=Archive & Encrypt Folder +Name[ar]=أرشفة و تشفير مجلّد +Name[bg]=Архивиране и шифроване на директория +Name[bs]=Arhiviraj i šifriraj direktorij +Name[ca]=Arxiva i xifra la carpeta +Name[cs]=Archivovat a zašifrovat složku +Name[da]=Arkivér & kryptér mappe +Name[de]=Ordner packen und verschlüsseln +Name[el]=Αρχειοθέτηση & κρυπτογράφηση φακέλου +Name[eo]=Arkivigi kaj ĉifri dosierujon +Name[es]=Archivar y cifrar carpeta +Name[et]=Arhiveeri ja krüpti kataloog +Name[eu]=Artxibatu eta enkriptatu karpeta +Name[fa]=بایگانی و رمزبندی پوشه +Name[fi]=Pakkaa ja salaa kansio +Name[fr]=Archiver puis chiffrer le dossier +Name[ga]=Cuir Fillteán i gCartlann & Criptigh É +Name[he]=כלי להצפנה וכיווץ תקייה +Name[hu]=Könyvtár titkosítása és archiválása +Name[is]=Pakka og dulrita möppu +Name[it]=Archivia e cifra cartella +Name[ja]=フォルダをアーカイブ化 & 暗号化 +Name[ka]=არქივი და დაშიფრვის საქაღალდე +Name[kk]=Қапшықты архивтеп шифрлау +Name[km]=ថត​ប័ណ្ណសារ & អ៊ិនគ្រីប +Name[lt]=Archyvuoti ir šifruoti aplanką +Name[nb]=Arkiver og krypter mappe +Name[nds]=Ornern komprimeren un verslöteln +Name[ne]=फोल्डरलाई सङ्ग्रह र गुप्तीकरण गर्नुहोस् +Name[nl]=Map archiveren en versleutelen +Name[nn]=Arkiver og krypter mappe +Name[pa]=ਆਕੀਵੀ & ਇੰਕਰਿਪਟ ਫੋਲਡਰ +Name[pl]=Zarchiwizuj i zaszyfruj katalog +Name[pt]=Arquivar e Cifrar a Pasta +Name[pt_BR]=Arquivar & Criptografar Pasta +Name[ru]=Архивировать и зашифровать папку +Name[sk]=Archivovať a šifrovať priečinok +Name[sl]=Arhiviranje in ši&friranje imenika +Name[sr]=Архивирај и шифруј фасциклу +Name[sr@Latn]=Arhiviraj i šifruj fasciklu +Name[sv]=Arkivera och kryptera katalog +Name[tr]=Arşiv ve Klasör Şifrele +Name[uk]=Зробити архів теки і зашифрувати +Name[zh_CN]=存档并加密文件夹 +Name[zh_TW]=壓縮並加密資料夾 +Icon=kgpg +Exec=kgpg -e %F diff --git a/kgpg/groupedit.ui b/kgpg/groupedit.ui new file mode 100644 index 0000000..ca96e4b --- /dev/null +++ b/kgpg/groupedit.ui @@ -0,0 +1,212 @@ + +groupEdit + + + groupEdit + + + + 0 + 0 + 557 + 259 + + + + + + + + unnamed + + + 0 + + + + + Name + + + true + + + true + + + + + Email + + + true + + + true + + + + + Id + + + true + + + true + + + + availableKeys + + + true + + + Extended + + + true + + + true + + + true + + + false + + + + 238 + 246 + 255 + + + + + + textLabel1 + + + + 5 + 4 + 0 + 0 + + + + Available Trusted Keys + + + + + buttonAdd + + + + + + + + buttonRemove + + + + + + + + spacer5 + + + Horizontal + + + Expanding + + + + 71 + 20 + + + + + + kActiveLabel1 + + + <b>Keys in the Group</b> + + + + + + Name + + + true + + + true + + + + + Email + + + true + + + true + + + + + Id + + + true + + + true + + + + groupKeys + + + true + + + Extended + + + true + + + true + + + 1 + + + true + + + false + + + + + + + + + kactivelabel.h + + diff --git a/kgpg/hi16-app-kgpg.png b/kgpg/hi16-app-kgpg.png new file mode 100644 index 0000000..4102aab Binary files /dev/null and b/kgpg/hi16-app-kgpg.png differ diff --git a/kgpg/hi22-app-kgpg.png b/kgpg/hi22-app-kgpg.png new file mode 100644 index 0000000..fb3e9de Binary files /dev/null and b/kgpg/hi22-app-kgpg.png differ diff --git a/kgpg/hi32-app-kgpg.png b/kgpg/hi32-app-kgpg.png new file mode 100644 index 0000000..82225f0 Binary files /dev/null and b/kgpg/hi32-app-kgpg.png differ diff --git a/kgpg/hi48-app-kgpg.png b/kgpg/hi48-app-kgpg.png new file mode 100644 index 0000000..a01145e Binary files /dev/null and b/kgpg/hi48-app-kgpg.png differ diff --git a/kgpg/icons/Makefile.am b/kgpg/icons/Makefile.am new file mode 100644 index 0000000..f45690c --- /dev/null +++ b/kgpg/icons/Makefile.am @@ -0,0 +1,2 @@ +kgpgiconsdir = $(kde_datadir)/kgpg/icons +kgpgicons_ICON = AUTO diff --git a/kgpg/icons/cr16-action-kgpg_key1.png b/kgpg/icons/cr16-action-kgpg_key1.png new file mode 100644 index 0000000..ee3b21c Binary files /dev/null and b/kgpg/icons/cr16-action-kgpg_key1.png differ diff --git a/kgpg/icons/cr16-action-kgpg_key2.png b/kgpg/icons/cr16-action-kgpg_key2.png new file mode 100644 index 0000000..ad4e016 Binary files /dev/null and b/kgpg/icons/cr16-action-kgpg_key2.png differ diff --git a/kgpg/icons/cr16-action-kgpg_key3.png b/kgpg/icons/cr16-action-kgpg_key3.png new file mode 100644 index 0000000..ae788ca Binary files /dev/null and b/kgpg/icons/cr16-action-kgpg_key3.png differ diff --git a/kgpg/icons/cr16-action-kgpg_key4.png b/kgpg/icons/cr16-action-kgpg_key4.png new file mode 100644 index 0000000..2e4e11a Binary files /dev/null and b/kgpg/icons/cr16-action-kgpg_key4.png differ diff --git a/kgpg/icons/cr22-action-kgpg_edit.png b/kgpg/icons/cr22-action-kgpg_edit.png new file mode 100644 index 0000000..96ba433 Binary files /dev/null and b/kgpg/icons/cr22-action-kgpg_edit.png differ diff --git a/kgpg/icons/cr22-action-kgpg_export.png b/kgpg/icons/cr22-action-kgpg_export.png new file mode 100644 index 0000000..b2e56ff Binary files /dev/null and b/kgpg/icons/cr22-action-kgpg_export.png differ diff --git a/kgpg/icons/cr22-action-kgpg_gen.png b/kgpg/icons/cr22-action-kgpg_gen.png new file mode 100644 index 0000000..d48fbe2 Binary files /dev/null and b/kgpg/icons/cr22-action-kgpg_gen.png differ diff --git a/kgpg/icons/cr22-action-kgpg_identity.png b/kgpg/icons/cr22-action-kgpg_identity.png new file mode 100644 index 0000000..c41101c Binary files /dev/null and b/kgpg/icons/cr22-action-kgpg_identity.png differ diff --git a/kgpg/icons/cr22-action-kgpg_import.png b/kgpg/icons/cr22-action-kgpg_import.png new file mode 100644 index 0000000..096e22b Binary files /dev/null and b/kgpg/icons/cr22-action-kgpg_import.png differ diff --git a/kgpg/icons/cr22-action-kgpg_info.png b/kgpg/icons/cr22-action-kgpg_info.png new file mode 100644 index 0000000..eef8be6 Binary files /dev/null and b/kgpg/icons/cr22-action-kgpg_info.png differ diff --git a/kgpg/icons/cr22-action-kgpg_photo.png b/kgpg/icons/cr22-action-kgpg_photo.png new file mode 100644 index 0000000..a370bd0 Binary files /dev/null and b/kgpg/icons/cr22-action-kgpg_photo.png differ diff --git a/kgpg/icons/cr22-action-kgpg_show.png b/kgpg/icons/cr22-action-kgpg_show.png new file mode 100644 index 0000000..3e3e122 Binary files /dev/null and b/kgpg/icons/cr22-action-kgpg_show.png differ diff --git a/kgpg/icons/cr22-action-kgpg_sign.png b/kgpg/icons/cr22-action-kgpg_sign.png new file mode 100644 index 0000000..3580184 Binary files /dev/null and b/kgpg/icons/cr22-action-kgpg_sign.png differ diff --git a/kgpg/icons/cr22-action-kgpg_term.png b/kgpg/icons/cr22-action-kgpg_term.png new file mode 100644 index 0000000..126fb73 Binary files /dev/null and b/kgpg/icons/cr22-action-kgpg_term.png differ diff --git a/kgpg/keyexport.ui b/kgpg/keyexport.ui new file mode 100644 index 0000000..35f4128 --- /dev/null +++ b/kgpg/keyexport.ui @@ -0,0 +1,142 @@ + +KeyExport + + + KeyExport + + + + 0 + 0 + 370 + 167 + + + + + 5 + 5 + 0 + 0 + + + + + 350 + 0 + + + + + unnamed + + + 0 + + + + exportAttributes + + + Export attributes (photo id) + + + true + + + + + spacer1 + + + Vertical + + + Expanding + + + + 20 + 16 + + + + + + buttonGroup2 + + + + + + + unnamed + + + + checkMail + + + Email + + + + + checkServer + + + Default key server + + + + + checkClipboard + + + Clipboard + + + + + newFilename + + + true + + + + + checkFile + + + File: + + + true + + + + + + + + + + + checkFile + toggled(bool) + KeyExport + checkFile_toggled(bool) + + + + keyexport.ui.h + + + checkFile_toggled( bool isOn ) + + + + kpushbutton.h + + diff --git a/kgpg/keyexport.ui.h b/kgpg/keyexport.ui.h new file mode 100644 index 0000000..89ef491 --- /dev/null +++ b/kgpg/keyexport.ui.h @@ -0,0 +1,21 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ +//(C) 2002 Jean-Baptiste Mardelle + +void KeyExport::checkFile_toggled( bool isOn) +{ +newFilename->setEnabled(isOn); +} diff --git a/kgpg/keygener.cpp b/kgpg/keygener.cpp new file mode 100644 index 0000000..739bb55 --- /dev/null +++ b/kgpg/keygener.cpp @@ -0,0 +1,176 @@ +/*************************************************************************** + keygen.cpp - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/////////////////////////////////////////////// code for new key generation + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "keygener.h" + +/////////////////////// main window +keyGenerate::keyGenerate(QWidget *parent, const char *name):KDialogBase( parent, name, true,i18n("Key Generation"),Apply | Ok | Cancel) +{ + expert=false; + setButtonApply(i18n("Expert Mode")); + + QWidget *page = new QWidget(this); + QVBoxLayout *vbox=new QVBoxLayout(page); + + QVButtonGroup *bgroup1=new QVButtonGroup(i18n("Generate Key Pair"),page); + + (void) new QLabel(i18n("Name:"),bgroup1); + kname=new KLineEdit("",bgroup1); + kname->setFocus(); + (void) new QLabel(i18n("Email:"),bgroup1); + mail=new KLineEdit("",bgroup1); + + (void) new QLabel(i18n("Comment (optional):"),bgroup1); + comment=new KLineEdit("",bgroup1); + + (void) new QLabel(i18n("Expiration:"),bgroup1); + QHButtonGroup *bgroup=new QHButtonGroup(bgroup1); + numb=new KLineEdit("0",bgroup); + numb->setMaxLength(4); + numb->setDisabled(true); + keyexp = new KComboBox(bgroup); + keyexp->insertItem(i18n("Never"),0); + keyexp->insertItem(i18n("Days"),1); + keyexp->insertItem(i18n("Weeks"),2); + keyexp->insertItem(i18n("Months"),3); + keyexp->insertItem(i18n("Years"),4); + keyexp->setMinimumSize(keyexp->sizeHint()); + connect(keyexp,SIGNAL(activated(int)),this,SLOT(activateexp(int))); + + (void) new QLabel(i18n("Key size:"),bgroup1); + keysize = new KComboBox(bgroup1); + keysize->insertItem("768"); + keysize->insertItem("1024"); + keysize->insertItem("2048"); + keysize->insertItem("4096"); + keysize->setCurrentItem("1024"); + keysize->setMinimumSize(keysize->sizeHint()); + + (void) new QLabel(i18n("Algorithm:"),bgroup1); + keykind = new KComboBox(bgroup1); + keykind->insertItem("DSA & ElGamal"); + keykind->insertItem("RSA"); + keykind->setMinimumSize(keykind->sizeHint()); + + vbox->addWidget(bgroup1); + page->show(); + page->resize(page->maximumSize()); + setMainWidget(page); +} + +void keyGenerate::slotOk() +{ + if (QString(kname->text()).stripWhiteSpace().isEmpty()) { + KMessageBox::sorry(this,i18n("You must give a name.")); + return; + } + QString vmail=mail->text(); + if (vmail.isEmpty()) + { + if (KMessageBox::warningContinueCancel(this,i18n("You are about to create a key with no email address"))!=KMessageBox::Continue) return; + } + else if ((vmail.find(" ")!=-1) || (vmail.find(".")==-1) || (vmail.find("@")==-1)) { + KMessageBox::sorry(this,i18n("Email address not valid")); + return; + } + accept(); +} + +void keyGenerate::slotApply() +{ + expert=true; + accept(); +} + +void keyGenerate::activateexp(int state) +{ + if (state==0) + numb->setDisabled(true); + else + numb->setDisabled(false); +} + +bool keyGenerate::getmode() +{ + return(expert); +} + + +QString keyGenerate::getkeytype() +{ + return(keykind->currentText()); +} + +QString keyGenerate::getkeysize() +{ + return(keysize->currentText()); +} + +int keyGenerate::getkeyexp() +{ + return(keyexp->currentItem()); +} + +QString keyGenerate::getkeynumb() +{ + if (numb->text()!=NULL) + return(numb->text()); + else + return (""); +} + +QString keyGenerate::getkeyname() +{ + if (kname->text()!=NULL) + return(kname->text()); + else + return (""); +} + +QString keyGenerate::getkeymail() +{ + if (mail->text()!=NULL) + return(mail->text()); + else + return (""); +} + +QString keyGenerate::getkeycomm() +{ + if (comment->text()!=NULL) + return(comment->text()); + else + return (""); +} + +#include "keygener.moc" diff --git a/kgpg/keygener.h b/kgpg/keygener.h new file mode 100644 index 0000000..0c1cd89 --- /dev/null +++ b/kgpg/keygener.h @@ -0,0 +1,50 @@ +/*************************************************************************** + keygen.h - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef KEYGEN_H +#define KEYGEN_H + +#include + +class KComboBox; +class KLineEdit; + +class keyGenerate : public KDialogBase +{ + Q_OBJECT +public: + keyGenerate(QWidget *parent=0, const char *name=0); + + KComboBox *keykind,*keysize,*keyexp; + KLineEdit *numb,*comment,*kname,*mail; + bool expert; + +public slots: + void slotOk(); + void slotApply(); + void activateexp(int state); + bool getmode(); + QString getkeycomm(); + QString getkeynumb(); + QString getkeymail(); + QString getkeyname(); + QString getkeysize(); + QString getkeytype(); + int getkeyexp(); +}; + +#endif // KEYGEN_H + diff --git a/kgpg/keyinfowidget.cpp b/kgpg/keyinfowidget.cpp new file mode 100644 index 0000000..4704eba --- /dev/null +++ b/kgpg/keyinfowidget.cpp @@ -0,0 +1,465 @@ +/*************************************************************************** + keyinfowidget.cpp - description + ------------------- + begin : Mon Nov 18 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your gpgOutpution) any later version. * + * * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "keyinfowidget.h" +#include "keyproperties.h" +#include "kgpgsettings.h" +#include "kgpginterface.h" + +KgpgKeyInfo::KgpgKeyInfo(QWidget *parent, const char *name,QString sigkey):KDialogBase( Swallow, i18n("Key Properties"), Close, Close, parent, name,true) +{ + + FILE *pass; + char line[200]=""; + QString gpgOutput,fullID; + hasPhoto=false; + bool isSecret=false; + keyWasChanged=false; + + prop=new KeyProperties(); + setMainWidget(prop); + QString gpgcmd="gpg --no-tty --no-secmem-warning --with-colon --list-secret-key "+KShellProcess::quote(sigkey); + pass=popen(QFile::encodeName(gpgcmd),"r"); + while ( fgets( line, sizeof(line), pass)) { + gpgOutput=line; + if (gpgOutput.startsWith("sec")) isSecret=true; + } + pclose(pass); + + if (!isSecret) { + prop->changeExp->hide(); + prop->changePass->hide(); + } + loadKey(sigkey); + + if (hasPhoto) { + KgpgInterface *photoProcess=new KgpgInterface(); + photoProcess->KgpgGetPhotoList(displayedKeyID); + connect(photoProcess,SIGNAL(signalPhotoList(QStringList)),this,SLOT(slotSetMainPhoto(QStringList))); + } + else + prop->comboId->setEnabled(false); + + connect(prop->changeExp,SIGNAL(clicked()),this,SLOT(slotChangeExp())); + connect(this,SIGNAL(closeClicked()),this,SLOT(slotPreOk())); + connect(prop->changePass,SIGNAL(clicked()),this,SLOT(slotChangePass())); + connect(prop->comboId,SIGNAL(activated (const QString &)),this,SLOT(reloadMainPhoto(const QString &))); + connect(prop->cbDisabled,SIGNAL(toggled(bool)),this,SLOT(slotDisableKey(bool))); + connect(prop->kCOwnerTrust,SIGNAL(activated (int)),this,SLOT(slotChangeTrust(int))); + connect(this,SIGNAL(changeMainPhoto(const QPixmap&)),this,SLOT(slotSetPhoto(const QPixmap&))); + + //prop->setMinimumSize(prop->sizeHint()); +} + +void KgpgKeyInfo::slotDisableKey(bool isOn) +{ +KProcess kp; + + kp<<"gpg" + <<"--no-tty" + <<"--edit-key" + <tLAlgo->setText(algo); + + const QString trust=gpgOutput.section(':',1,1); + QString tr; + switch( trust[0] ) { + case 'o': + tr= i18n("Unknown"); + trustColor=KGpgSettings::colorUnknown(); + break; + case 'i': + tr= i18n("Invalid"); + trustColor=KGpgSettings::colorBad(); + break; + case 'd': + tr=i18n("Disabled"); + trustColor=KGpgSettings::colorBad(); + prop->cbDisabled->setChecked(true); + break; + case 'r': + tr=i18n("Revoked"); + trustColor=KGpgSettings::colorRev(); + break; + case 'e': + tr=i18n("Expired"); + trustColor=KGpgSettings::colorBad(); + break; + case 'q': + tr=i18n("Undefined"); + trustColor=KGpgSettings::colorUnknown(); + break; + case 'n': + tr=i18n("None"); + trustColor=KGpgSettings::colorUnknown(); + break; + case 'm': + tr=i18n("Marginal"); + trustColor=KGpgSettings::colorBad(); + break; + case 'f': + tr=i18n("Full"); + trustColor=KGpgSettings::colorGood(); + break; + case 'u': + tr=i18n("Ultimate"); + trustColor=KGpgSettings::colorGood(); + break; + default: + tr="?"; + trustColor=KGpgSettings::colorUnknown(); + break; + } + + if (gpgOutput.section(':',11,11).find("D",0,true)!=-1) // disabled key + { + tr=i18n("Disabled"); + trustColor=KGpgSettings::colorBad(); + prop->cbDisabled->setChecked(true); + } + + prop->kLTrust->setText(tr); + prop->pixmapTrust->setPaletteBackgroundColor(trustColor); + + fullID=gpgOutput.section(':',4,4); + displayedKeyID=fullID.right(8); + prop->tLID->setText(fullID); + + QString fullname=gpgOutput.section(':',9,9); + + QDate date = QDate::fromString(gpgOutput.section(':',5,5), Qt::ISODate); + prop->tLCreation->setText(KGlobal::locale()->formatDate(date)); + + if (gpgOutput.section(':',6,6).isEmpty()) expirationDate=i18n("Unlimited"); + else + { + date = QDate::fromString(gpgOutput.section(':',6,6), Qt::ISODate); + expirationDate=KGlobal::locale()->formatDate(date); + } + prop->tLExpiration->setText(expirationDate); + + prop->tLLength->setText(gpgOutput.section(':',2,2)); + + const QString otrust=gpgOutput.section(':',8,8); + int ownerTrust=0; + + /* Don't know=1; Do NOT trust=2; Marginally=3; Fully=4; Ultimately=5; */ + + switch( otrust[0] ) { + case 'f': + ownerTrust=3; + break; + case 'u': + ownerTrust=4; + break; + case 'm': + ownerTrust=2; + break; + case 'n': + ownerTrust=1; + break; + default: + ownerTrust=0; + break; + } + prop->kCOwnerTrust->setCurrentItem(ownerTrust); + + if (fullname.find("<")!=-1) { + QString kmail=fullname; + if (fullname.find(")")!=-1) + kmail=kmail.section(')',1); + kmail=kmail.section('<',1); + kmail.truncate(kmail.length()-1); + if (kmail.find("<")!=-1) //////// several email addresses in the same key + { + kmail=kmail.replace(">",";"); + kmail.remove("<"); + } + prop->tLMail->setText(""+kmail+""); + } else + prop->tLMail->setText(i18n("none")); + + QString kname=fullname.section('<',0,0); + if (fullname.find("(")!=-1) { + kname=kname.section('(',0,0); + QString comment=fullname.section('(',1,1); + comment=comment.section(')',0,0); + prop->tLComment->setText(KgpgInterface::checkForUtf8(comment)); + } else + prop->tLComment->setText(i18n("none")); + + prop->tLName->setText(""+KgpgInterface::checkForUtf8(kname).replace(QRegExp("<"),"<")+""); + + } + if (gpgOutput.startsWith("fpr") && (fingervalue.isNull())) { + fingervalue=gpgOutput.section(':',9,9); + // format fingervalue in 4-digit groups + uint len = fingervalue.length(); + if ((len > 0) && (len % 4 == 0)) + for (uint n = 0; 4*(n+1) < len; n++) + fingervalue.insert(5*n+4, ' '); + prop->lEFinger->setText(fingervalue); + } + } + pclose(pass); +} + +void KgpgKeyInfo::slotSetMainPhoto(QStringList list) +{ +prop->comboId->insertStringList(list); +reloadMainPhoto(prop->comboId->currentText()); +} + +void KgpgKeyInfo::reloadMainPhoto(const QString &uid) +{ + + kgpginfotmp=new KTempFile(); + kgpginfotmp->setAutoDelete(true); + QString pgpgOutput="cp %i "+kgpginfotmp->name(); + KProcIO *p=new KProcIO(); + *p<<"gpg"<<"--no-tty"<<"--show-photos"<<"--photo-viewer"<start(KProcess::NotifyOnExit,true); + +} + + +void KgpgKeyInfo::slotMainImageRead(KProcess *p) +{ + p->deleteLater(); + QPixmap pixmap; + pixmap.load(kgpginfotmp->name()); + emit changeMainPhoto(pixmap); + kgpginfotmp->unlink(); +} + + +KgpgKeyInfo::~KgpgKeyInfo() +{ +} + +void KgpgKeyInfo::slotSetPhoto(const QPixmap &pix) +{ +QImage dup=pix.convertToImage(); +QPixmap dup2; +dup2.convertFromImage(dup.scale(prop->pLPhoto->width(),prop->pLPhoto->height(),QImage::ScaleMin)); +prop->pLPhoto->setPixmap(dup2); +} + + + + +void KgpgKeyInfo::finishphotoreadprocess(KProcIO *p) +{ + QString required=QString::null; + while (p->readln(required,true)!=-1) + if (required.find("keyedit.prompt")!=-1) { + p->writeStdin("quit"); + p->closeWhenDone(); + + } +} + + +void KgpgKeyInfo::openPhoto() +{ + KTrader::OfferList offers = KTrader::self()->query("image/jpeg", "Type == 'Application'"); + KService::Ptr ptr = offers.first(); + //KMessageBox::sorry(0,ptr->desktopEntryName()); + KProcIO *p=new KProcIO(); + *p<<"gpg"<<"--show-photos"<<"--photo-viewer"<desktopEntryName()+" %i")<<"--list-keys"<start(KProcess::DontCare,true); +} + +void KgpgKeyInfo::slotChangeExp() +{ +chdate=new KDialogBase( this, "choose_date", true,i18n("Choose New Expiration"),KDialogBase::Ok | KDialogBase::Cancel); +QWidget *page = new QWidget(chdate); +kb= new QCheckBox(i18n("Unlimited"),page ); + +if (prop->tLExpiration->text()==i18n("Unlimited")) +{ +kdt= new KDatePicker( page ); +kb->setChecked(true); +kdt->setEnabled(false); +} +else +kdt= new KDatePicker(page,KGlobal::locale()->readDate(prop->tLExpiration->text())); +QVBoxLayout *vbox=new QVBoxLayout(page,3); +vbox->addWidget(kdt); +vbox->addWidget(kb); +connect(kb,SIGNAL(toggled(bool)),this,SLOT(slotEnableDate(bool))); +connect(chdate,SIGNAL(okClicked()),this,SLOT(slotChangeDate())); +connect(kdt,SIGNAL(dateChanged(QDate)),this,SLOT(slotCheckDate(QDate))); +connect(kdt,SIGNAL(dateEntered(QDate)),this,SLOT(slotCheckDate(QDate))); + +chdate->setMainWidget(page); +chdate->show(); +} + +void KgpgKeyInfo::slotCheckDate(QDate date) +{ +chdate->enableButtonOK(date>=QDate::currentDate ()); +} + +void KgpgKeyInfo::slotChangeDate() +{ +KgpgInterface *KeyExpirationProcess=new KgpgInterface(); + if (kb->isChecked()) + KeyExpirationProcess->KgpgKeyExpire(displayedKeyID,QDate::currentDate(),true); + else + KeyExpirationProcess->KgpgKeyExpire(displayedKeyID,kdt->date(),false); + connect(KeyExpirationProcess,SIGNAL(expirationFinished(int)),this,SLOT(slotInfoExpirationChanged(int))); +} + +void KgpgKeyInfo::slotEnableDate(bool isOn) +{ +if (isOn) +{ +kdt->setEnabled(false); +chdate->enableButtonOK(true); +} +else +{ +kdt->setEnabled(true); +chdate->enableButtonOK(kdt->date()>=QDate::currentDate ()); +} +} + +void KgpgKeyInfo::slotinfoimgread(KProcess *) +{ + QPixmap pixmap; + pixmap.load(kgpginfotmp->name()); + emit signalPhotoId(pixmap); + kgpginfotmp->unlink(); +} + +void KgpgKeyInfo::slotChangePass() +{ + KgpgInterface *ChangeKeyPassProcess=new KgpgInterface(); + ChangeKeyPassProcess->KgpgChangePass(displayedKeyID); + connect(ChangeKeyPassProcess,SIGNAL(passwordChanged()),this,SLOT(slotInfoPasswordChanged())); +} + +void KgpgKeyInfo::slotChangeTrust(int newTrust) +{ + KgpgInterface *KeyTrustProcess=new KgpgInterface(); + KeyTrustProcess->KgpgTrustExpire(displayedKeyID,newTrust); + connect(KeyTrustProcess,SIGNAL(trustfinished()),this,SLOT(slotInfoTrustChanged())); +} + + +void KgpgKeyInfo::slotInfoPasswordChanged() +{ +KPassivePopup::message(i18n("Passphrase for the key was changed"),QString::null,KGlobal::iconLoader()->loadIcon("kgpg",KIcon::Desktop),this); +} + +void KgpgKeyInfo::slotInfoTrustChanged() +{ +keyWasChanged=true; +loadKey(displayedKeyID); +//KPassivePopup::message(i18n("Owner trust of the key was changed"),QString::null,KGlobal::iconLoader()->loadIcon("kgpg",KIcon::Desktop),this,0,600); +} + +void KgpgKeyInfo::slotInfoExpirationChanged(int res) +{ +QString infoMessage,infoText; +if (res==3) +{ +keyWasChanged=true; +if (kb->isChecked()) prop->tLExpiration->setText(i18n("Unlimited")); +else prop->tLExpiration->setText(KGlobal::locale()->formatDate(kdt->date())); +} +if (res==2) { +infoMessage=i18n("Could not change expiration");infoText=i18n("Bad passphrase"); +KPassivePopup::message(infoMessage,infoText,KGlobal::iconLoader()->loadIcon("kgpg",KIcon::Desktop),this); +} +} + + +void KgpgKeyInfo::slotPreOk() +{ +if (keyWasChanged) emit keyNeedsRefresh(); +accept(); +} + +#include "keyinfowidget.moc" diff --git a/kgpg/keyinfowidget.h b/kgpg/keyinfowidget.h new file mode 100644 index 0000000..af8ba64 --- /dev/null +++ b/kgpg/keyinfowidget.h @@ -0,0 +1,84 @@ +/*************************************************************************** + keyinfowidget.h - description + ------------------- + begin : Thu Jul 4 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KEYINFOWIDGET_H +#define KEYINFOWIDGET_H + +#include +#include + +class KTempFile; +class QLabel; +class KDialogBase; +class QCheckBox; +class KDatePicker; +class KeyProperties; +class KProcess; +class KProcIO; + +class KgpgKeyInfo : public KDialogBase +{ + Q_OBJECT + +public: + + KgpgKeyInfo( QWidget *parent = 0, const char *name = 0,QString sigkey=0); + ~KgpgKeyInfo(); + KeyProperties *prop; + +private slots: + void slotinfoimgread(KProcess *); + void slotChangePass(); + void slotPreOk(); + void slotChangeExp(); + void slotEnableDate(bool isOn); + void slotChangeDate(); + void slotCheckDate(QDate date); + void openPhoto(); + void slotSetPhoto(const QPixmap &pix); + void finishphotoreadprocess(KProcIO *p); + void slotMainImageRead(KProcess *); + void slotSetMainPhoto(QStringList list); + void reloadMainPhoto(const QString &uid); + void slotInfoPasswordChanged(); + void slotInfoExpirationChanged(int res); + void slotInfoTrustChanged(); + void slotChangeTrust(int newTrust); + void loadKey(QString Keyid); + void slotDisableKey(bool isOn); + +private: + KTempFile *kgpginfotmp; + QLabel *keyinfoPhoto; + QString displayedKeyID; + QString expirationDate; + bool hasPhoto,keyWasChanged; + KDialogBase *chdate; + QCheckBox *kb; + KDatePicker *kdt; + int counter; + +signals: + + void signalPhotoId(const QPixmap&); + void changeMainPhoto(const QPixmap&); + void keyNeedsRefresh(); + +}; + +#endif // KEYINFOWIDGET_H + diff --git a/kgpg/keyproperties.ui b/kgpg/keyproperties.ui new file mode 100644 index 0000000..4a44ea9 --- /dev/null +++ b/kgpg/keyproperties.ui @@ -0,0 +1,507 @@ + +KeyProperties + + + KeyProperties + + + + 0 + 0 + 431 + 350 + + + + + 5 + 5 + 0 + 0 + + + + Key Properties + + + + unnamed + + + 0 + + + + layout39 + + + + unnamed + + + + pLPhoto + + + + 5 + 0 + 0 + 0 + + + + + 120 + 140 + + + + + 32767 + 140 + + + + + 200 + 200 + 200 + + + + Box + + + 2 + + + No Photo + + + false + + + AlignCenter + + + <qt><b>Photo:</b><br /> + <p>A photo can be included with a public key for extra security. The photo can be used as an additional method of authenticating the key. However, it should not be relied upon as the only form of authentication.</p> + </qt> + + + + + layout13 + + + + unnamed + + + + textLabel1 + + + Photo Id: + + + + + comboId + + + + + + + + + layout4 + + + + unnamed + + + + cbDisabled + + + Disable key + + + + + changeExp + + + true + + + + 5 + 0 + 0 + 0 + + + + Change Expiration... + + + + + changePass + + + true + + + + 1 + 0 + 0 + 0 + + + + Change Passphrase... + + + + + + + labelLength + + + 0 + + + Length: + + + + + labelCreation + + + 0 + + + Creation: + + + + + labelID + + + 0 + + + Key ID: + + + + + tLTrust_2 + + + + 5 + 5 + 0 + 0 + + + + 0 + + + Owner trust: + + + + + tLMail2_2 + + + 0 + + + Email: + + + + + labelAlgo + + + 0 + + + Algorithm: + + + + + labelExpiration + + + 0 + + + Expiration: + + + + + txtTrust + + + + 5 + 5 + 0 + 0 + + + + 0 + + + Trust: + + + + + tLComment2_2 + + + 0 + + + Comment: + + + + + tLName2_2 + + + 0 + + + Name: + + + + + lEFinger + + + true + + + true + + + + + tLID_2 + + + Fingerprint: + + + + + tLComment + + + + 7 + 5 + 0 + 0 + + + + + + pixmapTrust + + + + 5 + 5 + 0 + 0 + + + + Box + + + true + + + + + tLMail + + + + 7 + 5 + 0 + 0 + + + + + + tLID + + + + 7 + 5 + 0 + 0 + + + + + + tLExpiration + + + + 7 + 5 + 0 + 0 + + + + + + + Don't Know + + + + + Do NOT Trust + + + + + Marginally + + + + + Fully + + + + + Ultimately + + + + kCOwnerTrust + + + + + kLTrust + + + + 5 + 4 + 0 + 0 + + + + + + + + + tLLength + + + + 7 + 5 + 0 + 0 + + + + + + + + + tLAlgo + + + + 7 + 5 + 0 + 0 + + + + + + + + + tLCreation + + + + 7 + 5 + 0 + 0 + + + + + + tLName + + + + 7 + 5 + 0 + 0 + + + + + + + + + + kactivelabel.h + kactivelabel.h + kactivelabel.h + kactivelabel.h + kactivelabel.h + kactivelabel.h + + diff --git a/kgpg/keyserver.ui b/kgpg/keyserver.ui new file mode 100644 index 0000000..44d42c9 --- /dev/null +++ b/kgpg/keyserver.ui @@ -0,0 +1,336 @@ + +keyServerWidget + + + keyServerWidget + + + + 0 + 0 + 465 + 252 + + + + + unnamed + + + 0 + + + + tabWidget2 + + + + tab + + + Import + + + + unnamed + + + + textLabel2 + + + NoFrame + + + Plain + + + Text to search or ID of the key to import: + + + <qt><b>Text to search or ID of the key to import:</b><br /> + <p>There are multiple ways to search for a key, you can use a text or partial text search (example: entering Phil or Zimmerman will bring up all keys in which Phil or Zimmerman shows up) or you can search by the ID's of the key. Key ID's are strings of letters and numbers that uniquely identify a key (example: searching for 0xED7585F4 would bring up the key associated with that ID).</p> + </qt> + + + + + kCBimportks + + + <b>Key Server Drop Down Dialog:</b> +Allows the user to select the Key Server which will be used to import PGP/GnuPG keys into the local keyring. + + + + + kLEimportid + + + + + textLabel1 + + + Key server: + + + <qt><b>Key Server:</b><br /> <p>A Key Server is a centralized repository of PGP/GnuPG keys connected to the Internet which can be conveniently accessed in order to obtain or deposit keys. Select from the drop down list to specify which key server should be used.</p> <p>Often these keys are held by people whom the user has never met and as such the authenticity is dubious at best. Refer to the GnuPG manual covering "Web-of-Trust" relationships to find out how GnuPG works around the problem of verifying authenticity.</p> </qt> + + + + + Buttonsearch + + + &Search + + + true + + + + + Buttonimport + + + &Import + + + + + spacer2_2_3 + + + Vertical + + + Expanding + + + + 20 + 16 + + + + + + spacer2_2_2_2 + + + Vertical + + + Expanding + + + + 20 + 20 + + + + + + spacer4_2_2 + + + Horizontal + + + Expanding + + + + 160 + 20 + + + + + + cBproxyI + + + false + + + Honor HTTP proxy: + + + + + kLEproxyI + + + false + + + + 7 + 0 + 0 + 0 + + + + true + + + + + + + tab + + + Export + + + + unnamed + + + + Buttonexport + + + &Export + + + <qt><b>Export:</b><br /> + <p>Depressing this key will export the specified key to the specified server.</p> + </qt> + + + + + spacer4_3 + + + Horizontal + + + Expanding + + + + 250 + 20 + + + + + + kCBexportks + + + + + kCBexportkey + + + + + textLabel3 + + + Key server: + + + + + textLabel4 + + + Key to be exported: + + + <qt><b>Key to be exported:</b><br /> + <p>This allows the user to specify the key from the drop down list that will be exported to the key server selected.</p> + </qt> + + + + + spacer2_4 + + + Vertical + + + Expanding + + + + 20 + 40 + + + + + + spacer2_3_2 + + + Vertical + + + Expanding + + + + 20 + 30 + + + + + + kLEproxyE + + + false + + + + 7 + 0 + 0 + 0 + + + + true + + + + + cBproxyE + + + false + + + Honor HTTP proxy: + + + + + exportAttributes + + + Export attributes (photo id) + + + true + + + + + + + + + diff --git a/kgpg/keyservers.cpp b/kgpg/keyservers.cpp new file mode 100644 index 0000000..1afd9d3 --- /dev/null +++ b/kgpg/keyservers.cpp @@ -0,0 +1,574 @@ +/*************************************************************************** + keyservers.cpp - description + ------------------- + begin : Tue Nov 26 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "kgpgsettings.h" +#include "searchres.h" +#include "detailedconsole.h" +#include "keyservers.h" + +keyServer::keyServer(QWidget *parent, const char *name,bool modal,bool autoClose):KDialogBase( Swallow, i18n("Key Server"), Close, Close, parent, name,modal) +{ + autoCloseWindow=autoClose; + config=new KSimpleConfig ("kgpgrc"); + page=new keyServerWidget(); + setMainWidget(page); + + syncCombobox(); + page->kLEimportid->setFocus(); + + connect(page->Buttonimport,SIGNAL(clicked()),this,SLOT(slotImport())); + connect(page->Buttonsearch,SIGNAL(clicked()),this,SLOT(slotSearch())); + connect(page->Buttonexport,SIGNAL(clicked()),this,SLOT(slotPreExport())); + connect(this,SIGNAL(okClicked()),this,SLOT(slotOk())); + + connect(page->cBproxyI,SIGNAL(toggled(bool)),this,SLOT(slotEnableProxyI(bool))); + connect(page->cBproxyE,SIGNAL(toggled(bool)),this,SLOT(slotEnableProxyE(bool))); + + connect(page->kLEimportid, SIGNAL( textChanged ( const QString & )), this, SLOT( slotTextChanged( const QString &))); + page->cBproxyI->setChecked(KGpgSettings::useProxy()); + page->cBproxyE->setChecked(KGpgSettings::useProxy()); + const char *httpproxy = getenv("http_proxy"); + if (httpproxy) { + page->cBproxyI->setEnabled(true); + page->cBproxyE->setEnabled(true); + page->kLEproxyI->setText(httpproxy); + page->kLEproxyE->setText(httpproxy); + } + + + KProcIO *encid=new KProcIO(QTextCodec::codecForLocale()); + *encid << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-keys"; + QObject::connect(encid, SIGNAL(readReady(KProcIO *)),this, SLOT(slotprocread(KProcIO *))); + encid->start(KProcess::NotifyOnExit,true); + page->Buttonimport->setEnabled( !page->kLEimportid->text().isEmpty()); + page->Buttonsearch->setEnabled( !page->kLEimportid->text().isEmpty()); +setMinimumSize(sizeHint()); +} + + +keyServer::~keyServer() +{} + + +void keyServer::slotTextChanged( const QString &text) +{ + page->Buttonimport->setEnabled( !text.isEmpty()); + page->Buttonsearch->setEnabled( !text.isEmpty()); + +} +void keyServer::slotEnableProxyI(bool on) +{ + page->kLEproxyI->setEnabled(on); +} + +void keyServer::slotEnableProxyE(bool on) +{ + page->kLEproxyE->setEnabled(on); +} + + + +void keyServer::slotprocread(KProcIO *p) +{ + ///////////////////////////////////////////////////////////////// extract encryption keys + bool dead; + QString tst; + //QPixmap pixkeySingle(KGlobal::iconLoader()->loadIcon("kgpg_key1",KIcon::Small,20)); + while (p->readln(tst)!=-1) { + //tst=tst.stripWhiteSpace(); + if (tst.startsWith("pub")) { + const QString trust=tst.section(':',1,1); + QString id=QString("0x"+tst.section(':',4,4).right(8)); + switch( trust[0] ) { + case 'i': + dead=true; + break; + case 'd': + dead=true; + break; + case 'r': + dead=true; + break; + case 'e': + dead=true; + break; + default: + dead=false; + break; + } + tst=tst.section(':',9,9); + if (tst.length()>35) { + tst.remove(35,tst.length()); + tst+="..."; + } + if ((!dead) && (!tst.isEmpty())) +// page->kCBexportkey->insertItem(pixkeySingle,id+": "+tst); + page->kCBexportkey->insertItem(id+": "+tst); + } + } +} + +void keyServer::slotSearch() +{ + if (page->kCBimportks->currentText().isEmpty()) + return; + + if (page->kLEimportid->text().isEmpty()) { + KMessageBox::sorry(this,i18n("You must enter a search string.")); + return; + } + + //listpop = new KeyServer( this,"result",WType_Dialog | WShowModal); + + dialogServer=new KDialogBase(KDialogBase::Swallow, i18n("Import Key From Keyserver"), KDialogBase::Ok | KDialogBase::Close,KDialogBase::Ok,this,0,true); + + dialogServer->setButtonText(KDialogBase::Ok,i18n("&Import")); + dialogServer->enableButtonOK(false); + listpop=new searchRes(); + listpop->kLVsearch->setColumnWidthMode(0,QListView::Manual); + listpop->kLVsearch->setColumnWidthMode(1,QListView::Manual); + listpop->kLVsearch->setColumnWidth(0,150); + listpop->kLVsearch->setColumnWidth(1,130); + listpop->statusText->setText(i18n("Connecting to the server...")); + connect(listpop->kLVsearch,SIGNAL(selectionChanged()),this,SLOT(transferKeyID())); + connect(dialogServer,SIGNAL(okClicked()),this,SLOT(preimport())); + connect(listpop->kLVsearch,SIGNAL(doubleClicked(QListViewItem *,const QPoint &,int)),dialogServer,SIGNAL(okClicked())); + + connect(dialogServer,SIGNAL(closeClicked()),this,SLOT(handleQuit())); + connect( listpop , SIGNAL( destroyed() ) , this, SLOT( abortSearch())); + count=0; + cycle=false; + readmessage=QString::null; + searchproc=new KProcIO(QTextCodec::codecForLocale()); + QString keyserv=page->kCBimportks->currentText(); + *searchproc<<"gpg"<<"--utf8-strings"; + if (page->cBproxyI->isChecked()) { + searchproc->setEnvironment("http_proxy",page->kLEproxyI->text()); + *searchproc<< "--keyserver-options"<<"honor-http-proxy"; + } else + *searchproc<< "--keyserver-options"<<"no-honor-http-proxy"; + *searchproc<<"--keyserver"<kLEimportid->text().stripWhiteSpace(); + + keyNumbers=0; + QObject::connect(searchproc, SIGNAL(processExited(KProcess *)),this, SLOT(slotsearchresult(KProcess *))); + QObject::connect(searchproc, SIGNAL(readReady(KProcIO *)),this, SLOT(slotsearchread(KProcIO *))); + searchproc->start(KProcess::NotifyOnExit,true); + QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); + dialogServer->setMainWidget(listpop); + listpop->setMinimumSize(listpop->sizeHint()); + listpop->setMinimumWidth(550); + dialogServer->exec(); +} + +void keyServer::handleQuit() +{ + if (searchproc->isRunning()) + { + QApplication::restoreOverrideCursor(); + disconnect(searchproc,0,0,0); + searchproc->kill(); + } + dialogServer->close(); +} + + +void keyServer::abortSearch() +{ + if (dialogServer) { + delete dialogServer; + dialogServer=0L; + } +} + +void keyServer::preimport() +{ + transferKeyID(); + if (listpop->kLEID->text().isEmpty()) { + KMessageBox::sorry(this,i18n("You must choose a key.")); + return; + } + page->kLEimportid->setText(listpop->kLEID->text()); + dialogServer->close(); + slotImport(); +} + +void keyServer::transferKeyID() +{ + if (!listpop->kLVsearch->firstChild()) + return; + QString kid,keysToSearch; + listpop->kLEID->clear(); + QPtrList< QListViewItem >searchList=listpop->kLVsearch->selectedItems(); + + for ( uint i = 0; i < searchList.count(); ++i ) + { + if ( searchList.at(i) ) + keysToSearch.append(" "+searchList.at(i)->text(3)); + } +// kdDebug(2100)<kLEID->setText(keysToSearch.stripWhiteSpace()); +} + +void keyServer::slotsearchresult(KProcess *) +{ + QString nb; + dialogServer->enableButtonOK(true); + QApplication::restoreOverrideCursor(); + nb=nb.setNum(keyNumbers); + //listpop->kLVsearch->setColumnText(0,i18n("Found %1 matching keys").arg(nb)); + listpop->statusText->setText(i18n("Found %1 matching keys").arg(nb)); + + if (listpop->kLVsearch->firstChild()!=NULL) { + listpop->kLVsearch->setSelected(listpop->kLVsearch->firstChild(),true); + listpop->kLVsearch->setCurrentItem(listpop->kLVsearch->firstChild()); + transferKeyID(); + } +} + +void keyServer::slotsearchread(KProcIO *p) +{ + QString required; + QString keymail,keyname; + while (p->readln(required,true)!=-1) { + //required=QString::fromUtf8(required); + + if (required.find("keysearch.prompt")!=-1) { + if (count<4) + p->writeStdin("N"); + else { + p->writeStdin("Q"); + p->closeWhenDone(); + } + required=QString::null; + } + + if (required.find("GOT_IT")!=-1) { + count++; + required=QString::null; + } + + if (required.find("(")==0) { + cycle=true; + QString fullname=required.remove(0,required.find(")")+1).stripWhiteSpace(); + if (fullname.find("<")!=-1) { + keymail=fullname.section('<',-1,-1); + if (keymail.endsWith(">")) keymail.truncate(keymail.length()-1); + keyname=fullname.section('<',0,0); + } else { + keymail=QString::null; + keyname=fullname; + } + kitem=new KListViewItem(listpop->kLVsearch,keyname,keymail,QString::null,QString::null); + keyNumbers++; + count=0; + required=QString::null; + } + + if ((cycle) && (!required.isEmpty())) { + QString subkey=required.stripWhiteSpace(); + if (subkey.find(" key ")!=-1 && subkey.at(0).isDigit ()) + { + QString kid=subkey.section(",",0,0).stripWhiteSpace(); + kid=kid.right(8); + kitem->setText(3,kid); + QString creation=subkey.section("created",1,1); + if (creation.startsWith(":")) creation=creation.right(creation.length()-1); + kitem->setText(2,creation); + cycle=false; + } + else + { + if (subkey.find("<")!=-1) { + keymail=subkey.section('<',-1,-1); + if (keymail.endsWith(">")) keymail.truncate(keymail.length()-1); + keyname=subkey.section('<',0,0); + } else { + keymail=QString::null; + keyname=subkey; + } + KListViewItem *subk = new KListViewItem(kitem,keyname,keymail,QString::null,QString::null); + subk->setSelectable(false); + } + required=QString::null; + } + } +} + +void keyServer::slotPreExport() +{ + slotExport(QStringList(page->kCBexportkey->currentText().section(':', 0, 0))); +} + +void keyServer::slotExport(QStringList keyIds) +{ + if (page->kCBexportks->currentText().isEmpty()) + return; + readmessage=QString::null; + exportproc=new KProcIO(QTextCodec::codecForLocale()); + QString keyserv=page->kCBexportks->currentText(); + + *exportproc<<"gpg"<<"--utf8-strings"; + if (!page->exportAttributes->isChecked()) + *exportproc<<"--export-options"<<"no-include-attributes"; + + if (page->cBproxyE->isChecked()) { + exportproc->setEnvironment("http_proxy",page->kLEproxyE->text()); + *exportproc<< "--keyserver-options"<<"honor-http-proxy"; + } else + *exportproc<< "--keyserver-options"<<"no-honor-http-proxy"; + *exportproc << "--status-fd=2" << "--keyserver" << keyserv << "--send-keys" << keyIds; + + QObject::connect(exportproc, SIGNAL(processExited(KProcess *)),this, SLOT(slotexportresult(KProcess *))); + QObject::connect(exportproc, SIGNAL(readReady(KProcIO *)),this, SLOT(slotimportread(KProcIO *))); + exportproc->start(KProcess::NotifyOnExit,true); + QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); + importpop = new QDialog( this,0,true,Qt::WDestructiveClose); + QVBoxLayout *vbox=new QVBoxLayout(importpop,3); + QLabel *tex=new QLabel(importpop); + tex->setText(i18n("Connecting to the server...")); + QPushButton *Buttonabort=new QPushButton(i18n("&Abort"),importpop); + vbox->addWidget(tex); + vbox->addWidget(Buttonabort); + importpop->setMinimumWidth(250); + importpop->adjustSize(); + importpop->show(); + connect(importpop,SIGNAL(destroyed ()),this,SLOT(abortExport())); + connect(Buttonabort,SIGNAL(clicked ()),importpop,SLOT(close())); +} + +void keyServer::abortExport() +{ + QApplication::restoreOverrideCursor(); + if (exportproc->isRunning()) + { + disconnect(exportproc,0,0,0); + exportproc->kill(); + } +} + +void keyServer::slotexportresult(KProcess*) +{ + QApplication::restoreOverrideCursor(); + KMessageBox::information(0,readmessage); + if (importpop) + delete importpop; +} + + +void keyServer::slotImport() +{ + if (page->kCBimportks->currentText().isEmpty()) + return; + if (page->kLEimportid->text().isEmpty()) { + KMessageBox::sorry(this,i18n("You must enter a search string.")); + return; + } + readmessage=QString::null; + importproc=new KProcIO(QTextCodec::codecForLocale()); + QString keyserv=page->kCBimportks->currentText(); + + *importproc<<"gpg"<<"--utf8-strings"; + if (page->cBproxyI->isChecked()) { + importproc->setEnvironment("http_proxy",page->kLEproxyI->text()); + *importproc<< "--keyserver-options"<<"honor-http-proxy"; + } else + *importproc<< "--keyserver-options"<<"no-honor-http-proxy"; + + *importproc<<"--status-fd=2"<<"--keyserver"<kLEimportid->text(); + keyNames=keyNames.stripWhiteSpace(); + keyNames=keyNames.simplifyWhiteSpace(); + while (!keyNames.isEmpty()) { + QString fkeyNames=keyNames.section(' ',0,0); + keyNames.remove(0,fkeyNames.length()); + keyNames=keyNames.stripWhiteSpace(); + *importproc<start(KProcess::NotifyOnExit,true); + importproc->closeWhenDone(); + QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); + importpop = new QDialog( this,0,true,Qt::WDestructiveClose); + QVBoxLayout *vbox=new QVBoxLayout(importpop,3); + QLabel *tex=new QLabel(importpop); + tex->setText(i18n("Connecting to the server...")); + QPushButton *Buttonabort=new QPushButton(i18n("&Abort"),importpop); + vbox->addWidget(tex); + vbox->addWidget(Buttonabort); + importpop->setMinimumWidth(250); + importpop->adjustSize(); + importpop->show(); + connect(Buttonabort,SIGNAL(clicked()),importpop,SLOT(close())); + connect(importpop,SIGNAL(destroyed ()),this,SLOT(abortImport())); +} + +void keyServer::abortImport() +{ + QApplication::restoreOverrideCursor(); + if (importproc->isRunning()) + { + disconnect(importproc,0,0,0); + importproc->kill(); + emit importFinished(QString::null); + } + if (autoCloseWindow) close(); +} + +void keyServer::slotimportresult(KProcess*) +{ + QApplication::restoreOverrideCursor(); + QString importedNb,importedNbSucess,importedNbProcess,resultMessage, parsedOutput,importedNbUnchanged,importedNbSig; + QString notImportesNbSec,importedNbMissing,importedNbRSA,importedNbUid,importedNbSub,importedNbRev,readNbSec; + QString importedNbSec,dupNbSec; + + parsedOutput=readmessage; + QStringList importedKeys; + + while (parsedOutput.find("IMPORTED")!=-1) { + parsedOutput.remove(0,parsedOutput.find("IMPORTED")+8); + importedKeys+=parsedOutput.section("\n",0,0).stripWhiteSpace(); + } + + if (readmessage.find("IMPORT_RES")!=-1) { + importedNb=readmessage.section("IMPORT_RES",-1,-1); + importedNb=importedNb.stripWhiteSpace(); + importedNbProcess=importedNb.section(" ",0,0); + importedNbMissing=importedNb.section(" ",1,1); + importedNbSucess=importedNb.section(" ",2,2); + importedNbRSA=importedNb.section(" ",3,3); + importedNbUnchanged=importedNb.section(" ",4,4); + importedNbUid=importedNb.section(" ",5,5); + importedNbSub=importedNb.section(" ",6,6); + importedNbSig=importedNb.section(" ",7,7); + importedNbRev=importedNb.section(" ",8,8); + readNbSec=importedNb.section(" ",9,9); + importedNbSec=importedNb.section(" ",10,10); + dupNbSec=importedNb.section(" ",11,11); + notImportesNbSec=importedNb.section(" ",12,12); + resultMessage=i18n("%n key processed.
","%n keys processed.
",importedNbProcess.toULong()); + if (importedNbUnchanged!="0") + resultMessage+=i18n("One key unchanged.
","%n keys unchanged.
",importedNbUnchanged.toULong()); + if (importedNbSig!="0") + resultMessage+=i18n("One signature imported.
","%n signatures imported.
",importedNbSig.toULong()); + if (importedNbMissing!="0") + resultMessage+=i18n("One key without ID.
","%n keys without ID.
",importedNbMissing.toULong()); + if (importedNbRSA!="0") + resultMessage+=i18n("One RSA key imported.
","%n RSA keys imported.
",importedNbRSA.toULong()); + if (importedNbUid!="0") + resultMessage+=i18n("One user ID imported.
","%n user IDs imported.
",importedNbUid.toULong()); + if (importedNbSub!="0") + resultMessage+=i18n("One subkey imported.
","%n subkeys imported.
",importedNbSub.toULong()); + if (importedNbRev!="0") + resultMessage+=i18n("One revocation certificate imported.
","%n revocation certificates imported.
",importedNbRev.toULong()); + if (readNbSec!="0") + resultMessage+=i18n("One secret key processed.
","%n secret keys processed.
",readNbSec.toULong()); + if (importedNbSec!="0") + resultMessage+=i18n("One secret key imported.
","%n secret keys imported.
",importedNbSec.toULong()); + if (dupNbSec!="0") + resultMessage+=i18n("One secret key unchanged.
","%n secret keys unchanged.
",dupNbSec.toULong()); + if (notImportesNbSec!="0") + resultMessage+=i18n("One secret key not imported.
","%n secret keys not imported.
",notImportesNbSec.toULong()); + if (importedNbSucess!="0") + resultMessage+=i18n("One key imported:
","%n keys imported:
",importedNbSucess.toULong()); + } else + resultMessage=i18n("No key imported... \nCheck detailed log for more infos"); + + QString lastID=QString("0x"+importedKeys.last().section(" ",0,0).right(8)); + if (!lastID.isEmpty()) + { + //kdDebug(2100)<<"++++++++++imported key"<hide(); + (void) new KDetailedInfo(0,"import_result",resultMessage,readmessage,importedKeys); + + if (importpop) + delete importpop; + if (autoCloseWindow) close(); +} + +void keyServer::slotimportread(KProcIO *p) +{ + QString required; + while (p->readln(required,true)!=-1) + readmessage+=required+"\n"; +} + +void keyServer::syncCombobox() +{ + config->setGroup("Servers"); + QString serverList=config->readEntry("Server_List"); + + QString optionsServer=KgpgInterface::getGpgSetting("keyserver", KGpgSettings::gpgConfigPath()); + + page->kCBexportks->clear(); + page->kCBimportks->clear(); + + if (!optionsServer.isEmpty()) { + page->kCBexportks->insertItem(optionsServer); + page->kCBimportks->insertItem(optionsServer); + } + else if ( serverList.isEmpty() ) + serverList = "hkp://wwwkeys.eu.pgp.net,hkp://search.keyserver.net,hkp://wwwkeys.pgp.net,hkp://pgp.dtype.org,hkp://wwwkeys.us.pgp.net"; // same as ini kgpgoptions.cpp + + page->kCBexportks->insertStringList(QStringList::split(",",serverList)); + page->kCBimportks->insertStringList(QStringList::split(",",serverList)); +} + +void keyServer::slotOk() +{ + accept(); +} + + +#include "keyservers.moc" diff --git a/kgpg/keyservers.h b/kgpg/keyservers.h new file mode 100644 index 0000000..e17af85 --- /dev/null +++ b/kgpg/keyservers.h @@ -0,0 +1,81 @@ +/*************************************************************************** + keyservers.h - description + ------------------- + begin : Tue Nov 26 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KEYSERVERS_H +#define KEYSERVERS_H + +#include +#include "keyserver.h" + +class KListViewItem; +class KSimpleConfig; +class KProcIO; +class KProcess; + +class searchRes; + +class keyServer : public KDialogBase +{ + Q_OBJECT +public: + keyServer(QWidget *parent=0, const char *name=0,bool modal=false,bool autoClose=false); + ~keyServer(); + keyServerWidget *page; + +public slots: + void abortImport(); + void abortExport(); + void abortSearch(); + void transferKeyID(); + void slotsearchread(KProcIO *p); + void slotOk(); + void syncCombobox(); + void slotImport(); + void slotSearch(); + void slotimportresult(KProcess*); + void slotexportresult(KProcess*); + void slotimportread(KProcIO *p); + void slotprocread(KProcIO *p); + void slotPreExport(); + void slotExport(QStringList keyIds); + void preimport(); + void slotsearchresult(KProcess *); + void slotEnableProxyI(bool on); + void slotEnableProxyE(bool on); + void handleQuit(); + void slotTextChanged( const QString &text); + +private: + + QDialog *importpop; + KSimpleConfig *config; + uint keyNumbers; + QString readmessage; + KProcIO *importproc,*exportproc; + KProcIO *searchproc; + searchRes *listpop; + int count; + bool cycle,autoCloseWindow; + KListViewItem *kitem; + KDialogBase *dialogServer; + +signals: + void importFinished(QString); +}; + +#endif // KEYSERVERS_H + diff --git a/kgpg/kgpg.cpp b/kgpg/kgpg.cpp new file mode 100644 index 0000000..a14ab64 --- /dev/null +++ b/kgpg/kgpg.cpp @@ -0,0 +1,1057 @@ +/*************************************************************************** + kgpg.cpp - description + ------------------- + begin : Mon Nov 18 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kgpgeditor.h" + +#include "kgpg.h" +#include "kgpgsettings.h" +#include "listkeys.h" +#include "keyserver.h" +#include "keyservers.h" +#include "popuppublic.h" +#include "kgpgview.h" +#include "kgpglibrary.h" +#include "kgpgwizard.h" + +MyView::MyView( QWidget *parent, const char *name ) + : QLabel( parent, name ) +{ + setBackgroundMode( X11ParentRelative ); + openTasks=0; + + KAction *saveDecrypt=new KAction(i18n("&Decrypt && Save File"),"decrypted",0,this, SLOT(decryptDroppedFile()),this,"decrypt_file"); + KAction *showDecrypt=new KAction(i18n("&Show Decrypted File"),"edit",0,this, SLOT(showDroppedFile()),this,"show_file"); + KAction *encrypt=new KAction(i18n("&Encrypt File"),"encrypted",0,this, SLOT(encryptDroppedFile()),this,"encrypt_file"); + KAction *sign=new KAction(i18n("&Sign File"), "signature",0,this, SLOT(signDroppedFile()),this,"sign_file"); + //QToolTip::add(this,i18n("KGpg drag & drop encryption applet")); + + readOptions(); + resize(24,24); + setPixmap( KSystemTray::loadIcon("kgpg_docked")); + setAcceptDrops(true); + + droppopup=new QPopupMenu(); + showDecrypt->plug(droppopup); + saveDecrypt->plug(droppopup); + + udroppopup=new QPopupMenu(); + encrypt->plug(udroppopup); + sign->plug(udroppopup); + QToolTip::add(this, i18n("KGpg - encryption tool")); +} + +MyView::~MyView() +{ + + delete droppopup; + droppopup = 0; + delete udroppopup; + udroppopup = 0; +} + + +void MyView::clipEncrypt() +{ + popupPublic *dialoguec=new popupPublic(0, "public_keys", 0,false,goDefaultKey); + connect(dialoguec,SIGNAL(selectedKey(QStringList,QStringList,bool,bool)),this,SLOT(encryptClipboard(QStringList,QStringList,bool,bool))); + dialoguec->exec(); + delete dialoguec; +} + +void MyView::clipDecrypt() +{ + QString clippie=kapp->clipboard()->text(clipboardMode).stripWhiteSpace(); + droppedtext(clippie,false); +} + +void MyView::clipSign(bool openEditor) +{ + QString clippie=kapp->clipboard()->text(clipboardMode).stripWhiteSpace(); + if (!clippie.isEmpty()) { + KgpgApp *kgpgtxtedit = new KgpgApp(0, "editor",WDestructiveClose,goDefaultKey); + connect(this,SIGNAL(setFont(QFont)),kgpgtxtedit,SLOT(slotSetFont(QFont))); + connect(kgpgtxtedit,SIGNAL(encryptFiles(KURL::List)),this,SLOT(encryptFiles(KURL::List))); + if (!openEditor) + connect(kgpgtxtedit->view,SIGNAL(verifyFinished()),kgpgtxtedit,SLOT(closeWindow())); + kgpgtxtedit->view->editor->setText(clippie); + kgpgtxtedit->view->clearSign(); + kgpgtxtedit->show(); + + } else + KMessageBox::sorry(this,i18n("Clipboard is empty.")); +} + +void MyView::encryptDroppedFolder() +{ + compressionScheme=0; + kgpgfoldertmp=new KTempFile(QString::null); + kgpgfoldertmp->setAutoDelete(true); + if (KMessageBox::warningContinueCancel(0,i18n("KGpg will now create a temporary archive file:
%1 to process the encryption. The file will be deleted after the encryption is finished.
").arg(kgpgfoldertmp->name()),i18n("Temporary File Creation"),KStdGuiItem::cont(),"FolderTmpFile")==KMessageBox::Cancel) + return; + + dialogue=new popupPublic(0,"Public keys",droppedUrls.first().fileName(),true,goDefaultKey); + + QHButtonGroup *bGroup = new QHButtonGroup(dialogue->plainPage()); + (void) new QLabel(i18n("Compression method for archive:"),bGroup); + KComboBox *optionbx=new KComboBox(bGroup); + optionbx->insertItem(i18n("Zip")); + optionbx->insertItem(i18n("Gzip")); + optionbx->insertItem(i18n("Bzip2")); + bGroup->show(); + connect(dialogue,SIGNAL(keyListFilled ()),dialogue,SLOT(slotSetVisible())); + connect(optionbx,SIGNAL(activated (int)),this,SLOT(slotSetCompression(int))); + connect(dialogue,SIGNAL(selectedKey(QStringList,QStringList,bool,bool)),this,SLOT(startFolderEncode(QStringList,QStringList,bool,bool))); + dialogue->CBshred->setEnabled(false); + dialogue->exec(); + dialogue=0L; +} + +void MyView::slotSetCompression(int cp) +{ +compressionScheme=cp; +} + +void MyView::startFolderEncode(QStringList selec,QStringList encryptOptions,bool ,bool symetric) +{ +QString extension; + +if (compressionScheme==0) + extension=".zip"; + else if (compressionScheme==1) + extension=".tar.gz"; + else + extension=".tar.bz2"; + +if (encryptOptions.find("armor")!=encryptOptions.end () ) + extension+=".asc"; + else if (KGpgSettings::pgpExtension()) + extension+=".pgp"; + else + extension+=".gpg"; + +KURL encryptedFile(droppedUrls.first().path()+extension); +QFile encryptedFolder(droppedUrls.first().path()+extension); +if (encryptedFolder.exists()) { + dialogue->hide(); + KIO::RenameDlg *over=new KIO::RenameDlg(0,i18n("File Already Exists"),QString::null,encryptedFile.path(),KIO::M_OVERWRITE); + if (over->exec()==QDialog::Rejected) + { + delete over; + return; + } + encryptedFile=over->newDestURL(); + delete over; + dialogue->show(); /////// strange, but if dialogue is hidden, the passive popup is not displayed... + } + +pop = new KPassivePopup(); + pop->setView(i18n("Processing folder compression and encryption"),i18n("Please wait..."),KGlobal::iconLoader()->loadIcon("kgpg",KIcon::Desktop)); + pop->setAutoDelete(false); + pop->show(); + kapp->processEvents(); + dialogue->slotAccept(); + dialogue=0L; + + KArchive *arch; + if (compressionScheme==0) + arch=new KZip(kgpgfoldertmp->name()); + else if (compressionScheme==1) + arch=new KTar(kgpgfoldertmp->name(), "application/x-gzip"); + else + arch=new KTar(kgpgfoldertmp->name(), "application/x-bzip2"); + + if (!arch->open( IO_WriteOnly )) { + KMessageBox::sorry(0,i18n("Unable to create temporary file")); + delete arch; + return; + } + arch->addLocalDirectory (droppedUrls.first().path(),droppedUrls.first().fileName()); + arch->close(); + delete arch; + + KgpgInterface *folderprocess=new KgpgInterface(); + folderprocess->KgpgEncryptFile(selec,KURL(kgpgfoldertmp->name()),encryptedFile,encryptOptions,symetric); + connect(folderprocess,SIGNAL(encryptionfinished(KURL)),this,SLOT(slotFolderFinished(KURL))); + connect(folderprocess,SIGNAL(errormessage(QString)),this,SLOT(slotFolderFinishedError(QString))); +} + +void MyView::slotFolderFinished(KURL) +{ + delete pop; + delete kgpgfoldertmp; +} + +void MyView::slotFolderFinishedError(QString errmsge) +{ + delete pop; + delete kgpgfoldertmp; + KMessageBox::sorry(0,errmsge); +} + +void MyView::busyMessage(QString mssge,bool reset) +{ +if (reset) openTasks=0; +if (!mssge.isEmpty()) +{ +openTasks++; +QToolTip::remove(this); +QToolTip::add(this, mssge); +setMovie(QMovie(locate("appdata","pics/kgpg_docked.gif"))); +} +else openTasks--; + +//kdDebug(2100) << "Emit message: "<slotFileEnc(droppedUrls,opts,QStringList::split(" ",KGpgSettings::fileKey()),goDefaultKey); + } else + lib->slotFileEnc(droppedUrls,QString::null,QString::null,goDefaultKey); +} + +void MyView::encryptFiles(KURL::List urls) +{ +droppedUrls=urls; +encryptDroppedFile(); +} + +void MyView::shredDroppedFile() +{ +KDialogBase *shredConfirm=new KDialogBase( this, "confirm_shred", true,i18n("Shred Files"),KDialogBase::Ok | KDialogBase::Cancel); +QWidget *page = new QWidget(shredConfirm); +shredConfirm->setMainWidget(page); +QBoxLayout *layout=new QBoxLayout(page,QBoxLayout::TopToBottom,0); +layout->setAutoAdd(true); + +(void) new KActiveLabel( i18n("Do you really want to shred these files?").arg(i18n( "

You must be aware that shredding is not secure on all file systems, and that parts of the file may have been saved in a temporary file or in the spooler of your printer if you previously opened it in an editor or tried to print it. Only works on files (not on folders).

")),page); +KListBox *lb=new KListBox(page); +lb->insertStringList(droppedUrls.toStringList()); +if (shredConfirm->exec()==QDialog::Accepted) + { + KgpgLibrary *lib=new KgpgLibrary(this); + connect(lib,SIGNAL(systemMessage(QString,bool)),this,SLOT(busyMessage(QString,bool))); + lib->shredprocessenc(droppedUrls); + } +delete shredConfirm; +} + + +void MyView::slotVerifyFile() +{ + /////////////////////////////////// check file signature + if (droppedUrl.isEmpty()) + return; + + QString sigfile=QString::null; + ////////////////////////////////////// try to find detached signature. + if (!droppedUrl.fileName().endsWith(".sig")) { + sigfile=droppedUrl.path()+".sig"; + QFile fsig(sigfile); + if (!fsig.exists()) { + sigfile=droppedUrl.path()+".asc"; + QFile fsig(sigfile); + ////////////// if no .asc or .sig signature file included, assume the file is internally signed + if (!fsig.exists()) + sigfile=QString::null; + } + } else { + sigfile=droppedUrl.path(); + droppedUrl=KURL(sigfile.left(sigfile.length()-4)); + } + + ///////////////////////// pipe gpg command + KgpgInterface *verifyFileProcess=new KgpgInterface(); + verifyFileProcess->KgpgVerifyFile(droppedUrl,KURL(sigfile)); + connect (verifyFileProcess,SIGNAL(verifyquerykey(QString)),this,SLOT(importSignature(QString))); +} + +void MyView::importSignature(QString ID) +{ + keyServer *kser=new keyServer(0,"server_dialog",false); + kser->page->kLEimportid->setText(ID); + kser->slotImport(); +} + +void MyView::signDroppedFile() +{ + ////////////////////////////////////// create a detached signature for a chosen file + if (droppedUrl.isEmpty()) + return; + + QString signKeyID; + ////////////////// select a private key to sign file --> listkeys.cpp + KgpgSelKey *opts=new KgpgSelKey(0,"select_secret"); + if (opts->exec()==QDialog::Accepted) + signKeyID=opts->getkeyID(); + else { + delete opts; + return; + } + delete opts; + QStringList Options; + if (KGpgSettings::asciiArmor()) + Options<<"--armor"; + if (KGpgSettings::pgpCompatibility()) + Options<<"--pgp6"; + KgpgInterface *signFileProcess=new KgpgInterface(); + signFileProcess->KgpgSignFile(signKeyID,droppedUrl,Options); +} + +void MyView::decryptDroppedFile() +{ + //bool isFolder=false; // droppedUrls + KURL swapname; + + if (!droppedUrls.first().isLocalFile()) { + showDroppedFile(); + decryptNextFile(); + } + + QString oldname=droppedUrls.first().fileName(); + if (oldname.endsWith(".gpg") || oldname.endsWith(".asc") || oldname.endsWith(".pgp")) + oldname.truncate(oldname.length()-4); + else + oldname.append(".clear"); + /* + if (oldname.endsWith(".tar.gz")) { + isFolder=true; + kgpgFolderExtract=new KTempFile(QString::null,".tar.gz"); + kgpgFolderExtract->setAutoDelete(true); + swapname=KURL(kgpgFolderExtract->name()); + if (KMessageBox::warningContinueCancel(0,i18n("The file to decrypt is an archive. KGpg will create a temporary unencrypted archive file:
%1 before processing the archive extraction. This temporary file will be deleted after the decryption is finished.
").arg(kgpgFolderExtract->name()),i18n("Temporary File Creation"),KStdGuiItem::cont(),"FolderTmpDecFile")==KMessageBox::Cancel) + return; + } else*/ { + swapname=KURL(droppedUrls.first().directory(0,0)+oldname); + QFile fgpg(swapname.path()); + if (fgpg.exists()) { + KIO::RenameDlg *over=new KIO::RenameDlg(0,i18n("File Already Exists"),QString::null,swapname.path(),KIO::M_OVERWRITE); + if (over->exec()==QDialog::Rejected) + { + delete over; + decryptNextFile(); + return; + } + swapname=over->newDestURL(); + delete over; + } + } + KgpgLibrary *lib=new KgpgLibrary(this); + lib->slotFileDec(droppedUrls.first(),swapname,KGpgSettings::customDecrypt()); + connect(lib,SIGNAL(importOver(QStringList)),this,SIGNAL(importedKeys(QStringList))); + connect(lib,SIGNAL(systemMessage(QString,bool)),this,SLOT(busyMessage(QString,bool))); +// if (isFolder) + connect(lib,SIGNAL(decryptionOver()),this,SLOT(decryptNextFile())); + +} + +void MyView::decryptNextFile() +{ +if (droppedUrls.count()>1) +{ +droppedUrls.pop_front(); +decryptDroppedFile(); +} +} + +void MyView::unArchive() +{ + KTar compressedFolder(kgpgFolderExtract->name(),"application/x-gzip"); + if (!compressedFolder.open( IO_ReadOnly )) { + KMessageBox::sorry(0,i18n("Unable to read temporary archive file")); + return; + } + const KArchiveDirectory *archiveDirectory=compressedFolder.directory(); + //KURL savePath=KURL::getURL(droppedUrl,this,i18n("")); + KURLRequesterDlg *savePath=new KURLRequesterDlg(droppedUrl.directory(false),i18n("Extract to: "),0,"extract"); + savePath->fileDialog()->setMode(KFile::Directory); + if (!savePath->exec()==QDialog::Accepted) { + delete kgpgFolderExtract; + return; + } + archiveDirectory->KArchiveDirectory::copyTo(savePath->selectedURL().path()); + compressedFolder.close(); + delete savePath; + delete kgpgFolderExtract; +} + + +void MyView::showDroppedFile() +{ +kdDebug(2100)<<"------Show dropped file"<view->editor->slotDroppedFile(droppedUrls.first()); + connect(kgpgtxtedit,SIGNAL(encryptFiles(KURL::List)),this,SLOT(encryptFiles(KURL::List))); + connect(this,SIGNAL(setFont(QFont)),kgpgtxtedit,SLOT(slotSetFont(QFont))); + connect(kgpgtxtedit,SIGNAL(refreshImported(QStringList)),this,SIGNAL(importedKeys(QStringList))); + connect(kgpgtxtedit->view->editor,SIGNAL(refreshImported(QStringList)),this,SIGNAL(importedKeys(QStringList))); + kgpgtxtedit->show(); +} + + +void MyView::droppedfile (KURL::List url) +{ + droppedUrls=url; + droppedUrl=url.first(); + if (KMimeType::findByURL(droppedUrl)->name()=="inode/directory") { + encryptDroppedFolder(); + //KMessageBox::sorry(0,i18n("Sorry, only file operations are currently supported.")); + return; + } + if (!droppedUrl.isLocalFile()) { + showDroppedFile(); + return; + } + + if ((droppedUrl.path().endsWith(".asc")) || (droppedUrl.path().endsWith(".pgp")) || (droppedUrl.path().endsWith(".gpg"))) { + switch (KGpgSettings::encryptedDropEvent()) { + case KGpgSettings::EnumEncryptedDropEvent::DecryptAndSave: + decryptDroppedFile(); + break; + case KGpgSettings::EnumEncryptedDropEvent::DecryptAndOpen: + showDroppedFile(); + break; + case KGpgSettings::EnumEncryptedDropEvent::Ask: + droppopup->exec(QCursor::pos ()); + kdDebug(2100)<<"Drop menu--------"<exec(QCursor::pos ()); + break; + } +} + + +void MyView::droppedtext (QString inputText,bool allowEncrypt) +{ + + if (inputText.startsWith("-----BEGIN PGP MESSAGE")) { + KgpgApp *kgpgtxtedit = new KgpgApp(0, "editor",WDestructiveClose,goDefaultKey); + connect(kgpgtxtedit,SIGNAL(encryptFiles(KURL::List)),this,SLOT(encryptFiles(KURL::List))); + connect(this,SIGNAL(setFont(QFont)),kgpgtxtedit,SLOT(slotSetFont(QFont))); + kgpgtxtedit->view->editor->setText(inputText); + kgpgtxtedit->view->slotdecode(); + kgpgtxtedit->show(); + return; + } + if (inputText.startsWith("-----BEGIN PGP PUBLIC KEY")) { + int result=KMessageBox::warningContinueCancel(0,i18n("

The dropped text is a public key.
Do you want to import it ?

"),i18n("Warning")); + if (result==KMessageBox::Cancel) + return; + else { + KgpgInterface *importKeyProcess=new KgpgInterface(); + importKeyProcess->importKey(inputText); + connect(importKeyProcess,SIGNAL(importfinished(QStringList)),this,SIGNAL(importedKeys(QStringList))); + return; + } + } + if (inputText.startsWith("-----BEGIN PGP SIGNED MESSAGE")) { + clipSign(false); + return; + } + if (allowEncrypt) clipEncrypt(); + else KMessageBox::sorry(this,i18n("No encrypted text found.")); +} + + +void MyView::dragEnterEvent(QDragEnterEvent *e) +{ + e->accept (KURLDrag::canDecode(e) || QTextDrag::canDecode (e)); +} + + +void MyView::dropEvent (QDropEvent *o) +{ + KURL::List list; + QString text; + if ( KURLDrag::decode( o, list ) ) + droppedfile(list); + else if ( QTextDrag::decode(o, text) ) + { + QApplication::clipboard()->setText(text,clipboardMode); + droppedtext(text); + } +} + + +void MyView::readOptions() +{ + clipboardMode=QClipboard::Clipboard; + if ( KGpgSettings::useMouseSelection() && kapp->clipboard()->supportsSelection()) + clipboardMode=QClipboard::Selection; + + if (KGpgSettings::firstRun()) { + firstRun(); + } else { + QString path = KGpgSettings::gpgConfigPath(); + if (path.isEmpty()) { + if (KMessageBox::questionYesNo(0,i18n("You have not set a path to your GnuPG config file.
This may cause some surprising results in KGpg's execution.
Would you like to start KGpg's Wizard to fix this problem?
"),QString::null,i18n("Start Wizard"),i18n("Do Not Start"))==KMessageBox::Yes) + startWizard(); + } else { + QStringList groups=KgpgInterface::getGpgGroupNames(path); + if (!groups.isEmpty()) + KGpgSettings::setGroups(groups.join(",")); + } + } +} + + +void MyView::firstRun() +{ + KProcIO *p=new KProcIO(); + *p<<"gpg"<<"--no-tty"<<"--list-secret-keys"; + p->start(KProcess::Block); //// start gnupg so that it will create a config file + startWizard(); +} + + +static QString getGpgHome() +{ + char *env=getenv("GNUPGHOME"); + QString gpgHome(env ? env : QDir::homeDirPath()+"/.gnupg/"); + + gpgHome.replace("//", "/"); + + if(!gpgHome.endsWith("/")) + gpgHome.append('/'); + + KStandardDirs::makeDir(gpgHome, 0700); + return gpgHome; +} + + +void MyView::startWizard() +{ + kdDebug(2100)<<"Starting Wizard"<The GnuPG configuration file was not found. Please make sure you have GnuPG installed. Should KGpg try to create a config file ?"),QString::null,i18n("Create Config"),i18n("Do Not Create"))==KMessageBox::Yes) { + confPath=gpgHome+"options"; + QFile file(confPath); + if ( file.open( IO_WriteOnly ) ) { + QTextStream stream( &file ); + stream <<"# GnuPG config file created by KGpg"<< "\n"; + file.close(); + } + } else { + wiz->text_optionsfound->setText(i18n("The GnuPG configuration file was not found. Please make sure you have GnuPG installed and give the path to the config file.")); + confPath=QString::null; + } + } + } + + int gpgVersion=KgpgInterface::getGpgVersion(); + if (gpgVersion<120) wiz->txtGpgVersion->setText(i18n("Your GnuPG version seems to be older than 1.2.0. Photo Id's and Key Groups will not work properly. Please consider upgrading GnuPG (http://gnupg.org).")); + else wiz->txtGpgVersion->setText(QString::null); + + wiz->kURLRequester1->setURL(confPath); + /* + wiz->kURLRequester2->setURL(KGlobalSettings::desktopPath()); + wiz->kURLRequester2->setMode(2);*/ + + FILE *fp,*fp2; + QString tst,tst2,name,trustedvals="idre-"; + QString firstKey=QString::null; + char line[300]; + bool counter=false; + + fp = popen("gpg --display-charset=utf-8 --no-tty --with-colon --list-secret-keys", "r"); + while ( fgets( line, sizeof(line), fp)) { + tst=QString::fromUtf8(line); + if (tst.startsWith("sec")) { + name=KgpgInterface::checkForUtf8(tst.section(':',9,9)); + if (!name.isEmpty()) { + fp2 = popen("gpg --display-charset=utf-8 --no-tty --with-colon --list-keys "+QFile::encodeName(tst.section(':',4,4)), "r"); + while ( fgets( line, sizeof(line), fp2)) { + tst2=QString::fromUtf8(line); + if (tst2.startsWith("pub") && (trustedvals.find(tst2.section(':',1,1))==-1)) { + counter=true; + wiz->CBdefault->insertItem(tst.section(':',4,4).right(8)+": "+name); + if (firstKey.isEmpty()) + firstKey=tst.section(':',4,4).right(8)+": "+name; + break; + } + } + pclose(fp2); + } + } + } + pclose(fp); + wiz->CBdefault->setCurrentItem(firstKey); + //connect(wiz->pushButton4,SIGNAL(clicked()),this,SLOT(slotGenKey())); + if (!counter) + connect(wiz->finishButton(),SIGNAL(clicked()),this,SLOT(slotGenKey())); + else { + wiz->textGenerate->hide(); + wiz->setTitle(wiz->page_4,i18n("Step Three: Select your Default Private Key")); + connect(wiz->finishButton(),SIGNAL(clicked()),this,SLOT(slotSaveOptionsPath())); + } + connect(wiz->nextButton(),SIGNAL(clicked()),this,SLOT(slotWizardChange())); + connect( wiz , SIGNAL( destroyed() ) , this, SLOT( slotWizardClose())); + connect(wiz,SIGNAL(helpClicked()),this,SLOT(help())); + + wiz->setFinishEnabled(wiz->page_4,true); + wiz->show(); +} + +void MyView::slotWizardChange() +{ + QString tst,name; + char line[300]; + FILE *fp; + + if (wiz->indexOf(wiz->currentPage())==2) { + QString defaultID=KgpgInterface::getGpgSetting("default-key",wiz->kURLRequester1->url()); + if (defaultID.isEmpty()) + return; + fp = popen("gpg --display-charset=utf-8 --no-tty --with-colon --list-secret-keys "+QFile::encodeName(defaultID), "r"); + while ( fgets( line, sizeof(line), fp)) { + tst=QString::fromUtf8(line); + if (tst.startsWith("sec")) { + name=KgpgInterface::checkForUtf8(tst.section(':',9,9)); + wiz->CBdefault->setCurrentItem(tst.section(':',4,4).right(8)+": "+name); + } + } + pclose(fp); + } +} + +void MyView::installShred() +{ + KURL path; + path.setPath(KGlobalSettings::desktopPath()); + path.addPath("shredder.desktop"); + KDesktopFile configl2(path.path(), false); + if (configl2.isImmutable() ==false) { + configl2.setGroup("Desktop Entry"); + configl2.writeEntry("Type", "Application"); + configl2.writeEntry("Name",i18n("Shredder")); + configl2.writeEntry("Icon","editshred"); + configl2.writeEntry("Exec","kgpg -X %U"); + } +} + +void MyView::slotSaveOptionsPath() +{ +qWarning("Save wizard settings..."); + if (wiz->checkBox1->isChecked()) installShred(); + + KGpgSettings::setAutoStart( wiz->checkBox2->isChecked() ); + + KGpgSettings::setGpgConfigPath( wiz->kURLRequester1->url() ); + KGpgSettings::setFirstRun( false ); + + QString defaultID=wiz->CBdefault->currentText().section(':',0,0); +/* if (!defaultID.isEmpty()) { + KGpgSettings::setDefaultKey(defaultID); + }*/ + + KGpgSettings::writeConfig(); + + emit updateDefault("0x"+defaultID); + if (wiz) + delete wiz; +} + +void MyView::slotWizardClose() +{ + wiz=0L; +} + +void MyView::slotGenKey() +{ + slotSaveOptionsPath(); + emit createNewKey(); +} + +void MyView::about() +{ + KAboutApplication dialog(kapp->aboutData());//_aboutData); + dialog.exec(); +} + +void MyView::help() +{ + kapp->invokeHelp(0,"kgpg"); +} + +kgpgapplet::kgpgapplet(QWidget *parent, const char *name) + : KSystemTray(parent,name) +{ + w=new MyView(this); + w->show(); + KPopupMenu *conf_menu=contextMenu(); + KgpgEncryptClipboard = new KAction(i18n("&Encrypt Clipboard"), "kgpg", 0,w, SLOT(clipEncrypt()),actionCollection(),"clip_encrypt"); + KgpgDecryptClipboard = new KAction(i18n("&Decrypt Clipboard"), 0, 0,w, SLOT(clipDecrypt()),actionCollection(),"clip_decrypt"); + KgpgSignClipboard = new KAction(i18n("&Sign/Verify Clipboard"), "signature", 0,w, SLOT(clipSign()),actionCollection(),"clip_sign"); + KAction *KgpgOpenEditor; + if (KGpgSettings::leftClick()==KGpgSettings::EnumLeftClick::KeyManager) + KgpgOpenEditor = new KAction(i18n("&Open Editor"), "edit", 0,parent, SLOT(slotOpenEditor()),actionCollection(),"kgpg_editor"); + else + KgpgOpenEditor = new KAction(i18n("&Open Key Manager"), "kgpg", 0,this, SLOT(slotOpenKeyManager()),actionCollection(),"kgpg_editor"); + + KAction *KgpgOpenServer = new KAction(i18n("&Key Server Dialog"), "network", 0,this, SLOT(slotOpenServerDialog()),actionCollection(),"kgpg_server"); + KAction *KgpgPreferences=KStdAction::preferences(this, SLOT(showOptions()), actionCollection()); + + connect (conf_menu,SIGNAL(aboutToShow()),this,SLOT(checkMenu())); + + KgpgEncryptClipboard->plug(conf_menu); + KgpgDecryptClipboard->plug(conf_menu); + KgpgSignClipboard->plug(conf_menu); + KgpgOpenEditor->plug(conf_menu); + KgpgOpenServer->plug(conf_menu); + conf_menu->insertSeparator(); + KgpgPreferences->plug(conf_menu); +} + + +void kgpgapplet::checkMenu() +{ + KgpgDecryptClipboard->setEnabled(false); + if ((kapp->clipboard()->text(w->clipboardMode).isEmpty())) + { + KgpgEncryptClipboard->setEnabled(false); + KgpgSignClipboard->setEnabled(false); + } + else + { + KgpgEncryptClipboard->setEnabled(true); + if (kapp->clipboard()->text(w->clipboardMode).stripWhiteSpace().startsWith("-----BEGIN")) + KgpgDecryptClipboard->setEnabled(true); + KgpgSignClipboard->setEnabled(true); + } +} + +void kgpgapplet::showOptions() +{ +QByteArray data; +if (!kapp->dcopClient()->send("kgpg", "KeyInterface", "showOptions()",data)) +kdDebug(2100) <<"there was some error using DCOP."<dcopClient()->send("kgpg", "KeyInterface", "showKeyManager()",data)) +kdDebug(2100) <<"there was some error using DCOP."<dcopClient()->send("kgpg", "KeyInterface", "showKeyServer()",data)) +kdDebug(2100) <<"there was some error using DCOP."<keysList2->saveLayout(KGlobal::config(),"KeyView"); + KGpgSettings::setPhotoProperties(s_keyManager->photoProps->currentItem()); + KGpgSettings::setShowTrust(s_keyManager->sTrust->isChecked()); + KGpgSettings::setShowExpi(s_keyManager->sExpi->isChecked()); + KGpgSettings::setShowCreat(s_keyManager->sCreat->isChecked()); + KGpgSettings::setShowSize(s_keyManager->sSize->isChecked()); + KGpgSettings::writeConfig(); + KSimpleConfig ("kgpgrc").sync(); + quit(); +} + +void KgpgAppletApp::wizardOver(QString defaultKeyId) +{ + if (defaultKeyId.length()==10) + s_keyManager->slotSetDefaultKey(defaultKeyId); + s_keyManager->show(); + s_keyManager->raise(); +} + +int KgpgAppletApp::newInstance() +{ + kdDebug(2100)<<"New instance"<show(); + } else { + kdDebug(2100) << "Starting KGpg"<refreshkey(); + + if (KGpgSettings::leftClick()==KGpgSettings::EnumLeftClick::KeyManager) + kgpg_applet=new kgpgapplet(s_keyManager,"kgpg_systrayapplet"); + else + { + kgpg_applet=new kgpgapplet(s_keyManager->s_kgpgEditor,"kgpg_systrayapplet"); + } + connect(s_keyManager,SIGNAL(encryptFiles(KURL::List)),kgpg_applet->w,SLOT(encryptFiles(KURL::List))); + connect(s_keyManager,SIGNAL(installShredder()),kgpg_applet->w,SLOT(installShred())); + connect(s_keyManager->s_kgpgEditor,SIGNAL(encryptFiles(KURL::List)),kgpg_applet->w,SLOT(encryptFiles(KURL::List))); + + connect( kgpg_applet, SIGNAL(quitSelected()), this, SLOT(slotHandleQuit())); + connect(s_keyManager,SIGNAL(readAgainOptions()),kgpg_applet->w,SLOT(readOptions())); + connect(kgpg_applet->w,SIGNAL(updateDefault(QString)),this,SLOT(wizardOver(QString))); + connect(kgpg_applet->w,SIGNAL(createNewKey()),s_keyManager,SLOT(slotgenkey())); + connect(s_keyManager,SIGNAL(fontChanged(QFont)),kgpg_applet->w,SIGNAL(setFont(QFont))); + connect(kgpg_applet->w,SIGNAL(importedKeys(QStringList)),s_keyManager->keysList2,SLOT(slotReloadKeys(QStringList))); + kgpg_applet->show(); + + + if (!gpgPath.isEmpty()) { + if ((KgpgInterface::getGpgBoolSetting("use-agent",gpgPath)) && (!getenv("GPG_AGENT_INFO"))) + KMessageBox::sorry(0,i18n("The use of GnuPG Agent is enabled in GnuPG's configuration file (%1).
" + "However, the agent does not seem to be running. This could result in problems with signing/decryption.
" + "Please disable GnuPG Agent from KGpg settings, or fix the agent.
").arg(gpgPath)); + } + + } + goHome=s_keyManager->actionCollection()->action("go_default_key")->shortcut(); + kgpg_applet->w->goDefaultKey=goHome; + + //////////////////////// parsing of command line args + if (args->isSet("k")!=0) { + s_keyManager->show(); + KWin::setOnDesktop( s_keyManager->winId() , KWin::currentDesktop() ); //set on the current desktop + KWin::deIconifyWindow( s_keyManager->winId()); //de-iconify window + s_keyManager->raise(); // set on top + } else + if (args->count()>0) { + kdDebug(2100) << "KGpg: found files"<count();ct++) + urlList.append(args->url(ct)); + + if (urlList.empty()) + return 0; + + kgpg_applet->w->droppedUrl=urlList.first(); + + bool directoryInside=false; + QStringList lst=urlList.toStringList(); + for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) { + if (KMimeType::findByURL(KURL( *it ))->name()=="inode/directory") + directoryInside=true; + } + + if ((directoryInside) && (lst.count()>1)) { + KMessageBox::sorry(0,i18n("Unable to perform requested operation.\nPlease select only one folder, or several files, but do not mix files and folders.")); + return 0; + } + + kgpg_applet->w->droppedUrls=urlList; + + if (args->isSet("e")!=0) { + if (!directoryInside) + kgpg_applet->w->encryptDroppedFile(); + else + kgpg_applet->w->encryptDroppedFolder(); + } else if (args->isSet("X")!=0) { + if (!directoryInside) + kgpg_applet->w->shredDroppedFile(); + else + KMessageBox::sorry(0,i18n("Cannot shred folder.")); + } else if (args->isSet("s")!=0) { + if (!directoryInside) + kgpg_applet->w->showDroppedFile(); + else + KMessageBox::sorry(0,i18n("Cannot decrypt and show folder.")); + } else if (args->isSet("S")!=0) { + if (!directoryInside) + kgpg_applet->w->signDroppedFile(); + else + KMessageBox::sorry(0,i18n("Cannot sign folder.")); + } else if (args->isSet("V")!=0) { + if (!directoryInside) + kgpg_applet->w->slotVerifyFile(); + else + KMessageBox::sorry(0,i18n("Cannot verify folder.")); + } else if (kgpg_applet->w->droppedUrl.fileName().endsWith(".sig")) + kgpg_applet->w->slotVerifyFile(); + else + kgpg_applet->w->decryptDroppedFile(); + } + return 0; +} + + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +void MyView::encryptClipboard(QStringList selec,QStringList encryptOptions,bool,bool symmetric) +{ + if (kapp->clipboard()->text(clipboardMode).isEmpty()) { + KPassivePopup::message(i18n("Clipboard is empty."),QString::null,KGlobal::iconLoader()->loadIcon("kgpg",KIcon::Desktop),this); + return; + } + if (KGpgSettings::pgpCompatibility()) + encryptOptions<<"--pgp6"; + encryptOptions<<"--armor"; + + if (symmetric) selec.clear(); + KgpgInterface *txtEncrypt=new KgpgInterface(); + connect (txtEncrypt,SIGNAL(txtencryptionfinished(QString)),this,SLOT(slotSetClip(QString))); + connect (txtEncrypt,SIGNAL(txtencryptionstarted()),this,SLOT(slotPassiveClip())); + txtEncrypt->KgpgEncryptText(kapp->clipboard()->text(clipboardMode),selec,encryptOptions); +} + +void MyView::slotPassiveClip() +{ +QString newtxt=kapp->clipboard()->text(clipboardMode); +if (newtxt.length()>300) + newtxt=QString(newtxt.left(250).stripWhiteSpace())+"...\n"+QString(newtxt.right(40).stripWhiteSpace()); + + newtxt.replace(QRegExp("<"),"<"); ///// disable html tags + newtxt.replace(QRegExp("\n"),"
"); + +pop = new KPassivePopup( this); + pop->setView(i18n("Encrypted following text:"),newtxt,KGlobal::iconLoader()->loadIcon("kgpg",KIcon::Desktop)); + pop->setTimeout(3200); + pop->show(); + QRect qRect(QApplication::desktop()->screenGeometry()); + int iXpos=qRect.width()/2-pop->width()/2; + int iYpos=qRect.height()/2-pop->height()/2; + pop->move(iXpos,iYpos); +} + +void MyView::slotSetClip(QString newtxt) +{ + if (newtxt.isEmpty()) return; + QApplication::clipboard()->setText(newtxt,clipboardMode);//,QClipboard::Clipboard); QT 3.1 only +} + + + +///////////////////////////////////////////////////////////////////////////// + +#include "kgpg.moc" + + diff --git a/kgpg/kgpg.desktop b/kgpg/kgpg.desktop new file mode 100644 index 0000000..e5b844f --- /dev/null +++ b/kgpg/kgpg.desktop @@ -0,0 +1,123 @@ +# KDE Config File +[Desktop Entry] +Type=Application +Exec=kgpg %U +Icon=kgpg +DocPath=kgpg/index.html +MimeType=application/pgp-encrypted;application/pgp-signature;application/pgp-keys; +GenericName=Encryption Tool +GenericName[ar]=أداة للتشفير +GenericName[bg]=Програма за шифроване +GenericName[br]=Ostilh enrinegadur +GenericName[bs]=Alat za šifrovanje +GenericName[ca]=Eina de xifrat +GenericName[cs]=Šifrovací nástroj +GenericName[cy]=Erfyn Cêl-ysgrifo +GenericName[da]=Krypteringsværktøj +GenericName[de]=Verschlüsselungsprogramm +GenericName[el]=Εργαλείο κρυπτογράφησης +GenericName[eo]=Ilo por Ĉifrado +GenericName[es]=Herramienta de cifrado +GenericName[et]=Krüptimisvahend +GenericName[eu]=Zifraketa Tresna +GenericName[fa]=میلۀ رمزبندی +GenericName[fi]=Salaustyökalu +GenericName[fr]=Outil de cryptage +GenericName[ga]=Uirlis Chriptithe +GenericName[he]=כלי הצפנה +GenericName[hi]=एनक्रिप्शन औज़ार +GenericName[hu]=Titkosítóeszköz +GenericName[is]=Dulritunartól +GenericName[it]=Strumento di crittografia +GenericName[ja]=暗号化ツール +GenericName[ka]=დაშიფვრის ხელსაწყო +GenericName[kk]=Шифрлау құралы +GenericName[km]=ឧបករណ៍​អ៊ិនគ្រីប +GenericName[lt]=Šifravimo įrankis +GenericName[mk]=Алатка за криптирање +GenericName[nb]=Krypteringsverktøy +GenericName[nds]=Verslötel-Warktüüch +GenericName[ne]=गुप्तीकरण उपकरण +GenericName[nl]=Cryptografisch programma +GenericName[nn]=Krypteringsverktøy +GenericName[pa]=ਇੰਕਰਿਪਸ਼ਨ ਸੰਦ +GenericName[pl]=Narzędzie do szyfrowania +GenericName[pt]=Ferramenta de Cifra +GenericName[pt_BR]=Ferramenta de Criptografia +GenericName[ro]=Utilitar de criptare +GenericName[ru]=Шифрование +GenericName[sk]=Šifrovací nástroj +GenericName[sl]=Šifrirno orodje +GenericName[sr]=Алат за шифровање +GenericName[sr@Latn]=Alat za šifrovanje +GenericName[sv]=Krypteringsverktyg +GenericName[ta]=சங்கேத கருவி +GenericName[tg]=Асбоби Рамзкунонӣ +GenericName[tr]=Şifreleme Aracı +GenericName[uk]=Засіб для шифрування +GenericName[zh_CN]=加密工具 +GenericName[zh_TW]=加密工具 +Comment=A GnuPG frontend +Comment[ar]=واجهة لـ GnuPG +Comment[bg]=Клиент за GnuPG +Comment[bs]=Alat za GnuPG +Comment[ca]=Un entorn gràfic per GnuPG +Comment[cs]=Rozhraní pro GnuPG +Comment[cy]=Blaen-wyneb GnuPG +Comment[da]=En GnuPG-forende +Comment[de]=Eine Benutzeroberfläche für GnuPG +Comment[el]=Λογισμικό κρυπτογράφησης (GnuPG) +Comment[eo]=Fasado por GnuPG +Comment[es]=Interfaz para GnuPG +Comment[et]=GnuPG kasutajaliides +Comment[eu]=GnuPGren bitarteko bat +Comment[fa]=GnuPGنرم‌افزار نهایی +Comment[fi]=GnuPG-käyttöliittymä +Comment[fr]=Une interface à GnuPG +Comment[ga]=Comhéadan do GnuPG +Comment[he]=מנשק גרפי של GnuPG +Comment[hi]=एक ग्नू-पीजी फ्रन्टएण्ड +Comment[hu]=Grafikus kezelőprogram a GnuPG-hez +Comment[is]=Viðmót á GnuPG +Comment[it]=Interfaccia grafica per GnuPG +Comment[ja]=GnuPG のフロントエンド +Comment[ka]=GnuPG გრაფიკული გარსი +Comment[kk]=GnuPG интерфейсі +Comment[km]=កម្មវិធី​ខាងមុខ GnuPG +Comment[lt]=GnuPG naudotojo sąsaja +Comment[nb]=En GnuPG grenseflate +Comment[nds]=En GnuPG-Böversiet +Comment[ne]=GnuPG फ्रन्टेन्ड +Comment[nl]=Een programma om GnuPG-cryptografie en -ondertekening te gebruiken +Comment[nn]=Ei GnuPG-grenseflate +Comment[pa]=GnuPG ਮੁੱਖੜਾ +Comment[pl]=Interfejs do GnuPG +Comment[pt]=Uma interface para o GnuPG +Comment[pt_BR]=Uma interface para o GnuPG +Comment[ro]=Interfaţă grafică pentru GnuPG +Comment[ru]=Управление ключами GPG +Comment[sk]=Rozhranie pre GnuPG +Comment[sl]=Vmesnik za GnuPG +Comment[sr]=Интерфејс за GnuPG +Comment[sr@Latn]=Interfejs za GnuPG +Comment[sv]=Gränssnitt till GnuPG +Comment[ta]=GnuPG முன் அமைப்பு +Comment[tg]=Пешохири GnuPG +Comment[tr]=Bir GnuPG arayüzü +Comment[uk]=Інтерфейс до GnuPG +Comment[uz]=GnuPG uchun grafik interfeys +Comment[uz@cyrillic]=GnuPG учун график интерфейс +Comment[wa]=Ene eterface po GnuPG +Comment[zh_CN]=GnuPG 前端 +Comment[zh_TW]=GnuPG 前端軟體 +Terminal=false +Name=KGpg +Name[hi]=के-जीपीजी +Name[nl]=KGPG +Name[sv]=Kgpg +Name[ta]= KGpg + +X-KDE-autostart-after=panel +X-KDE-autostart-condition=kgpgrc:User Interface:AutoStart:false + +Categories=Qt;KDE;Utility;X-KDE-Utilities-PIM; diff --git a/kgpg/kgpg.h b/kgpg/kgpg.h new file mode 100644 index 0000000..aff3d18 --- /dev/null +++ b/kgpg/kgpg.h @@ -0,0 +1,168 @@ +/*************************************************************************** + kgpg.h - description + ------------------- + begin : Mon Nov 18 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGAPPLET_H +#define KGPGAPPLET_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include + + +class QPopupMenu; +class KTempFile; +class KAboutData; +class KPassivePopup; +class KgpgWizard; +class popupPublic; + +class MyView : public QLabel +{ + + Q_OBJECT + +public: + MyView( QWidget *parent = 0, const char *name = 0); + ~MyView(); + + KURL droppedUrl; + KURL::List droppedUrls; + KTempFile *kgpgfoldertmp; + KShortcut goDefaultKey; + QClipboard::Mode clipboardMode; + +private: + QPopupMenu *droppopup,*udroppopup; + KAboutData *_aboutData; + QStringList customDecrypt; + KgpgWizard *wiz; + KPassivePopup *pop; + KTempFile *kgpgFolderExtract; + int compressionScheme,openTasks; + popupPublic *dialogue; + +public slots: + void busyMessage(QString mssge,bool reset=false); + void encryptDroppedFile(); + void decryptDroppedFile(); + void slotVerifyFile(); + void signDroppedFile(); + void showDroppedFile (); + void clipDecrypt(); + void clipSign(bool openEditor=true); + void clipEncrypt(); + void shredDroppedFile(); + void encryptDroppedFolder(); + void startFolderEncode(QStringList selec,QStringList encryptOptions,bool ,bool symetric); + void slotFolderFinished(KURL); + void slotFolderFinishedError(QString errmsge); + void encryptFiles(KURL::List urls); + void installShred(); + +private slots: + void slotWizardClose(); + void startWizard(); + void slotWizardChange(); + void slotSaveOptionsPath(); + void slotGenKey(); + void importSignature(QString ID); + void slotSetClip(QString newtxt); + void slotPassiveClip(); + void encryptClipboard(QStringList selec,QStringList encryptOptions,bool,bool symmetric); + void help(); + void about(); + void firstRun(); + void readOptions(); + void droppedfile (KURL::List); + void droppedtext (QString inputText, bool allowEncrypt=true); + void unArchive(); + void slotSetCompression(int cp); + void decryptNextFile(); + +protected: + virtual void dragEnterEvent(QDragEnterEvent *); + virtual void dropEvent (QDropEvent*); + +protected slots: + + +signals: + void setFont(QFont); + void readAgain2(); + void createNewKey(); + void updateDefault(QString); + void importedKeys(QStringList); +}; + +class kgpgapplet : public KSystemTray//KUniqueApplication +{ + Q_OBJECT + +public: + kgpgapplet( QWidget *parent = 0, const char *name = 0); + /** destructor */ + ~kgpgapplet(); + MyView *w; + +private: + KSystemTray *kgpgapp; + KAction *KgpgEncryptClipboard, *KgpgDecryptClipboard, *KgpgSignClipboard; + +private slots: + void slotOpenKeyManager(); + void slotOpenServerDialog(); + void showOptions(); + void checkMenu(); +}; + +class KCmdLineArgs; + +class KgpgAppletApp : public KUniqueApplication +{ + Q_OBJECT + friend class kgpgapplet; +public: + KgpgAppletApp(); + ~KgpgAppletApp(); + int newInstance (); + KURL::List urlList; + bool running; + KShortcut goHome; + +protected: + KCmdLineArgs *args; +private: + kgpgapplet *kgpg_applet; + class listKeys *s_keyManager; + +private slots: + void slotHandleQuit(); + void wizardOver(QString defaultKeyId); +}; + +#endif // KGPGAPPLET_H + diff --git a/kgpg/kgpg.kcfg b/kgpg/kgpg.kcfg new file mode 100644 index 0000000..a7ade9f --- /dev/null +++ b/kgpg/kgpg.kcfg @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + false + + + + + + + true + + + + false + + + + false + + + + false + + + + false + + + + false + + + + + + + + + + + + + false + + + + false + + + + false + + + + + + + + + + + + + + + + + + Disable + + + + true + + + + + + + true + + + + true + + + + true + + + + true + + + + + + + false + + + + false + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Disabled + + + + + + + + + Disabled + + + + + + + true + + + + + + + 144,255,0 + + + + 30,30,30 + + + + 255,255,255 + + + + 172,0,0 + + + + + + + KGlobalSettings::fixedFont() + + + + + + + false + + + diff --git a/kgpg/kgpg.rc b/kgpg/kgpg.rc new file mode 100644 index 0000000..5b72f56 --- /dev/null +++ b/kgpg/kgpg.rc @@ -0,0 +1,27 @@ + + + + + + + + + + + + &View + + + + Si&gnature + + + + + + &Settings + + + + + diff --git a/kgpg/kgpg_anim.gif b/kgpg/kgpg_anim.gif new file mode 100644 index 0000000..d296d2e Binary files /dev/null and b/kgpg/kgpg_anim.gif differ diff --git a/kgpg/kgpg_blank.png b/kgpg/kgpg_blank.png new file mode 100644 index 0000000..c326d0b Binary files /dev/null and b/kgpg/kgpg_blank.png differ diff --git a/kgpg/kgpg_docked.gif b/kgpg/kgpg_docked.gif new file mode 100644 index 0000000..1fe5ac4 Binary files /dev/null and b/kgpg/kgpg_docked.gif differ diff --git a/kgpg/kgpg_docked.png b/kgpg/kgpg_docked.png new file mode 100644 index 0000000..ddcee25 Binary files /dev/null and b/kgpg/kgpg_docked.png differ diff --git a/kgpg/kgpg_fill.png b/kgpg/kgpg_fill.png new file mode 100644 index 0000000..576bbea Binary files /dev/null and b/kgpg/kgpg_fill.png differ diff --git a/kgpg/kgpgeditor.cpp b/kgpg/kgpgeditor.cpp new file mode 100644 index 0000000..9db9ce3 --- /dev/null +++ b/kgpg/kgpgeditor.cpp @@ -0,0 +1,554 @@ +/*************************************************************************** + kgpgeditor.cpp - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "kgpgsettings.h" +#include "kgpgeditor.h" +#include "sourceselect.h" +#include "keyexport.h" +#include "keyserver.h" +#include "keyservers.h" +#include "kgpg.h" +#include "kgpgview.h" +#include "listkeys.h" +#include "kgpglibrary.h" + +KgpgApp::KgpgApp(QWidget *parent, const char *name, WFlags f,KShortcut goHome,bool mainWindow):KMainWindow(parent, name,f) +{ + isMainWindow=mainWindow; + textEncoding=QString::null; + readOptions(); + goDefaultKey=goHome; + // call inits to invoke all other construction parts + + initActions(); + initView(); + + slotSetFont(KGpgSettings::font()); + setupGUI(( ToolBar | Keys | StatusBar | Save | Create ), "kgpg.rc"); + setAutoSaveSettings("Editor",true); + +} + +KgpgApp::~KgpgApp() +{ +delete view; +} + +void KgpgApp::slotOptions() +{ +QByteArray data; +if (!kapp->dcopClient()->send("kgpg", "KeyInterface", "showOptions()",data)) +kdDebug(2100) <<"there was some error using DCOP."<dcopClient()->send("kgpg", "KeyInterface", "showKeyManager()",data)) +kdDebug(2100) <<"there was some error using DCOP."<ref(); + KMainWindow::closeEvent( e ); + } + else e->accept(); +} + +void KgpgApp::closeWindow() +{ +if (view->windowAutoClose) close(); +kdDebug(2100) << "Close requested"<editor->setFont (myFont); +} + + +void KgpgApp::slotSetCharset() +{ +//////// work in progress +//if (encodingAction->isChecked()) +//view->editor->setText(QString::fromUtf8(view->editor->text().ascii())); +//else +{ +if (checkEncoding(QTextCodec::codecForLocale ())) return; +view->editor->setText(view->editor->text().utf8()); +} +} + +void KgpgApp::initView() +{ + //////////////////////////////////////////////////////////////////// + // create the main widget here that is managed by KTMainWindow's view-region and + // connect the widget to your document to display document contents. + + view = new KgpgView(this,0); + // doc->addView(view); + connect(view,SIGNAL(resetEncoding(bool)),this,SLOT(slotResetEncoding(bool))); + setCentralWidget(view); + setCaption(i18n("Untitled"),false); /// doc->URL().fileName(),false); + +} + +void KgpgApp::slotFileQuit() +{ + saveOptions(); + exit(1); +} + +void KgpgApp::slotResetEncoding(bool enc) +{ +//kdDebug(2100)<<"Resetting encoding--------------------"<setChecked(enc); +//if (enc) slotSetCharset(); +} + +void KgpgApp::slotFileNew() +{ + ////// delete all text from editor + + view->editor->setText(QString::null); + editRedo->setEnabled(false); + editUndo->setEnabled(false); + setCaption(i18n("Untitled"), false); + fileSave->setEnabled(false); + Docname=QString::null; + slotResetEncoding(false); +} + +void KgpgApp::slotFilePreEnc() +{ + QStringList opts; + KURL::List urls=KFileDialog::getOpenURLs(QString::null, + i18n("*|All Files"), this, i18n("Open File to Encode")); + if (urls.isEmpty()) + return; + emit encryptFiles(urls); +} + +void KgpgApp::slotFilePreDec() +{ + + KURL url=KFileDialog::getOpenURL(QString::null, + i18n("*|All Files"), this, i18n("Open File to Decode")); + + if (url.isEmpty()) + return; + QString oldname=url.fileName(); + + QString newname; + + if (oldname.endsWith(".gpg") || oldname.endsWith(".asc") || oldname.endsWith(".pgp")) + oldname.truncate(oldname.length()-4); + else + oldname.append(".clear"); + oldname.prepend(url.directory(0,0)); + + KDialogBase *popn=new KDialogBase( KDialogBase::Swallow, i18n("Decrypt File To"), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, this, "file_decrypt",true); + + SrcSelect *page=new SrcSelect(); + popn->setMainWidget(page); + page->newFilename->setURL(oldname); + page->newFilename->setMode(KFile::File); + page->newFilename->setCaption(i18n("Save File")); + + page->checkClipboard->setText(i18n("Editor")); + page->resize(page->minimumSize()); + popn->resize(popn->minimumSize()); + if (popn->exec()==QDialog::Accepted) { + if (page->checkFile->isChecked()) + newname=page->newFilename->url(); + } else { + delete popn; + return; + } + delete popn; + + + if (!newname.isEmpty()) { + QFile fgpg(newname); + if (fgpg.exists()) { + KIO::RenameDlg *over=new KIO::RenameDlg(0,i18n("File Already Exists"),QString::null,newname,KIO::M_OVERWRITE); + if (over->exec()==QDialog::Rejected) + { + delete over; + return; + } + newname=over->newDestURL().path(); + delete over; + } + KgpgLibrary *lib=new KgpgLibrary(this); + lib->slotFileDec(url,KURL(newname), customDecrypt); + connect(lib,SIGNAL(importOver(QStringList)),this,SIGNAL(refreshImported(QStringList))); + } else + openEncryptedDocumentFile(url); +} + +void KgpgApp::slotFileOpen() +{ + KEncodingFileDialog::Result loadResult; + loadResult=KEncodingFileDialog::getOpenURLAndEncoding(QString::null,QString::null,QString::null,this); + KURL url=loadResult.URLs.first(); + textEncoding=loadResult.encoding; + + if(!url.isEmpty()) { + openDocumentFile(url,textEncoding); + Docname=url; + fileSave->setEnabled(false); + //fileSaveAs->setEnabled(true); + setCaption(url.fileName(), false); + } + +} + +bool KgpgApp::checkEncoding(QTextCodec *codec) +{ + ///////////// KGlobal::locale()->encoding()->name() +return codec->canEncode(view->editor->text()); +} + +void KgpgApp::slotFileSave() +{ + QString filn=Docname.path(); + if (filn.isEmpty()) { + slotFileSaveAs(); + return; + } + QTextCodec*cod=QTextCodec::codecForName (textEncoding.ascii()); + // slotStatusMsg(i18n("Saving file...")); + if (!checkEncoding(cod)) { + KMessageBox::sorry(this,i18n("The document could not been saved, as the selected encoding cannot encode every unicode character in it.")); + return; + } + + KTempFile tmpfile; + if (Docname.isLocalFile()) { + QFile f(filn); + if ( !f.open( IO_WriteOnly ) ) { + KMessageBox::sorry(this,i18n("The document could not be saved, please check your permissions and disk space.")); + return; + } + QTextStream t( &f ); + t.setCodec(cod); + //t.setEncoding( QTextStream::Latin1 ); + t << view->editor->text();//.utf8(); + f.close(); + } + else { + /*FIXME use following code: + QFile f( fName ); +00983 if ( !f.open( IO_ReadOnly ) ) +00984 return; +00985 QFileInfo info ( f ); +00986 smModificationTime = new QTime( info.lastModified().time() ); +00987 QTextStream t(&f); +00988 t.setEncoding( QTextStream::Latin1 ); +00989 QString s = t.readLine(); +00990 f.close(); + +*/ + QTextStream *stream = tmpfile.textStream(); + stream->setCodec(cod); + *stream << view->editor->text();//.utf8(); + tmpfile.close(); + if(!KIO::NetAccess::upload(tmpfile.name(), Docname,this)) { + KMessageBox::sorry(this,i18n("The document could not be saved, please check your permissions and disk space.")); + tmpfile.unlink(); + return; + } + tmpfile.unlink(); + } + + fileSave->setEnabled(false); + setCaption(Docname.fileName(),false); +} + + +void KgpgApp::slotFileSaveAs() +{ + + //KURL url=KFileDialog::getSaveURL(QDir::currentDirPath(),i18n("*|All Files"), this, i18n("Save As")); + KEncodingFileDialog::Result saveResult; + saveResult=KEncodingFileDialog::getSaveURLAndEncoding (QString::null,QString::null,QString::null,this); + KURL url=saveResult.URLs.first(); + QString selectedEncoding=saveResult.encoding; + + if(!url.isEmpty()) { + if (url.isLocalFile()) + { + QString filn=url.path(); + QFile f(filn); + if (f.exists()) { + QString message=i18n("Overwrite existing file %1?").arg(url.fileName()); + int result=KMessageBox::warningContinueCancel(this,QString(message),i18n("Warning"),i18n("Overwrite")); + if (result==KMessageBox::Cancel) + return; + } + f.close(); + } + else if (KIO::NetAccess::exists(url,false,this)) + { + QString message=i18n("Overwrite existing file %1?").arg(url.fileName()); + int result=KMessageBox::warningContinueCancel(this,QString(message),i18n("Warning"),i18n("Overwrite")); + if (result==KMessageBox::Cancel) + return; + } + Docname=url; + textEncoding=selectedEncoding; + slotFileSave(); + } +} + +void KgpgApp::openDocumentFile(const KURL& url,QString encoding) +{ +QString tempOpenFile; + ///////////////////////////////////////////////// +if( KIO::NetAccess::download( url, tempOpenFile,this ) ) { + QFile qfile(tempOpenFile); + if (qfile.open(IO_ReadOnly)) { + QTextStream t( &qfile ); + t.setCodec(QTextCodec::codecForName (encoding.ascii())); + view->editor->setText(t.read()); + qfile.close(); + fileSave->setEnabled(false); + editRedo->setEnabled(false); + editUndo->setEnabled(false); + } +} +} + +void KgpgApp::slotFilePrint() +{ + KPrinter prt; + //kdDebug(2100)<<"Printing..."<editor->text() ); + } +} + +void KgpgApp::slotEditCut() +{ + view->editor->cut(); +} + +void KgpgApp::slotEditCopy() +{ + view->editor->copy(); +} + +void KgpgApp::slotEditPaste() +{ + view->editor->paste(); +} + +void KgpgApp::slotSelectAll() +{ + view->editor->selectAll(); +} + +void KgpgApp::slotundo() +{ + view->editor->undo(); + editRedo->setEnabled(true); +} + +void KgpgApp::slotredo() +{ + view->editor->redo(); +} + +///////////// file signature slots + + +void KgpgApp::slotCheckMd5() +{ + ///////////////////////////////////////////////////////////////////////// display md5 sum for a chosen file + + KURL url=KFileDialog::getOpenURL(QString::null, + i18n("*|All Files"), this, i18n("Open File to Verify")); + if (!url.isEmpty()) { + + Md5Widget *mdwidget=new Md5Widget(this,0,url); + mdwidget->exec(); + delete mdwidget; + // KMessageBox::information(this,QString("MD5 sum for "+url.fileName()+" is:\n"+checkfile.hexDigest().data())); + } +} + + +void KgpgApp::slotPreSignFile() +{ + ////////////////////////////////////// create a detached signature for a chosen file + KURL url=KFileDialog::getOpenURL(QString::null,i18n("*|All Files"), this, i18n("Open File to Sign")); + if (!url.isEmpty()) + slotSignFile(url); +} + +void KgpgApp::slotSignFile(KURL url) +{ + ////////////////////////////////////// create a detached signature for a chosen file + QString signKeyID; + if (!url.isEmpty()) { + ////////////////// select a private key to sign file --> listkeys.cpp + KgpgSelKey *opts=new KgpgSelKey(this,"select_secret"); + if (opts->exec()==QDialog::Accepted) + signKeyID=opts->getkeyID(); + else { + delete opts; + return; + } + delete opts; + QString Options; + if (KGpgSettings::asciiArmor()) + Options="--armor"; + if (KGpgSettings::pgpCompatibility()) + Options+="--pgp6"; + KgpgInterface *signFileProcess=new KgpgInterface(); + signFileProcess->KgpgSignFile(signKeyID,url,Options); + } +} + +void KgpgApp::slotPreVerifyFile() +{ + KURL url=KFileDialog::getOpenURL(QString::null, + i18n("*|All Files"), this, i18n("Open File to Verify")); + slotVerifyFile(url); +} + +void KgpgApp::slotVerifyFile(KURL url) +{ + /////////////////////////////////// check file signature + QString sigfile=QString::null; + if (!url.isEmpty()) { + ////////////////////////////////////// try to find detached signature. + if (!url.fileName().endsWith(".sig")) { + sigfile=url.path()+".sig"; + QFile fsig(sigfile); + if (!fsig.exists()) { + sigfile=url.path()+".asc"; + QFile fsig(sigfile); + ////////////// if no .asc or .sig signature file included, assume the file is internally signed + if (!fsig.exists()) + sigfile=QString::null; + } + } + ///////////////////////// pipe gpg command + KgpgInterface *verifyFileProcess=new KgpgInterface(); + verifyFileProcess->KgpgVerifyFile(url,KURL(sigfile)); + connect (verifyFileProcess,SIGNAL(verifyquerykey(QString)),this,SLOT(importSignatureKey(QString))); + } +} + +void KgpgApp::importSignatureKey(QString ID) +{ + keyServer *kser=new keyServer(0,"server_dialog",false); + kser->page->kLEimportid->setText(ID); + kser->slotImport(); +} + +void KgpgApp::openEncryptedDocumentFile(const KURL& url) +{ + view->editor->slotDroppedFile(url); +} + + +#include "kgpgeditor.moc" diff --git a/kgpg/kgpgeditor.h b/kgpg/kgpgeditor.h new file mode 100644 index 0000000..0e8cda9 --- /dev/null +++ b/kgpg/kgpgeditor.h @@ -0,0 +1,123 @@ +/*************************************************************************** + kgpgeditor.h - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGEDITOR_H +#define KGPGEDITOR_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +class KPassivePopup; +class KComboBox; +class KToggleAction; +class KAction; +class KgpgView; + +class KgpgApp : public KMainWindow +{ + Q_OBJECT + + friend class KgpgView; + +public: + /** construtor of KgpgApp, calls all init functions to create the application. + */ + KgpgApp(QWidget *parent=0, const char *name=0,WFlags f = 0,KShortcut goHome=QKeySequence(CTRL+Qt::Key_Home),bool mainWindow=false); + ~KgpgApp(); + /** opens a file specified by commandline option + */ + void openDocumentFile(const KURL& url,QString encoding=QString::null); + void openEncryptedDocumentFile(const KURL& url); + /** returns a pointer to the current document connected to the KTMainWindow instance and is used by + * the View class to access the document object's methods + */ + KURL Docname; + int version; + QString messages; + KgpgView *view; + KShortcut goDefaultKey; + + +protected: + void readOptions(bool doresize=true); + void saveOptions(); + void initActions(); + void initView(); + void closeEvent( QCloseEvent * e ); + +private slots: + //void slotOptions(); + void slotFileQuit(); + void slotFileNew(); + void slotResetEncoding(bool enc); + void slotFilePreEnc(); + void slotFilePreDec(); + void slotFileOpen(); + void slotFileSave(); + void slotFileSaveAs(); + void slotFilePrint(); + void slotEditCut(); + void slotEditCopy(); + void slotEditPaste(); + void slotSelectAll(); + void slotCheckMd5(); + + void slotPreSignFile(); + void slotSignFile(KURL url); + void slotVerifyFile(KURL url); + void slotPreVerifyFile(); + void importSignatureKey(QString ID); + + void slotundo(); + void slotredo(); + void slotSetCharset(); + bool checkEncoding(QTextCodec *codec); + void slotOptions(); + void slotKeyManager(); + + +public slots: + void slotSetFont(QFont myFont); + void closeWindow(); + + +private: + + QStringList customDecrypt; + //KToggleAction *encodingAction ; + KURL urlselected; + KAction* fileSave, *editUndo, *editRedo; + KComboBox *fontCombo; + bool isMainWindow; + QString textEncoding; + +signals: + +void refreshImported(QStringList); +void openChangeFont(); +void openConfigDialog(); +void encryptFiles(KURL::List fileList); +}; + +#endif // KGPGEDITOR_H + diff --git a/kgpg/kgpginterface.cpp b/kgpg/kgpginterface.cpp new file mode 100644 index 0000000..5286c3c --- /dev/null +++ b/kgpg/kgpginterface.cpp @@ -0,0 +1,2166 @@ +/*************************************************************************** + kgpginterface.cpp - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kgpginterface.h" +#include "listkeys.h" +#include "detailedconsole.h" + +KgpgInterface::KgpgInterface() +{} + + +int KgpgInterface::getGpgVersion() +{ +FILE *fp; + QString readResult,gpgString; + char buffer[200]; + bool readLine=true; + + QString gpgcmd="gpg --version"; + + fp = popen(QFile::encodeName(gpgcmd), "r"); + while ( fgets( buffer, sizeof(buffer), fp)) { + readResult=buffer; + if (readLine) { + gpgString=readResult.stripWhiteSpace().section(' ',-1); + readLine=false; + } + } + pclose(fp); + return (100*gpgString.section('.',0,0).toInt()+10*gpgString.section('.',1,1).toInt()+gpgString.section('.',2,2).toInt()); +} + +void KgpgInterface::updateIDs(QString txtString) +{ + int cut=txtString.find(' ',22,false); + txtString.remove(0,cut); + if (txtString.find("(",0,false)!=-1) + txtString=txtString.section('(',0,0)+txtString.section(')',-1); + txtString.replace(QRegExp("<"),"<"); + if (userIDs.find(txtString)==-1) + { + if (!userIDs.isEmpty()) + userIDs+=i18n(" or "); + userIDs+=txtString; + } +} + +void KgpgInterface::KgpgEncryptFile(QStringList encryptKeys,KURL srcUrl,KURL destUrl, QStringList Options, bool symetrical) +{ + sourceFile=srcUrl; + message=QString::null; + + KProcIO *proc=new KProcIO(QTextCodec::codecForLocale()); + *proc<<"gpg"<<"--no-tty"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--utf8-strings"; + for ( QStringList::Iterator it = Options.begin(); it != Options.end(); ++it ) + if (!QFile::encodeName(*it).isEmpty()) *proc<< QFile::encodeName(*it); + + *proc<<"--output"<start(KProcess::NotifyOnExit,true); +} + + +KgpgInterface::~KgpgInterface() +{} + + +void KgpgInterface::encryptfin(KProcess *) +{ + if (message.find("END_ENCRYPTION")!=-1) + emit encryptionfinished(sourceFile); + else { + emit errormessage(message); + } +} + +void KgpgInterface::readencprocess(KProcIO *p) +{ + QString required; + while (p->readln(required,true)!=-1) { + if (required.find("BEGIN_ENCRYPTION",0,false)!=-1) + emit processstarted(sourceFile.path()); + if (required.find("GET_")!=-1) { + if (required.find("openfile.overwrite.okay")!=-1) + p->writeStdin("Yes"); + else if ((required.find("passphrase.enter")!=-1)) { + QCString passphrase; + int code=KPasswordDialog::getNewPassword(passphrase,i18n("Enter passphrase for your file (symmetrical encryption):")); + if (code!=QDialog::Accepted) { + p->deleteLater(); + emit processaborted(true); + return; + } + p->writeStdin(passphrase,true); + } else { + p->writeStdin("quit"); + p->closeWhenDone(); + } + } + message+=required+"\n"; + } +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////// File decryption + +void KgpgInterface::KgpgDecryptFile(KURL srcUrl,KURL destUrl,QStringList Options) +{ + message=QString::null; + step=3; + decryptUrl=srcUrl.path(); + userIDs=QString::null; + anonymous=false; + + KProcIO *proc=new KProcIO(QTextCodec::codecForLocale()); + + *proc<<"gpg"<<"--no-tty"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--utf8-strings"; + + for ( QStringList::Iterator it = Options.begin(); it != Options.end(); ++it ) + if (!QFile::encodeName(*it).isEmpty()) *proc<< QFile::encodeName(*it); + + if (!destUrl.fileName().isEmpty()) // a filename was entered + *proc<<"-o"<start(KProcess::NotifyOnExit,true); +} + +void KgpgInterface::decryptfin(KProcess *) +{ + if ((message.find("DECRYPTION_OKAY")!=-1) && (message.find("END_DECRYPTION")!=-1)) //&& (message.find("GOODMDC")!=-1) + emit decryptionfinished(); + else + emit errormessage(message); +} + + +void KgpgInterface::readdecprocess(KProcIO *p) +{ + QString required; + while (p->readln(required,true)!=-1) { + if (required.find("BEGIN_DECRYPTION",0,false)!=-1) + emit processstarted(decryptUrl); + if (required.find("USERID_HINT",0,false)!=-1) + updateIDs(required); + + if (required.find("ENC_TO")!=-1) { + if (required.find("0000000000000000")!=-1) + anonymous=true; + } + if (required.find("GET_")!=-1) { + if (required.find("openfile.overwrite.okay")!=-1) + p->writeStdin("Yes"); + else if ((required.find("passphrase.enter")!=-1)) { + if (userIDs.isEmpty()) + userIDs=i18n("[No user id found]"); + userIDs.replace(QRegExp("<"),"<"); + QCString passphrase; + QString passdlgmessage; + if (anonymous) + passdlgmessage=i18n("No user id found. Trying all secret keys.
"); + if ((step<3) && (!anonymous)) + passdlgmessage=i18n("Bad passphrase. You have %1 tries left.
").arg(step); + + passdlgmessage+=i18n("Enter passphrase for %1").arg(userIDs); + int code=KPasswordDialog::getPassword(passphrase,passdlgmessage); + if (code!=QDialog::Accepted) { + p->deleteLater(); + emit processaborted(true); + return; + } + p->writeStdin(passphrase,true); + userIDs=QString::null; + if (step>1) step--; + else step=3; + } else { + p->writeStdin("quit"); + p->closeWhenDone(); + } + } + message+=required+"\n"; + } +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////// Text encryption + + +void KgpgInterface::KgpgEncryptText(QString text,QStringList userIDs, QStringList Options) +{ + message=QString::null; + //QTextCodec *codec = KGlobal::charsets()->codecForName(KGlobal::locale()->encoding()); + QTextCodec *codec =QTextCodec::codecForLocale (); + if (codec->canEncode(text)) txtToEncrypt=text; + else txtToEncrypt=text.utf8(); + + KProcIO *proc=new KProcIO(QTextCodec::codecForLocale()); + *proc<<"gpg"<<"--no-tty"<<"--no-secmem-warning"<<"--command-fd=0"<<"--status-fd=1"<<"--utf8-strings"; + + for ( QStringList::Iterator it = Options.begin(); it != Options.end(); ++it ) + if (!QFile::encodeName(*it).isEmpty()) *proc<< QFile::encodeName(*it); + + if (!userIDs.isEmpty()) + { + *proc<<"-e"; + for ( QStringList::Iterator it = userIDs.begin(); it != userIDs.end(); ++it ) + *proc<<"--recipient"<< *it; + } + else + *proc<<"-c"; + + ///////// when process ends, update dialog infos + + QObject::connect(proc, SIGNAL(processExited(KProcess *)),this,SLOT(txtencryptfin(KProcess *))); + QObject::connect(proc,SIGNAL(readReady(KProcIO *)),this,SLOT(txtreadencprocess(KProcIO *))); + proc->start(KProcess::NotifyOnExit,false); + emit txtencryptionstarted(); +} + + +void KgpgInterface::txtencryptfin(KProcess *) +{ + if (!message.isEmpty()) + emit txtencryptionfinished(message); + else + emit txtencryptionfinished(QString::null); +} + +void KgpgInterface::txtreadencprocess(KProcIO *p) +{ + QString required; + while (p->readln(required,true)!=-1) { + if (required.find("BEGIN_ENCRYPTION",0,false)!=-1) + { + p->writeStdin(txtToEncrypt,false); + txtToEncrypt=QString::null; + p->closeWhenDone(); + } + else + if ((required.find("passphrase.enter")!=-1)) + { + QCString passphrase; + QString passdlgmessage=i18n("Enter passphrase (symmetrical encryption)"); + int code=KPasswordDialog::getNewPassword(passphrase,passdlgmessage); + if (code!=QDialog::Accepted) + { + p->deleteLater(); + return; + } + p->writeStdin(passphrase,true); + } + else + if (!required.startsWith("[GNUPG:]")) message+=required+"\n"; + } +} + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Text decryption + +void KgpgInterface::KgpgDecryptText(QString text,QStringList Options) +{ + gpgOutput=QString::null; + log=QString::null; + + message=QString::null; + userIDs=QString::null; + step=3; + anonymous=false; + decfinished=false; + decok=false; + badmdc=false; + KProcess *proc=new KProcess(); + *proc<<"gpg"<<"--no-tty"<<"--no-secmem-warning"<<"--command-fd=0"<<"--status-fd=2"<<"--no-batch"<<"--utf8-strings"; + for ( QStringList::Iterator it = Options.begin(); it != Options.end(); ++it ) + if (!QFile::encodeName(*it).isEmpty()) *proc<< QFile::encodeName(*it); + *proc<<"-d"; + + ///////// when process ends, update dialog infos + + QObject::connect(proc, SIGNAL(processExited(KProcess *)),this,SLOT(txtdecryptfin(KProcess *))); + connect(proc, SIGNAL(receivedStdout(KProcess *, char *, int)),this, SLOT(getOutput(KProcess *, char *, int))); + connect(proc, SIGNAL(receivedStderr(KProcess *, char *, int)),this, SLOT(getCmdOutput(KProcess *, char *, int))); + proc->start(KProcess::NotifyOnExit,KProcess::All); + proc->writeStdin(text.utf8(), text.length()); +} + +void KgpgInterface::txtdecryptfin(KProcess *) +{ +if ((decok) && (!badmdc)) +emit txtdecryptionfinished(message); + +else if (badmdc) +{ +KMessageBox::sorry(0,i18n("Bad MDC detected. The encrypted text has been manipulated.")); +emit txtdecryptionfailed(log); +} +else +emit txtdecryptionfailed(log); +} + + +void KgpgInterface::getOutput(KProcess *, char *data, int ) +{ + message.append(QString::fromUtf8(data)); +} + + +void KgpgInterface::getCmdOutput(KProcess *p, char *data, int ) +{ + gpgOutput.append(QString::fromUtf8(data)); + log.append(data); + + int pos; + while ((pos=gpgOutput.find("\n"))!=-1) + { + QString required=gpgOutput.left(pos); + gpgOutput.remove(0,pos+2); + + if (required.find("USERID_HINT",0,false)!=-1) + updateIDs(required); + + if (required.find("ENC_TO")!=-1) + { + if (required.find("0000000000000000")!=-1) + anonymous=true; + } + + if (required.find("GET_")!=-1) + { + if ((required.find("passphrase.enter")!=-1)) + { + if (userIDs.isEmpty()) + userIDs=i18n("[No user id found]"); + QCString passphrase; + QString passdlgmessage; + if (anonymous) + passdlgmessage=i18n("No user id found. Trying all secret keys.
"); + if ((step<3) && (!anonymous)) + passdlgmessage=i18n("Bad passphrase. You have %1 tries left.
").arg(step); + passdlgmessage+=i18n("Enter passphrase for %1").arg(userIDs); + int code=KPasswordDialog::getPassword(passphrase,passdlgmessage); + if (code!=QDialog::Accepted) + { + p->deleteLater(); + emit processaborted(true); + return; + } + passphrase.append("\n"); + p->writeStdin(passphrase,passphrase.length()); + userIDs=QString::null; + if (step>1) step--; + else step=3; + } + else + { + p->writeStdin("quit",4); + p->closeStdin(); + } + } + + if (required.find("BEGIN_DECRYPTION")!=-1) + { + p->closeStdin(); + required=QString::null; + } + + if (required.find("END_DECRYPTION")!=-1) decfinished=true; + if (required.find("DECRYPTION_OKAY")!=-1) decok=true; + if (required.find("DECRYPTION_FAILED")!=-1) decok=false; + if (required.find("BADMDC")!=-1) badmdc=true; + } +} +////////////////////////////////////////////////////////////////////////////////////////////////////////// Text signing + + +void KgpgInterface::KgpgSignText(QString text,QString userIDs, QStringList Options) +{ + message=QString::null; + step=4; + QString txtprocess; + QTextCodec *codec =QTextCodec::codecForLocale (); + if (codec->canEncode(text)) txtprocess=text; + else txtprocess=text.utf8(); + + KProcIO *proc=new KProcIO(QTextCodec::codecForLocale()); + *proc<<"gpg"<<"--no-tty"<<"--no-secmem-warning"<<"--command-fd=0"<<"--status-fd=1"<<"--utf8-strings"; + + for ( QStringList::Iterator it = Options.begin(); it != Options.end(); ++it ) + if (!QFile::encodeName(*it).isEmpty()) *proc<< QFile::encodeName(*it); + *proc<<"--clearsign"<<"-u"<start(KProcess::NotifyOnExit,false); + /*if (useAgent) + { + kdDebug(2100)<<"Using Agent+++++++++++++"<writeStdin(txtprocess,true); + proc->closeWhenDone(); + } + else*/ + message=txtprocess; +} + + +void KgpgInterface::txtsignfin(KProcess *) +{ + if (!message.isEmpty()) + emit txtSignOver(message); + else + emit txtSignOver(QString::null); +} + +void KgpgInterface::txtsignprocess(KProcIO *p) +{ + QString required; + while (p->readln(required,true)!=-1) { +// kdDebug(2100)<<"SIGNING: "<writeStdin(message,true); + message=QString::null; + p->closeWhenDone(); + } + + if ((required.find("passphrase.enter")!=-1)) + { + if (step>1) step--; + else step=3; + if (userIDs.isEmpty()) + userIDs=i18n("[No user id found]"); + QCString passphrase; + QString passdlgmessage; + if (step<3) + passdlgmessage=i18n("Bad passphrase. You have %1 tries left.
").arg(step); + passdlgmessage+=i18n("Enter passphrase for %1").arg(userIDs); + int code=KPasswordDialog::getPassword(passphrase,passdlgmessage); + if (code!=QDialog::Accepted) + { + p->deleteLater(); + return; + } + p->writeStdin(passphrase,true); + } + else + if (!required.startsWith("[GNUPG:]")) message+=required+"\n"; + } +} + + +//////////////////////////////////////////////// decrypt file to text + +void KgpgInterface::KgpgDecryptFileToText(KURL srcUrl,QStringList Options) +{ + + message=QString::null; + userIDs=QString::null; + step=3; + anonymous=false; +decfinished=false; +decok=false; +badmdc=false; + + KProcess *proc=new KProcess(); + *proc<<"gpg"<<"--no-tty"<<"--utf8-strings"<<"--no-secmem-warning"<<"--command-fd=0"<<"--status-fd=2"<<"--no-batch"<<"-o"<<"-"; + for ( QStringList::Iterator it = Options.begin(); it != Options.end(); ++it ) { + if (!QFile::encodeName(*it).isEmpty()) *proc<< QFile::encodeName(*it); + } + *proc<<"-d"<start(KProcess::NotifyOnExit,KProcess::All); +} + + +/////////////////////////////////////////////////////// verify text + + +void KgpgInterface::KgpgVerifyText(QString text) +{ + + QTextCodec *codec =QTextCodec::codecForLocale (); + if (!codec->canEncode(text)) text=text.utf8(); + signmiss=false; + signID=QString::null; + message=QString::null; + KProcIO *verifyproc=new KProcIO(QTextCodec::codecForLocale()); + *verifyproc<<"gpg"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--utf8-strings"<<"--verify"; + connect(verifyproc, SIGNAL(processExited(KProcess *)),this, SLOT(slotverifyresult(KProcess *))); + connect(verifyproc, SIGNAL(readReady(KProcIO *)),this, SLOT(slotverifyread(KProcIO *))); + verifyproc->start(KProcess::NotifyOnExit,true); + verifyproc->writeStdin (text); + verifyproc->closeWhenDone(); +} + + +void KgpgInterface::slotverifyresult(KProcess*) +{ +if (signmiss) emit missingSignature(signID); + else { + if (signID.isEmpty()) signID=i18n("No signature found."); + emit verifyOver(signID,message); + } +//kdDebug(2100) << "GPG VERIFY OVER________"<readln(required,true)!=-1) + { + message+=required+"\n"; + required=required.section("]",1,-1).stripWhiteSpace(); + if (required.startsWith("GOODSIG")) + { + QString userName=required.section(" ",2,-1).replace(QRegExp("<"),"<"); + userName=checkForUtf8(userName); + signID=i18n("Good signature from:
%1
Key ID: %2
").arg(userName).arg("0x"+required.section(" ",1,1).right(8)); + } + if (required.startsWith("BADSIG")) + { + signID=i18n("Bad signature from:
%1
Key ID: %2

Text is corrupted.
").arg(required.section(" ",2,-1).replace(QRegExp("<"),"<")).arg("0x"+required.section(" ",1,1).right(8)); + } + if (required.startsWith("NO_PUBKEY")) + { + signID="0x"+required.section(" ",1,1).right(8); + signmiss=true; + } + if (required.startsWith("UNEXPECTED") || required.startsWith("NODATA")) + signID=i18n("No signature found."); + if (required.startsWith("TRUST_UNDEFINED")) + signID+=i18n("The signature is valid, but the key is untrusted"); + if (required.startsWith("TRUST_ULTIMATE")) + signID+=i18n("The signature is valid, and the key is ultimately trusted"); + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// MD5 + +Md5Widget::Md5Widget(QWidget *parent, const char *name,KURL url):KDialogBase( parent, name, true,i18n("MD5 Checksum"),Apply | Close) +{ + setButtonApply(i18n("Compare MD5 with Clipboard")); + mdSum=QString::null; + QFile f(url.path()); + f.open( IO_ReadOnly); + KMD5 checkfile; + checkfile.reset(); + checkfile.update(f); + mdSum=checkfile.hexDigest().data(); + f.close(); + QWidget *page = new QWidget(this); + + resize( 360, 150 ); + QGridLayout *MyDialogLayout = new QGridLayout( page, 1, 1, 5, 6, "MyDialogLayout"); + + QLabel *TextLabel1 = new QLabel( page, "TextLabel1" ); + TextLabel1->setText(i18n("MD5 sum for %1 is:").arg(url.fileName())); + MyDialogLayout->addWidget( TextLabel1, 0, 0 ); + + KLineEdit *KRestrictedLine1 = new KLineEdit(mdSum,page); + KRestrictedLine1->setReadOnly(true); + KRestrictedLine1->setPaletteBackgroundColor(QColor(255,255,255)); + MyDialogLayout->addWidget( KRestrictedLine1, 1, 0 ); + + + QHBoxLayout *Layout4 = new QHBoxLayout( 0, 0, 6, "Layout4"); + + KLed1=new KLed(QColor(80,80,80),KLed::Off,KLed::Sunken,KLed::Circular,page,"KLed1"); + KLed1->off(); + KLed1->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, KLed1->sizePolicy().hasHeightForWidth() ) ); + Layout4->addWidget( KLed1 ); + + TextLabel1_2 = new QLabel( page, "TextLabel1_2" ); + TextLabel1_2->setText(i18n( "Unknown status" ) ); + Layout4->addWidget( TextLabel1_2 ); + + MyDialogLayout->addLayout( Layout4, 2, 0 ); + QSpacerItem* spacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ); + MyDialogLayout->addItem( spacer, 3, 0 ); + + page->show(); + page->resize(page->minimumSize()); + setMainWidget(page); + + +} + +Md5Widget::~Md5Widget() +{} + +void Md5Widget::slotApply() +{ + QClipboard *cb = QApplication::clipboard(); + QString text; + // Copy text from the clipboard (paste) + text = cb->text(QClipboard::Clipboard); + if ( !text.isEmpty() ) { + text=text.stripWhiteSpace(); + while (text.find(' ')!=-1) + text.remove(text.find(' '),1); + if (text==mdSum) { + TextLabel1_2->setText(i18n("Correct checksum, file is ok.")); + KLed1->setColor(QColor(0,255,0)); + KLed1->on(); + }//KMessageBox::sorry(0,"OK"); + else if (text.length()!=mdSum.length()) + KMessageBox::sorry(0,i18n("Clipboard content is not a MD5 sum.")); + else { + TextLabel1_2->setText(i18n("Wrong checksum, FILE CORRUPTED")); + KLed1->setColor(QColor(255,0,0)); + KLed1->on(); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// signatures + + +void KgpgInterface::KgpgSignFile(QString keyID,KURL srcUrl,QStringList Options) +{ + ////////////////////////////////////// create a detached signature for a chosen file + message=QString::null; + step=3; + ///////////// create gpg command + KProcIO *proc=new KProcIO(QTextCodec::codecForLocale()); + keyID=keyID.stripWhiteSpace(); + *proc<<"gpg"<<"--no-tty"<<"--no-secmem-warning"<<"--utf8-strings"<<"--status-fd=2"<<"--command-fd=0"<<"-u"<start(KProcess::NotifyOnExit,true); +} + + + +void KgpgInterface::signfin(KProcess *) +{ + if (message.find("SIG_CREATED")!=-1) + KMessageBox::information(0,i18n("The signature file %1 was successfully created.").arg(file.fileName())); + else if (message.find("BAD_PASSPHRASE")!=-1) + KMessageBox::sorry(0,i18n("Bad passphrase, signature was not created.")); + else + KMessageBox::sorry(0,message); + emit signfinished(); +} + + +void KgpgInterface::readsignprocess(KProcIO *p) +{ + QString required; + while (p->readln(required,true)!=-1) { + if (required.find("USERID_HINT",0,false)!=-1) + updateIDs(required); + + if (required.find("GET_")!=-1) { + if (required.find("openfile.overwrite.okay")!=-1) + p->writeStdin("Yes"); + else if ((required.find("passphrase.enter")!=-1)) { + if (userIDs.isEmpty()) + userIDs=i18n("[No user id found]"); + QCString passphrase; + QString passdlgmessage; + if (step<3) + passdlgmessage=i18n("Bad passphrase. you have %1 tries left.
").arg(step); + passdlgmessage+=i18n("Enter passphrase for %1").arg(userIDs); + int code=KPasswordDialog::getPassword(passphrase,passdlgmessage); + if (code!=QDialog::Accepted) { + p->deleteLater(); + emit signfinished(); + return; + } + p->writeStdin(passphrase,true); + userIDs=QString::null; + if (step>1) step--; + else step=3; + } else { + p->writeStdin("quit"); + p->closeWhenDone(); + } + } + message+=required+"\n"; + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +void KgpgInterface::KgpgVerifyFile(KURL sigUrl,KURL srcUrl) +{ + ////////////////////////////////////// verify signature for a chosen file + message=QString::null; + signID=QString::null; + signmiss=false; + ///////////// create gpg command + KProcIO *proc=new KProcIO(QTextCodec::codecForLocale()); + file=sigUrl; + *proc<<"gpg"<<"--no-tty"<<"--utf8-strings"<<"--no-secmem-warning"<<"--status-fd=2"<<"--verify"; + if (!srcUrl.isEmpty()) + *proc<start(KProcess::NotifyOnExit,true); +} + + +void KgpgInterface::readprocess(KProcIO *p) +{ +QString required; + while (p->readln(required,true)!=-1) + { + message+=required+"\n"; + if (required.find("GET_")!=-1) { + p->writeStdin("quit"); + p->closeWhenDone(); + } + required=required.section("]",1,-1).stripWhiteSpace(); + if (required.startsWith("UNEXPECTED") || required.startsWith("NODATA")) + signID=i18n("No signature found."); + if (required.startsWith("GOODSIG")) + { + signID=i18n("Good signature from:
%1
Key ID: %2
").arg(required.section(" ",2,-1).replace(QRegExp("<"),"<")).arg("0x"+required.section(" ",1,1).right(8)); + } + if (required.startsWith("BADSIG")) + { + signID=i18n("BAD signature from:
%1
Key id: %2

" + "The file is corrupted!
").arg(required.section(" ",2,-1).replace(QRegExp("<"),"<")).arg("0x"+required.section(" ",1,1).right(8)); + } + if (required.startsWith("NO_PUBKEY")) + { + signmiss=true; + signID="0x"+required.section(" ",1,1).right(8); + } + if (required.startsWith("TRUST_UNDEFINED")) + signID+=i18n("The signature is valid, but the key is untrusted"); + if (required.startsWith("TRUST_ULTIMATE")) + signID+=i18n("The signature is valid, and the key is ultimately trusted"); + } +} + + +void KgpgInterface::verifyfin(KProcess *) +{ + if (!signmiss) { + if (signID.isEmpty()) signID=i18n("No signature found."); + (void) new KDetailedInfo(0,"verify_result",signID,message); + } + else { + if (KMessageBox::questionYesNo(0,i18n("Missing signature:
Key id: %1

" + "Do you want to import this key from a keyserver?
").arg(signID),file.fileName(),QString::null, i18n("Import"), i18n("Do Not Import"))==KMessageBox::Yes) + emit verifyquerykey(signID); + } + emit verifyfinished(); +} + + + +//////////////////////////////////////////////////////////// sign a key + +void KgpgInterface::KgpgSignKey(QString keyID,QString signKeyID,QString signKeyMail,bool local,int checking) +{ + signKeyMail.replace(QRegExp("<"),"<"); + konsChecked=checking; + konsLocal=local; + konsSignKey=signKeyID; + konsKeyID=keyID; + errMessage=QString::null; + if (checkuid(keyID)>0) + { + openSignConsole(); + return; + } + + signSuccess=0; + step=1; + output=QString::null; + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<<"gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--utf8-strings"<<"--command-fd=0"<<"--status-fd=2"<<"-u"<start(KProcess::NotifyOnExit,true); +} + +void KgpgInterface::sigprocess(KProcIO *p) +{ + QString required=QString::null; + + while (p->readln(required,true)!=-1) + { + + output+=required+"\n"; + if (required.find("USERID_HINT",0,false)!=-1) + updateIDs(required); + + if (signSuccess==4) { + if (required.find("GET_")!=-1) + p->writeStdin("quit"); + p->closeWhenDone(); + return; + } + + if ((required.find("GOOD_PASSPHRASE")!=-1)) { + signSuccess=3; + step=2; + } + + if (required.find("sign_uid.expire")!=-1) { + p->writeStdin("Never"); + required=QString::null; + } + if (required.find("sign_uid.class")!=-1) { + p->writeStdin(QString::number(konsChecked)); + required=QString::null; + } + if (required.find("sign_uid.okay")!=-1) { + p->writeStdin("Y"); + required=QString::null; + } + + if (required.find("sign_all.okay")!=-1) { + p->writeStdin("Y"); + required=QString::null; + } + + if (required.find("passphrase.enter")!=-1) { + QCString signpass; + int code=KPasswordDialog::getPassword(signpass,i18n("%1 Enter passphrase for %2:") + .arg(errMessage).arg(userIDs)); + if (code!=QDialog::Accepted) { + signSuccess=4; ///// aborted by user mode + required=QString::null; + p->writeStdin("quit"); + p->closeWhenDone(); + return; + } + p->writeStdin(signpass,true); + required=QString::null; + // step=2; + } + if ((step==2) && (required.find("keyedit.prompt")!=-1)) { + p->writeStdin("save"); + required=QString::null; + } + if (required.find("BAD_PASSPHRASE")!=-1) { + errMessage=i18n("Bad passphrase. Try again.
"); + required=QString::null; + signSuccess=2; ///// bad passphrase + } + if (required.find("GET_")!=-1) /////// gpg asks for something unusal, turn to konsole mode + { + if (signSuccess!=2) + signSuccess=1; ///// switching to console mode + p->writeStdin("quit"); + p->closeWhenDone(); + + } + } +} + + +void KgpgInterface::signover(KProcess *) +{ + if (signSuccess>1) + emit signatureFinished(signSuccess); //// signature successful or bad passphrase + else { + KDetailedConsole *q=new KDetailedConsole(0,"sign_error",i18n("Signing key %1 with key %2 failed.
" + "Do you want to try signing the key in console mode?
").arg(konsKeyID).arg(konsSignKey),output); + if (q->exec()==QDialog::Accepted) + openSignConsole(); + else + emit signatureFinished(0); + } +} + +void KgpgInterface::openSignConsole() +{ + KProcess conprocess; + KConfig *config = KGlobal::config(); + config->setGroup("General"); + conprocess<< config->readPathEntry("TerminalApplication","konsole"); + conprocess<<"-e"<<"gpg"; + conprocess<<"--no-secmem-warning"<<"--expert"<<"-u"<0) { + KMessageBox::sorry(0,i18n("This key has more than one user ID.\nEdit the key manually to delete signature.")); + return; + } + + message=signKeyID.remove(0,2); + deleteSuccess=false; + step=0; + + FILE *fp; + QString encResult; + char buffer[200]; + signb=0; + sigsearch=0; + + QString gpgcmd="gpg --no-tty --no-secmem-warning --with-colon --list-sigs "+keyID; + fp = popen(QFile::encodeName(gpgcmd), "r"); + while ( fgets( buffer, sizeof(buffer), fp)) { + encResult=buffer; + if (encResult.startsWith("sig")) { + if (encResult.find(message)!=-1) + break; + signb++; + } else if (encResult.startsWith("rev")) + signb++; + } + pclose(fp); + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<<"gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--utf8-strings"<<"--command-fd=0"<<"--status-fd=2"; + *conprocess<<"--edit-key"<start(KProcess::NotifyOnExit,true); +} + + +void KgpgInterface::delsigprocess(KProcIO *p) +{ + + QString required=QString::null; + while (p->readln(required,true)!=-1) + { + if (required.find("keyedit.delsig")!=-1){ + + if ((sigsearch==signb) && (step==0)) { + p->writeStdin("Y"); + step=1; + } else + p->writeStdin("n"); + sigsearch++; + required=QString::null; + } + if ((step==1) && (required.find("keyedit.prompt")!=-1)) { + p->writeStdin("save"); + required=QString::null; + deleteSuccess=true; + } + if (required.find("GET_LINE")!=-1) { + p->writeStdin("quit"); + p->closeWhenDone(); + deleteSuccess=false; + } + } +} + +void KgpgInterface::delsignover(KProcess *) +{ + emit delsigfinished(deleteSuccess); +} + +/////////////////////////////////////////////////// check if a key has more than one id + +int KgpgInterface::checkuid(QString KeyID) +{ + FILE *fp; + QString encResult; + char buffer[200]; + int uidcnt=0; + + QString gpgcmd="gpg --no-tty --no-secmem-warning --with-colon --list-sigs "+KeyID; + ////////// encode with untrusted keys or armor if checked by user + fp = popen(QFile::encodeName(gpgcmd), "r"); + while (fgets(buffer, sizeof(buffer), fp)) { + encResult=buffer; + if (encResult.startsWith("uid")) + uidcnt++; + } + pclose(fp); + return uidcnt; +} + + +/////////////////////////////////////////////////////////////// change key expiration + + +void KgpgInterface::KgpgKeyExpire(QString keyID,QDate date,bool unlimited) +{ + expSuccess=0; + step=0; + if (unlimited) + expirationDelay=0; + else + expirationDelay=QDate::currentDate().daysTo(date); + output=QString::null; + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<<"gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--command-fd=0"<<"--status-fd=2"<<"--utf8-strings"; + *conprocess<<"--edit-key"<start(KProcess::NotifyOnExit,KProcess::AllOutput); + +} + +void KgpgInterface::expprocess(KProcIO *p) +{ + QString required=QString::null; + + while (p->readln(required,true)!=-1) { + output+=required+"\n"; + + if (required.find("USERID_HINT",0,false)!=-1) + updateIDs(required); + + if ((required.find("GOOD_PASSPHRASE")!=-1)) { + expSuccess=3; + step=2; + } + + if (required.find("keygen.valid")!=-1) { + p->writeStdin(QString::number(expirationDelay)); + required=QString::null; + } + + if (required.find("passphrase.enter")!=-1) { + QCString signpass; + int code=KPasswordDialog::getPassword(signpass,i18n("Enter passphrase for %1:").arg(userIDs)); + if (code!=QDialog::Accepted) { + expSuccess=3; ///// aborted by user mode + p->writeStdin("quit"); + p->closeWhenDone(); + return; + } + p->writeStdin(signpass,true); + required=QString::null; + // step=2; + } + if ((step==2) && (required.find("keyedit.prompt")!=-1)) { + p->writeStdin("save"); + p->closeWhenDone(); + required=QString::null; + } + if ((step==2) && (required.find("keyedit.save.okay")!=-1)) { + p->writeStdin("YES"); + p->closeWhenDone(); + required=QString::null; + } + if (required.find("BAD_PASSPHRASE")!=-1) { + p->writeStdin("quit"); + p->closeWhenDone(); + expSuccess=2; ///// bad passphrase + } + if ((required.find("GET_")!=-1) && (expSuccess!=2)) /////// gpg asks for something unusal, turn to konsole mode + { + expSuccess=1; ///// switching to console mode + p->writeStdin("quit"); + p->closeWhenDone(); + + } + } +} + + + +void KgpgInterface::expover(KProcess *) +{ + if ((expSuccess==3) || (expSuccess==2)) + emit expirationFinished(expSuccess); //// signature successful or bad passphrase + else { + KDetailedConsole *q=new KDetailedConsole(0,"sign_error",i18n("Changing expiration failed.
" + "Do you want to try changing the key expiration in console mode?
"),output); + if (q->exec()==QDialog::Accepted) + KMessageBox::sorry(0,"work in progress..."); + //openSignConsole(); + else + emit expirationFinished(0); + } +} + + +/////////////////////////////////////////////////////////////// change key trust + + +void KgpgInterface::KgpgTrustExpire(QString keyID,int keyTrust) +{ + trustValue=keyTrust+1; +/* Don't know=1; Do NOT trust=2; Marginally=3; Fully=4; Ultimately=5; */ + + output=QString::null; + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<<"gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--command-fd=0"<<"--status-fd=2"<<"--utf8-strings"; + *conprocess<<"--edit-key"<start(KProcess::NotifyOnExit,true); + +} + +void KgpgInterface::trustprocess(KProcIO *p) +{ + QString required=QString::null; + while (p->readln(required,true)!=-1) { + output+=required+"\n"; + if (required.find("edit_ownertrust.set_ultimate.okay")!=-1) { + p->writeStdin("YES"); + required=QString::null; + } + + if (required.find("edit_ownertrust.value")!=-1) { + p->writeStdin(QString::number(trustValue)); + required=QString::null; + } + + if (required.find("keyedit.prompt")!=-1) { + p->writeStdin("save"); + p->closeWhenDone(); + required=QString::null; + } + + if (required.find("GET_")!=-1) /////// gpg asks for something unusal, turn to konsole mode + { + expSuccess=1; ///// switching to console mode + p->writeStdin("quit"); + p->closeWhenDone(); + + } + } +} + + + +void KgpgInterface::trustover(KProcess *) +{ + emit trustfinished(); +} + + +/////////////////////////////////////////////////////////////// change passphrase + + +void KgpgInterface::KgpgChangePass(QString keyID) +{ + step=1; + output=QString::null; + message=QString::null; + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<<"gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--no-use-agent"<<"--command-fd=0"<<"--status-fd=2"<<"--utf8-strings"; + *conprocess<<"--edit-key"<start(KProcess::NotifyOnExit,KProcess::AllOutput); + +} + +void KgpgInterface::passprocess(KProcIO *p) +{ + QString required=QString::null; + + while (p->readln(required,true)!=-1) { + output+=required+"\n"; + + if (required.find("USERID_HINT",0,false)!=-1) + updateIDs(required); + + if ((step>2) && (required.find("keyedit.prompt")!=-1)) { + if (step==3) + { + emit passwordChanged(); + p->writeStdin("save"); + } + else p->writeStdin("quit"); + required=QString::null; + } + + if ((required.find("GOOD_PASSPHRASE")!=-1) && (step==2)) + step=3; + + if ((required.find("BAD_PASSPHRASE")!=-1) && (step==2)) { + step=1; + message=i18n("Bad passphrase. Try again
"); + } + + if ((required.find("passphrase.enter")!=-1)) { + if (userIDs.isEmpty()) + userIDs=i18n("[No user id found]"); + userIDs.replace(QRegExp("<"),"<"); + + if (step==1) { + QCString passphrase; + int code=KPasswordDialog::getPassword(passphrase,i18n("%1 Enter passphrase for %2") + .arg(message).arg(userIDs)); + if (code!=QDialog::Accepted) { + p->writeStdin("quit"); + // p->closeWhenDone(); + emit processaborted(true); + p->deleteLater(); + return; + } + p->writeStdin(passphrase,true); + step=2; + } + + if (step==3) { + QCString passphrase; + int code=KPasswordDialog::getNewPassword(passphrase,i18n("Enter new passphrase for %1
If you forget this passphrase, all your encrypted files and messages will be lost !
").arg(userIDs)); + if (code!=QDialog::Accepted) { + step=4; + p->writeStdin("quit"); + p->writeStdin("quit"); + p->closeWhenDone(); + emit processaborted(true); + return; + } + p->writeStdin(passphrase,true); + userIDs=QString::null; + } + + required=QString::null; + } + + + if (required.find("GET_")!=-1) /////// gpg asks for something unusal, turn to konsole mode + { + p->writeStdin("quit"); + p->closeWhenDone(); + + } + } +} + + + +void KgpgInterface::passover(KProcess *) +{ + //emit trustfinished(); +} + + + +////////////////////////////////////////////////////////////// key export + +QString KgpgInterface::getKey(QStringList IDs, bool attributes) +{ + keyString=QString::null; + KProcIO *proc=new KProcIO(QTextCodec::codecForLocale()); + *proc<< "gpg"<<"--no-tty"<<"--no-secmem-warning"<<"--utf8-strings"; + *proc<<"--export"<<"--armor"; + if (!attributes) + *proc<<"--export-options"<<"no-include-attributes"; + + for ( QStringList::Iterator it = IDs.begin(); it != IDs.end(); ++it ) + *proc << *it; + QObject::connect(proc, SIGNAL(readReady(KProcIO *)),this, SLOT(slotReadKey(KProcIO *))); + proc->start(KProcess::Block,false); + return keyString; +} + + +void KgpgInterface::slotReadKey(KProcIO *p) +{ + QString outp; + while (p->readln(outp)!=-1) + if (!outp.startsWith("gpg:")) keyString+=outp+"\n"; +} + + +////////////////////////////////////////////////////////////// key import + +void KgpgInterface::importKeyURL(KURL url) +{ + ///////////// import a key + + if( KIO::NetAccess::download( url, tempKeyFile,0) ) { + message=QString::null; + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<< "gpg"<<"--no-tty"<<"--no-secmem-warning"<<"--status-fd=2"<<"--utf8-strings"<<"--import"; + *conprocess<<"--allow-secret-key-import"; + *conprocess<start(KProcess::NotifyOnExit,true); + } +} + +void KgpgInterface::importKey(QString keystr) +{ + ///////////// import a key + message=QString::null; + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<< "gpg"<<"--no-tty"<<"--no-secmem-warning"<<"--status-fd=2"<<"--import"; + *conprocess<<"--allow-secret-key-import"; + QObject::connect(conprocess, SIGNAL(processExited(KProcess *)),this, SLOT(importover(KProcess *))); + QObject::connect(conprocess, SIGNAL(readReady(KProcIO *)),this, SLOT(importprocess(KProcIO *))); + conprocess->start(KProcess::NotifyOnExit,true); + conprocess->writeStdin(keystr, true); + conprocess->closeWhenDone(); +} + +void KgpgInterface::importover(KProcess *) +{ +QStringList importedKeysIds; +QStringList messageList; +QString resultMessage; +bool secretImport=false; +kdDebug(2100)<<"Importing is over"<%n key processed.
","%n keys processed.
",messageList[0].toULong()); + if (messageList[4]!="0") + resultMessage+=i18n("One key unchanged.
","%n keys unchanged.
",messageList[4].toULong()); + if (messageList[7]!="0") + resultMessage+=i18n("One signature imported.
","%n signatures imported.
",messageList[7].toULong()); + if (messageList[1]!="0") + resultMessage+=i18n("One key without ID.
","%n keys without ID.
",messageList[1].toULong()); + if (messageList[3]!="0") + resultMessage+=i18n("One RSA key imported.
","%n RSA keys imported.
",messageList[3].toULong()); + if (messageList[5]!="0") + resultMessage+=i18n("One user ID imported.
","%n user IDs imported.
",messageList[5].toULong()); + if (messageList[6]!="0") + resultMessage+=i18n("One subkey imported.
","%n subkeys imported.
",messageList[6].toULong()); + if (messageList[8]!="0") + resultMessage+=i18n("One revocation certificate imported.
","%n revocation certificates imported.
",messageList[8].toULong()); + if (messageList[9]!="0") + { + resultMessage+=i18n("One secret key processed.
","%n secret keys processed.
",messageList[9].toULong()); + secretImport=true; + } + if (messageList[10]!="0") + resultMessage+=i18n("One secret key imported.
","%n secret keys imported.
",messageList[10].toULong()); + if (messageList[11]!="0") + resultMessage+=i18n("One secret key unchanged.
","%n secret keys unchanged.
",messageList[11].toULong()); + if (messageList[12]!="0") + resultMessage+=i18n("One secret key not imported.
","%n secret keys not imported.
",messageList[12].toULong()); + if (messageList[2]!="0") + resultMessage+=i18n("One key imported:
","%n keys imported:
",messageList[2].toULong()); + + if (secretImport) resultMessage+=i18n("
You have imported a secret key.
" + "Please note that imported secret keys are not trusted by default.
" + "To fully use this secret key for signing and encryption, you must edit the key (double click on it) and set its trust to Full or Ultimate.
"); + } else + resultMessage=i18n("No key imported... \nCheck detailed log for more infos"); + + if (messageList[8]!="0") importedKeysIds="ALL"; + if ((messageList[9]!="0") && (importedKeysIds.isEmpty())) // orphaned secret key imported + emit refreshOrphaned(); + emit importfinished(importedKeysIds); + + (void) new KDetailedInfo(0,"import_result",resultMessage,message,importedKeys); +} + +void KgpgInterface::importURLover(KProcess *p) +{ + KIO::NetAccess::removeTempFile(tempKeyFile); + importover(p); + //KMessageBox::information(0,message); + //emit importfinished(); +} + +void KgpgInterface::importprocess(KProcIO *p) +{ + QString outp; + while (p->readln(outp)!=-1) { + if (outp.find("http-proxy")==-1) + message+=outp+"\n"; + } +} + + +/////////////////////////////////////////////////////////////////////////////////////// User ID's + + +void KgpgInterface::KgpgAddUid(QString keyID,QString name,QString email,QString comment) +{ +uidName=name; +uidComment=comment; +uidEmail=email; +output=QString::null; +addSuccess=true; + + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<< "gpg"<<"--no-tty"<<"--status-fd=2"<<"--command-fd=0"<<"--utf8-strings"; + *conprocess<<"--edit-key"<start(KProcess::NotifyOnExit,true); +} + +void KgpgInterface::adduidover(KProcess *) +{ +if (addSuccess) emit addUidFinished(); +else emit addUidError(output); +} + +void KgpgInterface::adduidprocess(KProcIO *p) +{ + QString required=QString::null; + while (p->readln(required,true)!=-1) { + output+=required+"\n"; + if (required.find("USERID_HINT",0,false)!=-1) + updateIDs(required); + + if (required.find("keygen.name")!=-1) { + p->writeStdin(uidName); + required=QString::null; + } + + if (required.find("keygen.email")!=-1) { + p->writeStdin(uidEmail); + required=QString::null; + } + + if (required.find("keygen.comment")!=-1) { + p->writeStdin(uidComment); + required=QString::null; + } + + if (required.find("passphrase.enter")!=-1) { + QCString delpass; + int code=KPasswordDialog::getPassword(delpass,i18n("Enter passphrase for %1:") + .arg(userIDs)); + if (code!=QDialog::Accepted) { + //addSuccess=false; + p->writeStdin("quit"); + p->closeWhenDone(); + return; + } + p->writeStdin(delpass,true); + required=QString::null; + + } + + if (required.find("keyedit.prompt")!=-1) { + p->writeStdin("save"); + required=QString::null; + } + + if ((required.find("GET_")!=-1)) /////// gpg asks for something unusal, turn to konsole mode + { + kdDebug(2100)<<"unknown request"<writeStdin("quit"); + p->closeWhenDone(); + } + } +} + + + + + + + + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// photo id's + +void KgpgInterface::KgpgGetPhotoList(QString keyID) +{ +photoList.clear(); +output=QString::null; +photoCount=1; +userIDs=keyID; + + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<< "gpg"<<"--no-tty"<<"--status-fd=2"<<"--command-fd=0"; + *conprocess<<"--with-colon"<<"--list-keys"<start(KProcess::NotifyOnExit,true); +} + +void KgpgInterface::photoreadprocess(KProcIO *p) +{ + QString required=QString::null; + while (p->readln(required,true)!=-1) { + output+=required+"\n"; + if (required.startsWith("uat") || required.startsWith("uid")) photoCount++; +} +} + + +void KgpgInterface::photoreadover(KProcess *) +{ +for (int i=1;isetAutoDelete(true); + QString pgpgOutput="cp %i "+kgpginfotmp->name(); + +KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<< "gpg"<<"--no-tty"<<"--status-fd=2"<<"--command-fd=0"<<"--utf8-strings"; + *conprocess<<"--photo-viewer"<start(KProcess::Block); + if (kgpginfotmp->file()->size()>0) + { + kgpginfotmp->unlink(); + return true; + } + kgpginfotmp->unlink(); + return false; +} + +void KgpgInterface::KgpgDeletePhoto(QString keyID,QString uid) +{ + delSuccess=true; + output=QString::null; + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<< "gpg"<<"--no-tty"<<"--status-fd=2"<<"--command-fd=0"<<"--utf8-strings"; + *conprocess<<"--edit-key"<start(KProcess::NotifyOnExit,true); +} + +void KgpgInterface::delphotoover(KProcess *) +{ +if (delSuccess) emit delPhotoFinished(); +else emit delPhotoError(output); +} + +void KgpgInterface::delphotoprocess(KProcIO *p) +{ + QString required=QString::null; + while (p->readln(required,true)!=-1) { + output+=required+"\n"; + if (required.find("USERID_HINT",0,false)!=-1) + updateIDs(required); + + if (required.find("keyedit.remove.uid.okay")!=-1) { + p->writeStdin("YES"); + required=QString::null; + } + + if (required.find("passphrase.enter")!=-1) { + QCString delpass; + int code=KPasswordDialog::getPassword(delpass,i18n("Enter passphrase for %1:").arg(userIDs)); + if (code!=QDialog::Accepted) { + //deleteSuccess=false; + p->writeStdin("quit"); + p->closeWhenDone(); + return; + } + p->writeStdin(delpass,true); + required=QString::null; + + } + + if (required.find("keyedit.prompt")!=-1) { + p->writeStdin("save"); + required=QString::null; + } + + if ((required.find("GET_")!=-1)) /////// gpg asks for something unusal, turn to konsole mode + { + kdDebug(2100)<<"unknown request"<writeStdin("quit"); + p->closeWhenDone(); + + } + } +} + + +void KgpgInterface::KgpgAddPhoto(QString keyID,QString imagePath) +{ +photoUrl=imagePath; +output=QString::null; +addSuccess=true; + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<< "gpg"<<"--no-tty"<<"--status-fd=2"<<"--command-fd=0"<<"--utf8-strings"; + *conprocess<<"--edit-key"<start(KProcess::NotifyOnExit,true); +} + +void KgpgInterface::addphotoover(KProcess *) +{ +if (addSuccess) emit addPhotoFinished(); +else emit addPhotoError(output); +} + +void KgpgInterface::addphotoprocess(KProcIO *p) +{ + QString required=QString::null; + while (p->readln(required,true)!=-1) { + output+=required+"\n"; + if (required.find("USERID_HINT",0,false)!=-1) + updateIDs(required); + + if (required.find("photoid.jpeg.add")!=-1) { + p->writeStdin(photoUrl); + required=QString::null; + } + + if (required.find("photoid.jpeg.size")!=-1) { + if (KMessageBox::questionYesNo(0,i18n("This image is very large. Use it anyway?"), QString::null, i18n("Use Anyway"), i18n("Do Not Use"))==KMessageBox::Yes) + p->writeStdin("Yes"); + else + { + p->writeStdin("No"); + p->writeStdin(""); + p->writeStdin("quit"); + } + required=QString::null; + } + + if (required.find("passphrase.enter")!=-1) { + QCString delpass; + int code=KPasswordDialog::getPassword(delpass,i18n("Enter passphrase for %1:").arg(userIDs)); + if (code!=QDialog::Accepted) { + //deleteSuccess=false; + p->writeStdin("quit"); + p->closeWhenDone(); + return; + } + p->writeStdin(delpass,true); + required=QString::null; + + } + + if (required.find("keyedit.prompt")!=-1) { + p->writeStdin("save"); + required=QString::null; + } + + if ((required.find("GET_")!=-1)) /////// gpg asks for something unusal, turn to konsole mode + { + kdDebug(2100)<<"unknown request"<writeStdin("quit"); + addSuccess=false; + p->closeWhenDone(); + + } + } +} + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// key revocation + +void KgpgInterface::KgpgRevokeKey(QString keyID,QString revokeUrl,int reason,QString description) +{ + revokeReason=reason; + revokeSuccess=false; + revokeDescription=description; + certificateUrl=revokeUrl; + output=QString::null; + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<< "gpg"<<"--no-tty"<<"--status-fd=2"<<"--logger-fd=2"<<"--command-fd=0"<<"--utf8-strings"; + if (!revokeUrl.isEmpty()) + *conprocess<<"-o"<start(KProcess::NotifyOnExit,true); +} + +void KgpgInterface::revokeover(KProcess *) +{ + if (!revokeSuccess) + KMessageBox::detailedSorry(0,i18n("Creation of the revocation certificate failed..."),output); + else { + output=output.section("-----BEGIN",1); + output.prepend("-----BEGIN"); + output=output.section("BLOCK-----",0); + emit revokecertificate(output); + if (!certificateUrl.isEmpty()) + emit revokeurl(certificateUrl); + } +} + +void KgpgInterface::revokeprocess(KProcIO *p) +{ + QString required=QString::null; + while (p->readln(required,true)!=-1) { + output+=required+"\n"; + + if (required.find("USERID_HINT",0,false)!=-1) + updateIDs(required); + + if ((required.find("GOOD_PASSPHRASE")!=-1)) + revokeSuccess=true; + + if ((required.find("gen_revoke.okay")!=-1) || (required.find("ask_revocation_reason.okay")!=-1) || (required.find("openfile.overwrite.okay")!=-1)) { + p->writeStdin("YES"); + required=QString::null; + } + + if (required.find("ask_revocation_reason.code")!=-1) { + p->writeStdin(QString::number(revokeReason)); + required=QString::null; + } + + if (required.find("passphrase.enter")!=-1) { + QCString signpass; + int code=KPasswordDialog::getPassword(signpass,i18n("Enter passphrase for %1:").arg(userIDs)); + if (code!=QDialog::Accepted) { + expSuccess=3; ///// aborted by user mode + p->writeStdin("quit"); + p->closeWhenDone(); + return; + } + p->writeStdin(signpass,true); + required=QString::null; + + } + if (required.find("ask_revocation_reason.text")!=-1) { + // kdDebug(2100)<<"description"<writeStdin(revokeDescription); + revokeDescription=QString::null; + required=QString::null; + } + if ((required.find("GET_")!=-1)) /////// gpg asks for something unusal, turn to konsole mode + { + kdDebug(2100)<<"unknown request"<writeStdin("quit"); + p->closeWhenDone(); + + } + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// parsing of ./gnupg/options file + +QString KgpgInterface::getGpgSetting(QString name,QString configFile) +{ + name=name.stripWhiteSpace()+" "; + QFile qfile(QFile::encodeName(configFile)); + if (qfile.open(IO_ReadOnly) && (qfile.exists())) { + QString result; + QTextStream t( &qfile ); + result=t.readLine(); + while (result!=NULL) { + if (result.stripWhiteSpace().startsWith(name)) { + result=result.stripWhiteSpace(); + result.remove(0,name.length()); + result=result.stripWhiteSpace(); + return result.section(" ",0,0); + } + result=t.readLine(); + } + qfile.close(); + } + return QString::null; +} + +QString KgpgInterface::getGpgMultiSetting(QString name,QString configFile) +{ +// get GnuPG setting for item that can have multiple entries (eg. encrypt-to) + +QString parsedResult=QString::null; + + name=name.stripWhiteSpace()+" "; + QFile qfile(QFile::encodeName(configFile)); + if (qfile.open(IO_ReadOnly) && (qfile.exists())) { + QString result; + QTextStream t( &qfile ); + result=t.readLine(); + while (result!=NULL) { + if (result.stripWhiteSpace().startsWith(name)) { + result=result.stripWhiteSpace(); + result.remove(0,name.length()); + if (parsedResult!=QString::null) + parsedResult+=" "+result.stripWhiteSpace(); + else + parsedResult+=result.stripWhiteSpace(); + //return result.section(" ",0,0); + } + result=t.readLine(); + } + qfile.close(); + } + return parsedResult; +} + +void KgpgInterface::delGpgGroup(QString name, QString configFile) +{ + QString textToWrite; + QFile qfile(QFile::encodeName(configFile)); + if (qfile.open(IO_ReadOnly) && (qfile.exists())) { + QString result; + QTextStream t( &qfile ); + result=t.readLine(); + while (result!=NULL) { + if (result.stripWhiteSpace().startsWith("group ")) { + QString result2=result.stripWhiteSpace(); + result2.remove(0,6); + result2=result2.stripWhiteSpace(); + if (result2.startsWith(name) && (result2.remove(0,name.length()).stripWhiteSpace().startsWith("="))) + result=QString::null; + } + if (result!=QString::null) textToWrite+=result+"\n"; + result=t.readLine(); + } + qfile.close(); + if (qfile.open(IO_WriteOnly)) { + QTextStream t( &qfile); + t << textToWrite; + qfile.close(); + } + } +} + +void KgpgInterface::setGpgGroupSetting(QString name,QStringList values, QString configFile) +{ + QString textToWrite; + bool found=false; + QFile qfile(QFile::encodeName(configFile)); + kdDebug(2100)<<"Changing group: "<= 0 ; ++idx ) { + char str[2] = "x"; + str[0] = (char) QString( txt.mid( idx + 2, 2 ) ).toShort( 0, 16 ); + txt.replace( idx, 4, str ); + } + if (!strchr (txt.ascii(), 0xc3)) + return QString::fromUtf8(txt.ascii()); + else + return QString::fromUtf8(QString::fromUtf8(txt.ascii()).ascii()); // perform Utf8 twice, or some keys display badly + + return txt; +} + + +#include "kgpginterface.moc" diff --git a/kgpg/kgpginterface.h b/kgpg/kgpginterface.h new file mode 100644 index 0000000..4fb21b2 --- /dev/null +++ b/kgpg/kgpginterface.h @@ -0,0 +1,404 @@ +/*************************************************************************** + kgpginterface.h - description + ------------------- + begin : Sat Jun 29 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGINTERFACE_H +#define KGPGINTERFACE_H + + +#include +#include +#include +#include + +class QLabel; +class KProcIO; +class KProcess; +class KLed; + +/** + * Encrypt a file using gpg. + */ + +class KgpgInterface : public QObject +{ + + Q_OBJECT + +public: + /** + * Initialize the class + */ + KgpgInterface(); + + /* + * Destructor for the class. + */ + ~KgpgInterface(); + +public slots: + + /**Encrypt file function + * @param userIDs the recipients key id's. + * @param srcUrl Kurl of the file to encrypt. + * @param destUrl Kurl for the encrypted file. + * @param Options String with the wanted gpg options. ex: "--armor" + * @param symetrical bool whether the encryption should be symmetrical. + */ + void KgpgEncryptFile(QStringList encryptKeys,KURL srcUrl,KURL destUrl,QStringList Options=QString::null,bool symetrical=false); + + /**Encrypt file function + * @param userIDs the key user identification. + * @param srcUrl Kurl of the file to decrypt. + * @param destUrl Kurl for the decrypted file. + * @param chances int number of trials left for decryption (used only as an info displayed in the password dialog) + */ + void KgpgDecryptFile(KURL srcUrl,KURL destUrl,QStringList Options=QStringList()); + + /**Sign file function + * @param keyID QString the signing key ID. + * @param srcUrl Kurl of the file to sign. + * @param Options String with the wanted gpg options. ex: "--armor" + */ + void KgpgSignFile(QString keyID,KURL srcUrl,QStringList Options=QStringList()); + + /**Verify file function + * @param sigUrl Kurl of the signature file. + * @param srcUrl Kurl of the file to be verified. If empty, gpg will try to find it using the signature file name (by removing the .sig extensio) + */ + void KgpgVerifyFile(KURL sigUrl,KURL srcUrl=KURL()) ; + + void KgpgVerifyText(QString text); + void slotverifyread(KProcIO *p); + void slotverifyresult(KProcess*); + + + /**Import key function + * @param url Kurl the url of the key file. Allows public & secret key import. + */ + void importKeyURL(KURL url); + /**Import key function + * @param keystr QString containing th key. Allows public & secret key import. + */ + void importKey(QString keystr); + + /**Key signature function + * @param keyID QString the ID of the key to be signed + * @param signKeyID QString the ID of the signing key + * @param signKeyMail QString the name of the signing key (only used to prompt user for passphrase) + * @param local bool should the signature be local + */ + void KgpgSignKey(QString keyID,QString signKeyID,QString signKeyMail=QString::null,bool local=false,int checking=0); + + /**Key signature deletion function + * @param keyID QString the ID of the key + * @param signKeyID QString the ID of the signature key + */ + void KgpgDelSignature(QString keyID,QString signKeyID); + + /**Encrypt text function + * @param text QString text to be encrypted. + * @param userIDs the recipients key id's. + * @param Options String with the wanted gpg options. ex: "--armor" + * returns the encrypted text or empty string if encyption failed + */ + void KgpgEncryptText(QString text,QStringList userIDs, QStringList Options=QString::null); + + /**Decrypt text function + * @param text QString text to be decrypted. + * @param userID QString the name of the decryption key (only used to prompt user for passphrase) + */ + //static QString KgpgDecryptText(QString text,QString userID); + void KgpgDecryptText(QString text,QStringList Options=QString::null); + void txtdecryptfin(KProcess *); + + /**Extract list of photographic user id's + * @param keyID the recipients key id's. + */ + void KgpgGetPhotoList(QString keyID); + + void getOutput(KProcess *, char *data, int ); + void getCmdOutput(KProcess *p, char *data, int ); + + QString getKey(QStringList IDs, bool attributes); + + void KgpgKeyExpire(QString keyID,QDate date,bool unlimited); + void KgpgTrustExpire(QString keyID,int keyTrust); + void KgpgChangePass(QString keyID); + + void KgpgRevokeKey(QString keyID,QString revokeUrl,int reason,QString description); + void revokeover(KProcess *); + void revokeprocess(KProcIO *p); + void KgpgDeletePhoto(QString keyID,QString uid); + void KgpgAddPhoto(QString keyID,QString imagePath); + + void KgpgAddUid(QString keyID,QString name,QString email,QString comment); + + void KgpgDecryptFileToText(KURL srcUrl,QStringList Options); + void KgpgSignText(QString text,QString userIDs, QStringList Options); + + static QString getGpgSetting(QString name,QString configFile); + static QString getGpgMultiSetting(QString name,QString configFile); + static void setGpgSetting(QString name,QString ID,QString url); + static void setGpgMultiSetting(QString name,QStringList values,QString url); + static bool getGpgBoolSetting(QString name,QString configFile); + static void setGpgBoolSetting(QString name,bool enable,QString url); + static QStringList getGpgGroupNames(QString configFile); + static QStringList getGpgGroupSetting(QString name,QString configFile); + static void setGpgGroupSetting(QString name,QStringList values, QString configFile); + static void delGpgGroup(QString name, QString configFile); + static QString checkForUtf8(QString txt); + static QString checkForUtf8bis(QString txt); + static int getGpgVersion(); + + + +private slots: + + void openSignConsole(); + /** + * Checks output of the signature process + */ + void signover(KProcess *); + /** + * Read output of the signature process + */ + void sigprocess(KProcIO *p); + + /** + * Checks if the encrypted file was saved. + */ + void encryptfin(KProcess *); + + /** + * Checks if the decrypted file was saved. + */ + void decryptfin(KProcess *); + + /** + * Checks if the signing was successful. + */ + void signfin(KProcess *p); + + /** + * Checks the number of uid's for a key-> if greater than one, key signature will switch to konsole mode + */ + int checkuid(QString KeyID); + + /** + * Reads output of the delete signature process + */ + void delsigprocess(KProcIO *p); + /** + * Checks output of the delete signature process + */ + void delsignover(KProcess *p); + /** + * Checks output of the import process + */ + void importURLover(KProcess *p); + void importover(KProcess *); + /** + * Read output of the import process + */ + void importprocess(KProcIO *p); + /** + * Reads output of the current process + allow overwriting of a file + */ + void readprocess(KProcIO *p); + /** + * Reads output of the current encryption process + allow overwriting of a file + */ + void readencprocess(KProcIO *p); + /** + * Reads output of the current signing process + allow overwriting of a file + */ + void readsignprocess(KProcIO *p); + /** + * Reads output of the current decryption process + allow overwriting of a file + */ + void readdecprocess(KProcIO *p); + /** + * Checks output of the verify process + */ + void verifyfin(KProcess *p); + + void expprocess(KProcIO *p); + void expover(KProcess*); + void trustprocess(KProcIO *p); + void passprocess(KProcIO *p); + void trustover(KProcess *); + void passover(KProcess *); + + void txtreadencprocess(KProcIO *p); + + void txtencryptfin(KProcess *); + + void delphotoover(KProcess *); + void delphotoprocess(KProcIO *p); + void addphotoover(KProcess *); + void addphotoprocess(KProcIO *p); + + void adduidover(KProcess *); + void adduidprocess(KProcIO *p); + + void slotReadKey(KProcIO *p); + void photoreadover(KProcess *); + void photoreadprocess(KProcIO *p); + bool isPhotoId(int uid); + void updateIDs(QString txtString); + + void txtsignprocess(KProcIO *p); + void txtsignfin(KProcess *); + + //void txtdecryptfin(KProcess *); + + +signals: + + void missingSignature(QString); + void verifyOver(QString,QString); + + /** + * emitted when a txt decryption failed. returns log output + */ + void txtdecryptionfailed(QString); + /** + * emitted when a txt encryption starts. + */ + void txtencryptionstarted(); + + /** + * emitted when a txt decryption finished. returns decrypted text + */ + void txtdecryptionfinished(QString); + /** + * emitted when a txt encryption finished. returns encrypted text + */ + void txtencryptionfinished(QString); + /** + * emitted when an error occurred + */ + void errormessage(QString); + /** + * true if encryption successful, false on error. + */ + void encryptionfinished(KURL); + /** + * true if key signature deletion successful, false on error. + */ + void delsigfinished(bool); + + /** + * Signature process result: 0=successful, 1=error, 2=bad passphrase + */ + void signatureFinished(int); + /** + * emitted when user cancels process + */ + void processaborted(bool); + /** + * emitted when the process starts + */ + void processstarted(QString); + /** + * true if decryption successful, false on error. + */ + void decryptionfinished(); + /** + * emitted if bad passphrase was giver + */ + void badpassphrase(bool); + /** + * true if import successful, false on error. + */ + void importfinished(QStringList); + /** + * true if verify successful, false on error. + */ + void verifyfinished(); + /** + * emmitted if signature key is missing & user want to import it from keyserver + */ + void verifyquerykey(QString ID); + /** + * true if signature successful, false on error. + */ + void signfinished(); + void delPhotoFinished(); + void delPhotoError(QString); + + void addPhotoFinished(); + void addPhotoError(QString); + void refreshOrphaned(); + + void addUidFinished(); + void addUidError(QString); + + void trustfinished(); + void revokecertificate(QString); + void revokeurl(QString); + void expirationFinished(int); + void signalPhotoList(QStringList); + void passwordChanged(); + + void txtSignOver(QString); + + +private: + /** + * @internal structure for communication + */ + QString message,tempKeyFile,userIDs,output,keyString,txtToEncrypt,log; + QCString passphrase; + bool deleteSuccess,konsLocal,anonymous,decfinished,decok,badmdc,revokeSuccess,addSuccess,delSuccess; + bool signmiss; + QString signID; + int signSuccess,expSuccess,trustValue,konsChecked; + int step,signb,sigsearch,expirationDelay; + QString konsSignKey, konsKeyID,errMessage; + int revokeReason,photoCount; + QString revokeDescription,certificateUrl,photoUrl; + QStringList photoList; + QString uidName, uidEmail, uidComment; + KURL sourceFile; + QString decryptUrl; + + QString gpgOutput; + + /** + * @internal structure for the file information + */ + KURL file; + +}; + +class Md5Widget :public KDialogBase +{ + Q_OBJECT +public: + Md5Widget(QWidget *parent=0, const char *name=0,KURL url=KURL()); + ~Md5Widget(); +public slots: + void slotApply(); +private: + QString mdSum; + KLed *KLed1; + QLabel *TextLabel1_2; +}; + +#endif // KGPGINTERFACE_HKGPGINTERFACE_H + diff --git a/kgpg/kgpglibrary.cpp b/kgpg/kgpglibrary.cpp new file mode 100644 index 0000000..55455f9 --- /dev/null +++ b/kgpg/kgpglibrary.cpp @@ -0,0 +1,245 @@ +/*************************************************************************** + kgpglibrary.cpp - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "kgpglibrary.h" +#include "popuppublic.h" +#include "kgpginterface.h" +#include + +KgpgLibrary::KgpgLibrary(QWidget *parent, bool pgpExtension) +{ + if (pgpExtension) + extension=".pgp"; + else + extension=".gpg"; + popIsActive=false; + panel=parent; +} + +KgpgLibrary::~KgpgLibrary() +{} + + +void KgpgLibrary::slotFileEnc(KURL::List urls,QStringList opts,QStringList defaultKey,KShortcut goDefaultKey) +{ + ///////////////////////////////////////////////////////////////////////// encode file file + if (!urls.empty()) { + urlselecteds=urls; + if (defaultKey.isEmpty()) { + QString fileNames=urls.first().fileName(); + if (urls.count()>1) fileNames+=",..."; + popupPublic *dialogue=new popupPublic(0,"Public keys",fileNames,true,goDefaultKey); + connect(dialogue,SIGNAL(selectedKey(QStringList,QStringList,bool,bool)),this,SLOT(startencode(QStringList,QStringList,bool,bool))); + dialogue->exec(); + delete dialogue; + } else + startencode(defaultKey,opts,false,false); + } +} + +void KgpgLibrary::startencode(QStringList encryptKeys,QStringList encryptOptions,bool shred,bool symetric) +{ + popIsActive=false; + //KURL::List::iterator it; + //filesToEncode=urlselecteds.count(); + _encryptKeys=encryptKeys; + _encryptOptions=encryptOptions; + _shred=shred; + _symetric=symetric; + fastencode(urlselecteds.first(),encryptKeys,encryptOptions,symetric); +} + + +void KgpgLibrary::fastencode(KURL &fileToCrypt,QStringList selec,QStringList encryptOptions,bool symetric) +{ + ////////////////// encode from file + if ((selec.isEmpty()) && (!symetric)) { + KMessageBox::sorry(0,i18n("You have not chosen an encryption key.")); + return; + } + urlselected=fileToCrypt; + KURL dest; + if (encryptOptions.find("--armor")!=encryptOptions.end()) + dest.setPath(urlselected.path()+".asc"); + else + dest.setPath(urlselected.path()+extension); + + QFile fgpg(dest.path()); + + if (fgpg.exists()) { + KIO::RenameDlg *over=new KIO::RenameDlg(0,i18n("File Already Exists"),QString::null,dest.path(),KIO::M_OVERWRITE); + if (over->exec()==QDialog::Rejected) + { + delete over; + emit systemMessage(QString::null,true); + return; + } + dest=over->newDestURL(); + delete over; + } + int filesToEncode=urlselecteds.count(); + if (filesToEncode>1) + emit systemMessage(i18n("%1 Files left.\nEncrypting %2").arg(filesToEncode).arg(urlselecteds.first().path())); + else emit systemMessage(i18n("Encrypting %2").arg(urlselecteds.first().path())); + KgpgInterface *cryptFileProcess=new KgpgInterface(); + pop = new KPassivePopup(panel); + cryptFileProcess->KgpgEncryptFile(selec,urlselected,dest,encryptOptions,symetric); + if (!popIsActive) + { + //connect(cryptFileProcess,SIGNAL(processstarted(QString)),this,SLOT(processpopup2(QString))); + popIsActive=true; + } + connect(cryptFileProcess,SIGNAL(encryptionfinished(KURL)),this,SLOT(processenc(KURL))); + connect(cryptFileProcess,SIGNAL(errormessage(QString)),this,SLOT(processencerror(QString))); +} + +void KgpgLibrary::processpopup2(QString fileName) +{ + + //pop->setTimeout(0); + pop->setView(i18n("Processing encryption (%1)").arg(fileName),i18n("Please wait..."),KGlobal::iconLoader()->loadIcon("kgpg",KIcon::Desktop)); + pop->show(); + /*QRect qRect(QApplication::desktop()->screenGeometry()); + int iXpos=qRect.width()/2-pop->width()/2; + int iYpos=qRect.height()/2-pop->height()/2; + pop->move(iXpos,iYpos);*/ + +} + +void KgpgLibrary::shredpreprocessenc(KURL fileToShred) +{ + popIsActive=false; + emit systemMessage(QString::null); + shredprocessenc(fileToShred); +} + +void KgpgLibrary::shredprocessenc(KURL::List filesToShred) +{ +emit systemMessage(i18n("Shredding %n file","Shredding %n files",filesToShred.count())); + +KIO::Job *job; +job = KIO::del( filesToShred, true ); +connect( job, SIGNAL( result( KIO::Job * ) ),SLOT( slotShredResult( KIO::Job * ) ) ); +} + +void KgpgLibrary::slotShredResult( KIO::Job * job ) +{ + emit systemMessage(QString::null); + if (job && job->error()) + { + job->showErrorDialog( (QWidget*)parent() ); + emit systemMessage(QString::null,true); + KPassivePopup::message(i18n("KGpg Error"),i18n("Process halted, not all files were shredded."),KGlobal::iconLoader()->loadIcon("kgpg",KIcon::Desktop),panel,"kgpg_error",0); + } +} + + +void KgpgLibrary::processenc(KURL) +{ + emit systemMessage(QString::null); + if (_shred) shredprocessenc(urlselecteds.first()); + urlselecteds.pop_front (); + if (urlselecteds.count()>0) + fastencode(urlselecteds.first(),_encryptKeys,_encryptOptions,_symetric); +} + +void KgpgLibrary::processencerror(QString mssge) +{ + popIsActive=false; + emit systemMessage(QString::null,true); + KMessageBox::detailedSorry(panel,i18n("Process halted.
Not all files were encrypted."),mssge); +} + + + +void KgpgLibrary::slotFileDec(KURL srcUrl,KURL destUrl,QStringList customDecryptOption) +{ + ////////////////////////////////////////////////////////////////// decode file from konqueror or menu + KgpgInterface *decryptFileProcess=new KgpgInterface(); + pop = new KPassivePopup(); + urlselected=srcUrl; + decryptFileProcess->KgpgDecryptFile(srcUrl,destUrl,customDecryptOption); + connect(decryptFileProcess,SIGNAL(processaborted(bool)),this,SLOT(processdecover())); + connect(decryptFileProcess,SIGNAL(processstarted(QString)),this,SLOT(processpopup(QString))); + connect(decryptFileProcess,SIGNAL(decryptionfinished()),this,SLOT(processdecover())); + connect(decryptFileProcess,SIGNAL(errormessage(QString)),this,SLOT(processdecerror(QString))); +} + +void KgpgLibrary::processpopup(QString fileName) +{ + emit systemMessage(i18n("Decrypting %1").arg(fileName)); + pop->setTimeout(0); + pop->setView(i18n("Processing decryption"),i18n("Please wait..."),KGlobal::iconLoader()->loadIcon("kgpg",KIcon::Desktop)); + pop->show(); + QRect qRect(QApplication::desktop()->screenGeometry()); + int iXpos=qRect.width()/2-pop->width()/2; + int iYpos=qRect.height()/2-pop->height()/2; + pop->move(iXpos,iYpos); +} + +void KgpgLibrary::processdecover() +{ + emit systemMessage(QString::null); + delete pop; + emit decryptionOver(); +} + + +void KgpgLibrary::processdecerror(QString mssge) +{ + delete pop; + emit systemMessage(QString::null); + ///// test if file is a public key + QFile qfile(QFile::encodeName(urlselected.path())); + if (qfile.open(IO_ReadOnly)) { + QTextStream t( &qfile ); + QString result(t.read()); + qfile.close(); + ////////////// if pgp data found, decode it + if (result.startsWith("-----BEGIN PGP PUBLIC KEY BLOCK")) {////// dropped file is a public key, ask for import + int result=KMessageBox::warningContinueCancel(0,i18n("

The file %1 is a public key.
Do you want to import it ?

").arg(urlselected.path()),i18n("Warning")); + if (result==KMessageBox::Cancel) + return; + else { + KgpgInterface *importKeyProcess=new KgpgInterface(); + importKeyProcess->importKeyURL(urlselected); + connect(importKeyProcess,SIGNAL(importfinished(QStringList)),this,SIGNAL(importOver(QStringList))); + return; + } + } else if (result.startsWith("-----BEGIN PGP PRIVATE KEY BLOCK")) {////// dropped file is a public key, ask for import + qfile.close(); + KMessageBox::information(0,i18n("

The file %1 is a private key block. Please use KGpg key manager to import it.

").arg(urlselected.path())); + return; + } + } + KMessageBox::detailedSorry(0,i18n("Decryption failed."),mssge); +} + + + +#include "kgpglibrary.moc" diff --git a/kgpg/kgpglibrary.h b/kgpg/kgpglibrary.h new file mode 100644 index 0000000..1892f5f --- /dev/null +++ b/kgpg/kgpglibrary.h @@ -0,0 +1,81 @@ +/*************************************************************************** + kgpglibrary.h - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef KGPGLIBRARY_H +#define KGPGLIBRARY_H + +#include +#include +#include +#include + +class KPassivePopup; +class KProgress; + +class KgpgLibrary : public QObject +{ + + Q_OBJECT + +public: + /** + * Initialize the class + */ + KgpgLibrary(QWidget *parent=0,bool pgpExtension=false); + ~KgpgLibrary(); + + KURL::List urlselecteds; + +public slots: + void slotFileEnc(KURL::List urls=KURL(""),QStringList opts=QString::null,QStringList defaultKey=QString::null,KShortcut goDefaultKey=QKeySequence(CTRL+Qt::Key_Home)); + void slotFileDec(KURL srcUrl,KURL destUrl,QStringList customDecryptOption=QStringList()); + void shredprocessenc(KURL::List filesToShred); + +private slots: + void startencode(QStringList encryptKeys,QStringList encryptOptions,bool shred,bool symetric); + void fastencode(KURL &fileToCrypt,QStringList selec,QStringList encryptOptions,bool symetric); +// void startencode(QString &selec,QString encryptOptions,bool shred,bool symetric); + void slotShredResult( KIO::Job * job ); + void shredpreprocessenc(KURL fileToShred); + void processenc(KURL); + void processdecover(); + void processdecerror(QString mssge); + void processencerror(QString mssge); + void processpopup(QString fileName); + void processpopup2(QString fileName); + +private: + QString customDecrypt,tempFile,extension; + KURL urlselected; + KPassivePopup *pop; + KProgress *shredProgressBar; + bool popIsActive; + QWidget *panel; + QStringList _encryptKeys; + QStringList _encryptOptions; + bool _shred; + bool _symetric; + +signals: + void decryptionOver(); + void importOver(QStringList); + void systemMessage(QString,bool reset=false); +}; + +#endif // KGPGLIBRARY_H + diff --git a/kgpg/kgpgoptions.cpp b/kgpg/kgpgoptions.cpp new file mode 100644 index 0000000..a45e8a6 --- /dev/null +++ b/kgpg/kgpgoptions.cpp @@ -0,0 +1,601 @@ +/*************************************************************************** + kgpgoptions.cpp - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/////////////////////////////////////////////// code for the option dialog box + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kgpgoptions.h" +#include "kgpgsettings.h" +#include "listkeys.h" + +#include "conf_decryption.h" +#include "conf_encryption.h" +#include "conf_gpg.h" +#include "conf_servers.h" +#include "conf_ui2.h" +#include "conf_misc.h" + +class QTabWidget; + +/////////////////////// main window + +kgpgOptions::kgpgOptions(QWidget *parent, const char *name) + : KConfigDialog( parent, name, KGpgSettings::self()) +{ + defaultServerList="hkp://wwwkeys.eu.pgp.net "; + defaultServerList+=i18n("(Default)"); + defaultServerList+=",hkp://search.keyserver.net,hkp://wwwkeys.pgp.net,hkp://pgp.dtype.org,hkp://wwwkeys.us.pgp.net"; + config = new KConfig ("kgpgrc"); + config->setGroup("Servers"); + serverList=QStringList::split (",",config->readEntry("Server_List",defaultServerList)); + keyServer = KgpgInterface::getGpgSetting("keyserver", KGpgSettings::gpgConfigPath()); + + if (!keyServer.isEmpty()) serverList.prepend(keyServer+" "+i18n("(Default)")); + + defaultHomePath=QDir::homeDirPath()+"/.gnupg/"; + if (QFile(defaultHomePath+"options").exists()) defaultConfigPath="options"; + else + { + if (QFile(defaultHomePath+"gpg.conf").exists()) defaultConfigPath="gpg.conf"; + else defaultConfigPath=QString::null; + } + +kdDebug(2100)<<"Adding pages"<tabWidget3->page(1),QBoxLayout::TopToBottom,10); + kfc=new KFontChooser(page3->tabWidget3->page(1),"kcfg_Font",false,QStringList(),false); + fontLayout->addWidget(kfc); + + page7->shredInfo->setText(i18n( "

You must be aware that shredding is not secure on all file systems, and that parts of the file may have been saved in a temporary file or in the spooler of your printer if you previously opened it in an editor or tried to print it. Only works on files (not on folders).

")); + page7->groupShred->adjustSize(); + pixkeySingle=KGlobal::iconLoader()->loadIcon("kgpg_key1",KIcon::Small,20); + pixkeyDouble=KGlobal::iconLoader()->loadIcon("kgpg_key2",KIcon::Small,20); + addPage(page1, i18n("Encryption"), "encrypted"); + addPage(page2, i18n("Decryption"), "decrypted"); + addPage(page3, i18n("Appearance"), "looknfeel"); + addPage(page4, i18n("GnuPG Settings"), "kgpg"); + addPage(page6, i18n("Key Servers"), "network"); + addPage(page7, i18n("Misc"), "misc"); + + page1->clear_akey->setIconSet(QIconSet(QPixmap(SmallIcon("clear_left")))); + page1->clear_fkey->setIconSet(QIconSet(QPixmap(SmallIcon("clear_left")))); + + // The following widgets are managed manually. + connect(page1->change_fkey, SIGNAL(clicked()), this, SLOT(insertFileKey())); + connect(page1->clear_fkey, SIGNAL(clicked()), page1->kcfg_FileKey, SLOT(clear())); + connect(page1->change_akey, SIGNAL(clicked()), this, SLOT(insertAlwaysKey())); + connect(page1->clear_akey, SIGNAL(clicked()), page1->alwaysKey, SLOT(clear())); + connect(page1->alwaysKey, SIGNAL(textChanged(const QString&)), this, SLOT(updateButtons())); + connect(page4->gpg_conf_path, SIGNAL(textChanged(const QString&)), this, SLOT(updateButtons())); + connect(page4->gpg_home_path, SIGNAL(textChanged(const QString&)), this, SLOT(updateButtons())); + connect(page4->use_agent, SIGNAL(toggled(bool)), this, SLOT(updateButtons())); + connect(page4->changeHome, SIGNAL(clicked()), this, SLOT(slotChangeHome())); + connect(page4->kcfg_PubKeyring, SIGNAL(toggled (bool)), page4->kcfg_PubKeyringUrl, SLOT(setEnabled(bool))); + connect(page4->kcfg_PubKeyring, SIGNAL(toggled (bool)), this, SLOT(checkAdditionalState(bool))); + connect(page4->kcfg_PrivKeyring, SIGNAL(toggled (bool)), page4->kcfg_PrivKeyringUrl, SLOT(setEnabled(bool))); + connect(page4->kcfg_PrivKeyring, SIGNAL(toggled (bool)), this, SLOT(checkAdditionalState(bool))); + connect(page6->server_add, SIGNAL(clicked()), this, SLOT(slotAddKeyServer())); + connect(page6->server_del, SIGNAL(clicked()), this, SLOT(slotDelKeyServer())); + connect(page6->server_default, SIGNAL(clicked()), this, SLOT(slotDefaultKeyServer())); + connect(page6->ServerBox, SIGNAL(currentChanged ( QListBoxItem *)), this, SLOT(updateButtons())); + connect(page7->pushShredder, SIGNAL(clicked ()), this, SIGNAL(installShredder())); + + //connect(this, SIGNAL(settingsChanged()), SLOT(updateSettings())); + + keyGood=KGpgSettings::colorGood(); + keyUnknown=KGpgSettings::colorUnknown(); + keyRev=KGpgSettings::colorRev(); + keyBad=KGpgSettings::colorBad(); +} + + +kgpgOptions::~kgpgOptions() +{ +delete config; +} + + +void kgpgOptions::checkAdditionalState(bool) +{ +// enable / disable the "use only this keyring" option depending on the other checkboxes state + +if (page4->kcfg_PubKeyring->isOn() && page4->kcfg_PrivKeyring->isOn()) +page4->kcfg_OnlyAdditional->setEnabled(true); +else +page4->kcfg_OnlyAdditional->setEnabled(false); +} + +void kgpgOptions::insertFileKey() +{ + QString signKeyID; + ///// open key selection dialog + KgpgSelKey *opts=new KgpgSelKey(this,0,true,page1->kcfg_FileKey->text()); + + if (opts->exec()==QDialog::Accepted) { + page1->kcfg_FileKey->setText(opts->getkeyID()); + } else { + delete opts; + return; + } + delete opts; +} + +void kgpgOptions::insertAlwaysKey() +{ + QString signKeyID; + ///// open key selection dialog + KgpgSelKey *opts=new KgpgSelKey(this,0,true,page1->alwaysKey->text()); + + if (opts->exec()==QDialog::Accepted) { + page1->alwaysKey->setText(opts->getkeyID()); + } else { + delete opts; + return; + } + delete opts; +} + +void kgpgOptions::slotChangeHome() +{ +QString gpgHome=KFileDialog::getExistingDirectory(page4->gpg_home_path->text(),this,i18n("New GnuPG Home Location")); +if (gpgHome.isEmpty()) return; +if (!gpgHome.endsWith("/")) gpgHome.append("/"); + QString confPath="options"; + if (!QFile(gpgHome+confPath).exists()) { + confPath="gpg.conf"; + if (!QFile(gpgHome+confPath).exists()) + { + if (KMessageBox::questionYesNo(this,i18n("No configuration file was found in the selected location.\nDo you want to create it now ?\n\nWithout configuration file, neither KGpg nor Gnupg will work properly."),i18n("No Configuration File Found"),i18n("Create"),i18n("Ignore"))==KMessageBox::Yes) ////////// Try to create config File by running gpg once + { + KProcIO *p=new KProcIO(); + *p<<"gpg"<<"--homedir"<start(KProcess::Block); //// start gnupg so that it will create a config file + confPath="gpg.conf"; + QFile confFile(gpgHome+confPath); + if (!confFile.open(IO_WriteOnly)) + {KMessageBox::sorry(this,i18n("Cannot create configuration file. Please check if destination media is mounted and if you have write access")); + return; + } + else + { + QTextStream stream( &confFile ); + stream<<"# Config file created by KGpg\n\n"; + confFile.close(); + } + } + else confPath=QString::null; + } + } + page4->gpg_conf_path->setText(confPath); + page4->gpg_home_path->setText(gpgHome); +} + +void kgpgOptions::updateWidgets() +{ +QString pubKeyring,privKeyring; + + gpgConfigPath = KGpgSettings::gpgConfigPath(); + page4->gpg_conf_path->setText(KURL(gpgConfigPath).fileName()); + page4->gpg_home_path->setText(KURL(gpgConfigPath).directory(false)); + + pubKeyring=KgpgInterface::getGpgSetting("keyring", gpgConfigPath); + if (pubKeyring!="") + { + page4->kcfg_PubKeyringUrl->setURL(pubKeyring); + page4->kcfg_PubKeyring->setChecked(true); + } + else page4->kcfg_PubKeyring->setChecked(false); + + privKeyring=KgpgInterface::getGpgSetting("secret-keyring", gpgConfigPath); + if (privKeyring!="") + { + page4->kcfg_PrivKeyringUrl->setURL(privKeyring); + page4->kcfg_PrivKeyring->setChecked(true); + } + else page4->kcfg_PrivKeyring->setChecked(false); + + page4->kcfg_OnlyAdditional->setChecked(KgpgInterface::getGpgBoolSetting("no-default-keyring", gpgConfigPath)); + + // fill some values from kgpg's config file + + useAgent = KgpgInterface::getGpgBoolSetting("use-agent", gpgConfigPath); + defaultUseAgent = false; + + page1->alwaysKey->setText(KgpgInterface::getGpgMultiSetting("encrypt-to", gpgConfigPath)); + alwaysKeyID = page1->alwaysKey->text(); + + page4->use_agent->setChecked( useAgent ); + + keyServer = KgpgInterface::getGpgSetting("keyserver", gpgConfigPath); + defaultKeyServer = "hkp://wwwkeys.pgp.net"; + + if (keyServer.isEmpty()) + keyServer = defaultKeyServer; + + page6->ServerBox->clear(); + page6->ServerBox->insertStringList(serverList); + + + kdDebug(2100)<<"Finishing options"<alwaysKey->clear(); + page1->kcfg_FileKey->clear(); + + page4->use_agent->setChecked( defaultUseAgent ); + + page4->gpg_conf_path->setText(defaultConfigPath); + page4->gpg_home_path->setText(defaultHomePath); + + page4->kcfg_PubKeyringUrl->setURL(QString::null); + page4->kcfg_PubKeyring->setChecked(false); + page4->kcfg_PrivKeyringUrl->setURL(QString::null); + page4->kcfg_PrivKeyring->setChecked(false); + page4->kcfg_OnlyAdditional->setChecked(false); + + + page6->ServerBox->clear(); + page6->ServerBox->insertStringList(QStringList::split(",",defaultServerList)); + + kdDebug(2100)<<"Finishing default options"<alwaysKey->text().isEmpty()) + return false; + + if (page4->gpg_conf_path->text()!=defaultConfigPath) + return false; + + if (page4->gpg_home_path->text()!=defaultHomePath) + return false; + + if (page4->use_agent->isChecked() != defaultUseAgent) + return false; + + QString currList; + for (uint i=0;iServerBox->count();i++) + currList+=page6->ServerBox->text(i)+","; + currList.truncate(currList.length()-1); + if (currList!=defaultServerList) return false; + + return true; +} + +bool kgpgOptions::hasChanged() +{ + + if (page1->alwaysKey->text()!= alwaysKeyID) + return true; + + if (page4->gpg_conf_path->text() != KURL(gpgConfigPath).fileName()) + return true; + if (page4->gpg_home_path->text() != KURL(gpgConfigPath).directory(false)) + return true; + + if (page4->use_agent->isChecked() != useAgent) + return true; + + QStringList currList; + for (uint i=0;iServerBox->count();i++) + currList.append(page6->ServerBox->text(i)); + if (currList!=serverList) return true; + + return false; +} + +void kgpgOptions::updateSettings() +{ + // Update config path first! + + KGpgSettings::setGpgConfigPath( page4->gpg_home_path->text()+page4->gpg_conf_path->text() ); + KGpgSettings::writeConfig(); //Don't forget to write the config file + if (page4->gpg_home_path->text()!=KURL(gpgConfigPath).directory(false)) + { + if (page4->gpg_home_path->text()!=defaultHomePath) + setenv("GNUPGHOME", QFile::encodeName(page4->gpg_home_path->text()), 1); + else setenv("GNUPGHOME","",1); + emit homeChanged(); + gpgConfigPath = KGpgSettings::gpgConfigPath(); + } + + bool emitReload=false; + + if (page4->kcfg_OnlyAdditional->isChecked()!=KgpgInterface::getGpgBoolSetting("no-default-keyring", gpgConfigPath)) emitReload=true; + KgpgInterface::setGpgBoolSetting("no-default-keyring",page4->kcfg_OnlyAdditional->isChecked(), gpgConfigPath); + + if (page4->kcfg_PubKeyring->isChecked()) + { + if (page4->kcfg_PubKeyringUrl->url()!=KgpgInterface::getGpgSetting("keyring", gpgConfigPath)) emitReload=true; + KgpgInterface::setGpgSetting("keyring",page4->kcfg_PubKeyringUrl->url(), gpgConfigPath); + } + else + { + if (KgpgInterface::getGpgSetting("keyring", gpgConfigPath)!="") emitReload=true; + KgpgInterface::setGpgSetting("keyring",QString::null, gpgConfigPath); + } + + if (page4->kcfg_PrivKeyring->isChecked()) + { + if (page4->kcfg_PrivKeyringUrl->url()!=KgpgInterface::getGpgSetting("secret-keyring", gpgConfigPath)) emitReload=true; + KgpgInterface::setGpgSetting("secret-keyring",page4->kcfg_PrivKeyringUrl->url(), gpgConfigPath); + } + else + { + if (KgpgInterface::getGpgSetting("secret-keyring", gpgConfigPath)!="") emitReload=true; + KgpgInterface::setGpgSetting("secret-keyring",QString::null, gpgConfigPath); + } + + emit changeFont(kfc->font()); + /////////////// install service menus + + if (page7->kcfg_SignMenu->currentItem()==KGpgSettings::EnumSignMenu::AllFiles) + slotInstallSign("all/allfiles"); + else + slotRemoveMenu("signfile.desktop"); + if (page7->kcfg_DecryptMenu->currentItem()==KGpgSettings::EnumDecryptMenu::AllFiles) + slotInstallDecrypt("all/allfiles"); + else if (page7->kcfg_DecryptMenu->currentItem()==KGpgSettings::EnumDecryptMenu::EncryptedFiles) + slotInstallDecrypt("application/pgp-encrypted,application/pgp-signature,application/pgp-keys"); + else + slotRemoveMenu("decryptfile.desktop"); + + KgpgInterface::setGpgMultiSetting("encrypt-to",QStringList::split(" ",page1->alwaysKey->text()),KGpgSettings::gpgConfigPath()); + alwaysKeyID = page1->alwaysKey->text(); + + useAgent = page4->use_agent->isChecked(); + + if (useAgent) + { + KgpgInterface::setGpgBoolSetting("use-agent",true, KGpgSettings::gpgConfigPath()); + KgpgInterface::setGpgBoolSetting("no-use-agent",false, KGpgSettings::gpgConfigPath()); + } + else + { + // KgpgInterface::setGpgBoolSetting("no-use-agent",true, KGpgSettings::gpgConfigPath()); + KgpgInterface::setGpgBoolSetting("use-agent",false, KGpgSettings::gpgConfigPath()); + } + + ////////////////// save key servers + + + QString currList; + serverList=QStringList (); + for (uint i=0;iServerBox->count();i++) + { + QString currItem=page6->ServerBox->text(i); + if (currItem.find(" ")!=-1) // it is the default keyserver + keyServer=currItem.section(" ",0,0); + else + { + serverList.append(currItem); + } + } + + KgpgInterface::setGpgSetting("keyserver",keyServer, KGpgSettings::gpgConfigPath()); + serverList.prepend(keyServer+" "+i18n("(Default)")); + currList=serverList.join(","); + + if (keyGood!=page3->kcfg_ColorGood->color()) + emit refreshTrust(GoodColor,page3->kcfg_ColorGood->color()); + if (keyBad!=page3->kcfg_ColorBad->color()) emit refreshTrust(BadColor,page3->kcfg_ColorBad->color()); + if (keyUnknown!=page3->kcfg_ColorUnknown->color()) emit refreshTrust(UnknownColor,page3->kcfg_ColorUnknown->color()); + if (keyRev!=page3->kcfg_ColorRev->color()) emit refreshTrust(RevColor,page3->kcfg_ColorRev->color()); + + +// KGpgSettings::writeConfig(); + config->setGroup("Servers"); + config->writeEntry("Server_List",currList); + emit settingsUpdated(); + if (emitReload) emit reloadKeyList(); +} + + +void kgpgOptions::slotInstallSign(QString mimetype) +{ + + QString path=locateLocal("data","konqueror/servicemenus/signfile.desktop"); + KDesktopFile configl2(path, false); + if (configl2.isImmutable() ==false) { + configl2.setGroup("Desktop Entry"); + configl2.writeEntry("ServiceTypes", mimetype); + configl2.writeEntry("Actions", "sign"); + configl2.setGroup("Desktop Action sign"); + configl2.writeEntry("Name",i18n("Sign File")); + //configl2.writeEntry("Icon", "sign_file"); + configl2.writeEntry("Exec","kgpg -S %F"); + //KMessageBox::information(this,i18n("Decrypt file option is now added in Konqueror's menu.")); + } +} + +void kgpgOptions::slotInstallDecrypt(QString mimetype) +{ + + QString path=locateLocal("data","konqueror/servicemenus/decryptfile.desktop"); + KDesktopFile configl2(path, false); + if (configl2.isImmutable() ==false) { + configl2.setGroup("Desktop Entry"); + configl2.writeEntry("ServiceTypes", mimetype); + configl2.writeEntry("Actions", "decrypt"); + configl2.setGroup("Desktop Action decrypt"); + configl2.writeEntry("Name",i18n("Decrypt File")); + //configl2.writeEntry("Icon", "decrypt_file"); + configl2.writeEntry("Exec","kgpg %U"); + //KMessageBox::information(this,i18n("Decrypt file option is now added in Konqueror's menu.")); + } +} + + +void kgpgOptions::slotRemoveMenu(QString menu) +{ + + QString path=locateLocal("data","konqueror/servicemenus/"+menu); + QFile qfile(path); + if (qfile.exists()) + qfile.remove(); + { + //if (!qfile.remove()) KMessageBox::sorry(this,i18n("Cannot remove service menu. Check permissions")); + //else KMessageBox::information(this,i18n("Service menu 'Decrypt File' has been removed.")); + } + //else KMessageBox::sorry(this,i18n("No service menu found")); + +} + +QString kgpgOptions::namecode(QString kid) +{ + + for ( uint counter = 0; counter',0,0); + names+=name; + ids+=tst.section(':',4,4); + if (tst.section(':',4,4).right(8)==alwaysKeyID) + alwaysKeyName=tst.section(':',4,4).right(8)+":"+name; + if (issec.find(tst.section(':',4,4).right(8),0,FALSE)!=-1) + { +//*** page1->file_key->insertItem(pixkeyDouble,tst.section(':',4,4).right(8)+":"+name); +//*** page1->always_key->insertItem(pixkeyDouble,tst.section(':',4,4).right(8)+":"+name); + } + else + { +//*** page1->file_key->insertItem(pixkeySingle,tst.section(':',4,4).right(8)+":"+name); +//*** page1->always_key->insertItem(pixkeySingle,tst.section(':',4,4).right(8)+":"+name); + } + } + } + } + pclose(fp); + if (counter==0) { + ids+="0"; +//*** page1->file_key->insertItem(i18n("none")); +//*** page1->always_key->insertItem(i18n("none")); + } +} + +void kgpgOptions::slotAddKeyServer() +{ +QString newServer=KInputDialog::getText(i18n("Add New Key Server"),i18n("Server URL:")); +if (!newServer.isEmpty()) +page6->ServerBox->insertItem(newServer.stripWhiteSpace()); +page6->ServerBox->setSelected(page6->ServerBox->findItem(newServer.stripWhiteSpace()),true); +} + +void kgpgOptions::slotDelKeyServer() +{ +bool defaultDeleted=false; +if (page6->ServerBox->currentText().find(" ")!=-1) defaultDeleted=true; +page6->ServerBox->removeItem(page6->ServerBox->currentItem()); +page6->ServerBox->setSelected(0,true); +if (defaultDeleted) page6->ServerBox->changeItem(page6->ServerBox->currentText().section(" ",0,0)+" "+i18n("(Default)"),0); +} + +void kgpgOptions::slotDefaultKeyServer() +{ +uint curr=page6->ServerBox->currentItem(); +page6->ServerBox->changeItem(page6->ServerBox->currentText ().section(" ",0,0)+" "+i18n("(Default)"),curr); + +for (uint i=0;iServerBox->count();i++) +{ +if (i!=curr) +page6->ServerBox->changeItem(page6->ServerBox->text(i).section(" ",0,0),i); +} +page6->ServerBox->setSelected(curr,true); +} + +#include "kgpgoptions.moc" + diff --git a/kgpg/kgpgoptions.h b/kgpg/kgpgoptions.h new file mode 100644 index 0000000..05a7b32 --- /dev/null +++ b/kgpg/kgpgoptions.h @@ -0,0 +1,106 @@ +/*************************************************************************** + kgpgoptions.h - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef KGPGOPTIONS_H +#define KGPGOPTIONS_H + +#include + +#define GoodColor 0 +#define BadColor 1 +#define UnknownColor 2 +#define RevColor 3 + +class KConfig; +class Encryption; +class Decryption; +class UIConf; +class GPGConf; +class ServerConf; +class ColorsConf; +class MiscConf; +class KFontChooser; +class KConfig; +class KSimpleConfig; + +class kgpgOptions : public KConfigDialog +{ + Q_OBJECT +public: + kgpgOptions(QWidget *parent=0, const char *name=0); + ~kgpgOptions(); + QStringList names,ids; + Encryption *page1; + Decryption *page2; + UIConf *page3; + GPGConf *page4; + ServerConf *page6; + MiscConf *page7; + KFontChooser *kfc; + +private: + KConfig *config; + QString alwaysKeyID,alwaysKeyName; + bool firstDisplay; + + QPixmap pixkeySingle,pixkeyDouble; + QString fileEncryptionKey; + QString gpgConfigPath; + QString keyServer,defaultServerList; + QString defaultKeyServer; + QFont startFont; + bool useAgent; + bool defaultUseAgent; + bool encryptToAlways; + bool defaultEncryptToAlways; + QStringList serverList; + QString defaultConfigPath,defaultHomePath; + QColor keyGood,keyBad,keyUnknown,keyRev; + +private: + bool hasChanged(); + bool isDefault(); + +private slots: + void checkAdditionalState(bool); + void slotAddKeyServer(); + void slotDelKeyServer(); + void slotDefaultKeyServer(); + void updateWidgets(); + void updateWidgetsDefault(); + void updateSettings(); + void insertAlwaysKey(); + void insertFileKey(); + + void listkey(); + QString namecode(QString kid); + QString idcode(QString kname); + void slotInstallDecrypt(QString mimetype); + void slotInstallSign(QString mimetype); + void slotRemoveMenu(QString menu); + void slotChangeHome(); +signals: + void updateDisplay(); + void settingsUpdated(); + void changeFont(QFont); + void homeChanged(); + void refreshTrust(int, QColor); + void installShredder(); + void reloadKeyList(); +}; + +#endif // KGPGOPTIONS_H + diff --git a/kgpg/kgpgrevokewidget.ui b/kgpg/kgpgrevokewidget.ui new file mode 100644 index 0000000..0884276 --- /dev/null +++ b/kgpg/kgpgrevokewidget.ui @@ -0,0 +1,152 @@ + +KgpgRevokeWidget + + + KgpgRevokeWidget + + + + 0 + 0 + 459 + 230 + + + + + unnamed + + + 0 + + + + keyID + + + key id + + + AlignVCenter + + + + + cbPrint + + + Print certificate + + + + + textLabel1 + + + Create revocation certificate for + + + + + textLabel4 + + + Description: + + + + + + No Reason + + + + + Key Has Been Compromised + + + + + Key is Superseded + + + + + Key is No Longer Used + + + + comboBox1 + + + + + textLabel3 + + + Reason for revocation: + + + + + cbSave + + + Save certificate: + + + true + + + + + cbImport + + + true + + + Import into keyring + + + + + textDescription + + + + + kURLRequester1 + + + + + + + + + cbSave + toggled(bool) + KgpgRevokeWidget + cbSave_toggled(bool) + + + + comboBox1 + textDescription + cbSave + cbPrint + cbImport + kURLRequester1 + + + kgpgrevokewidget.ui.h + + + cbSave_toggled( bool isOn ) + + + + kpushbutton.h + + diff --git a/kgpg/kgpgrevokewidget.ui.h b/kgpg/kgpgrevokewidget.ui.h new file mode 100644 index 0000000..6d13319 --- /dev/null +++ b/kgpg/kgpgrevokewidget.ui.h @@ -0,0 +1,21 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ +//(C) 2002 Jean-Baptiste Mardelle + +void KgpgRevokeWidget::cbSave_toggled( bool isOn) +{ +kURLRequester1->setEnabled(isOn); +} diff --git a/kgpg/kgpgsettings.kcfgc b/kgpg/kgpgsettings.kcfgc new file mode 100644 index 0000000..afbe628 --- /dev/null +++ b/kgpg/kgpgsettings.kcfgc @@ -0,0 +1,9 @@ +# Code generation options for kconfig_compiler +File=kgpg.kcfg +ClassName=KGpgSettings +Singleton=true +Mutators=true +# Inherits=KConfigSkeleton +IncludeFiles=kgpginterface.h +# MemberVariables=public +CustomAdditions=true \ No newline at end of file diff --git a/kgpg/kgpgsettings_addons.h b/kgpg/kgpgsettings_addons.h new file mode 100644 index 0000000..6b2e8f5 --- /dev/null +++ b/kgpg/kgpgsettings_addons.h @@ -0,0 +1,41 @@ +/*************************************************************************** + kgpgsettings_addons.h - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2003Waldo Bastian + email : bastian@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +public: + static + QString defaultKey() + { + if (self()->mDefaultKey.isEmpty()) + { + self()->mDefaultKey = KgpgInterface::getGpgSetting("default-key", gpgConfigPath()); + if (!self()->mDefaultKey.isEmpty()) + self()->mDefaultKey.prepend("0x"); + } + return self()->mDefaultKey; + } + + static + void setDefaultKey(const QString &_defaultKey) + { + self()->mDefaultKey = _defaultKey; + KgpgInterface::setGpgSetting("default-key",_defaultKey.right(8),gpgConfigPath()); + if (!_defaultKey.startsWith("0x")) + self()->mDefaultKey.prepend("0x"); + } + +private: + QString mDefaultKey; diff --git a/kgpg/kgpgview.cpp b/kgpg/kgpgview.cpp new file mode 100644 index 0000000..c9bff6a --- /dev/null +++ b/kgpg/kgpgview.cpp @@ -0,0 +1,409 @@ +/*************************************************************************** + kgpgview.cpp - description + ------------------- + begin : Tue Jul 2 12:31:38 GMT 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +////////////////////////////////////////////////////////////// code for the main view (editor) + +// include files for Qt +//#include + +// application specific includes + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "kgpgsettings.h" +#include "kgpginterface.h" +#include "kgpgview.h" +#include "keyservers.h" +#include "keyserver.h" +#include "kgpg.h" +#include "kgpgeditor.h" +#include "listkeys.h" +#include "popuppublic.h" +#include "detailedconsole.h" + +//////////////// configuration for editor + +MyEditor::MyEditor( QWidget *parent, const char *name ) + : KTextEdit( parent, name ) +{ + setTextFormat(PlainText); + setCheckSpellingEnabled (true); + setAcceptDrops(true); +} + +void MyEditor::contentsDragEnterEvent( QDragEnterEvent *e ) +{ + //////////////// if a file is dragged into editor ... + e->accept (KURLDrag::canDecode(e) || QTextDrag::canDecode (e)); + //e->accept (QTextDrag::canDecode (e)); +} + + + + +void MyEditor::contentsDropEvent( QDropEvent *e ) +{ + ///////////////// decode dropped file + KURL::List list; + QString text; + if ( KURLDrag::decode( e, list ) ) + slotDroppedFile(list.first()); + else if ( QTextDrag::decode(e, text) ) + insert(text); +} + +void MyEditor::slotDroppedFile(KURL url) +{ + ///////////////// decide what to do with dropped file + QString text; + if (!tempFile.isEmpty()) { + KIO::NetAccess::removeTempFile(tempFile); + tempFile=QString::null; + } + + if (url.isLocalFile()) + tempFile = url.path(); + else { + if (KMessageBox::warningContinueCancel(0,i18n("Remote file dropped.
The remote file will now be copied to a temporary file to process requested operation. This temporary file will be deleted after operation.
"),0,KStdGuiItem::cont(),"RemoteFileWarning")!=KMessageBox::Continue) + return; + if (!KIO::NetAccess::download (url, tempFile,this)) { + KMessageBox::sorry(this,i18n("Could not download file.")); + return; + } + } + + + ///////////// if dropped filename ends with gpg, pgp or asc, try to decode it + if ((tempFile.endsWith(".gpg")) || (tempFile.endsWith(".asc")) || (tempFile.endsWith(".pgp"))) { + slotDecodeFile(tempFile); + } + else slotCheckContent(tempFile); +} + + +bool MyEditor::slotCheckContent(QString fileToCheck, bool checkForPgpMessage) +{ +QFile qfile(fileToCheck); + if (qfile.open(IO_ReadOnly)) { + ////////// open file + + QTextStream t( &qfile ); + QString result(t.read()); + ////////////// if pgp data found, decode it + if ((checkForPgpMessage) && (result.startsWith("-----BEGIN PGP MESSAGE"))) { + qfile.close(); + slotDecodeFile(fileToCheck); + return true; + } else + if (result.startsWith("-----BEGIN PGP PUBLIC KEY BLOCK")) {////// dropped file is a public key, ask for import + qfile.close(); + int result=KMessageBox::warningContinueCancel(this,i18n("

The file %1 is a public key.
Do you want to import it ?

").arg(fileToCheck),i18n("Warning")); + if (result==KMessageBox::Cancel) { + KIO::NetAccess::removeTempFile(fileToCheck); + return true; + } else { + KgpgInterface *importKeyProcess=new KgpgInterface(); + importKeyProcess->importKeyURL(KURL(fileToCheck)); + connect(importKeyProcess,SIGNAL(importfinished(QStringList)),this,SLOT(slotProcessResult(QStringList))); + return true; + } + } else { + if (result.startsWith("-----BEGIN PGP PRIVATE KEY BLOCK")) { + qfile.close(); + KMessageBox::information(0,i18n("This file is a private key.\nPlease use kgpg key management to import it.")); + KIO::NetAccess::removeTempFile(fileToCheck); + return true; + } + + setText(result); + qfile.close(); + KIO::NetAccess::removeTempFile(fileToCheck); + } + } + return false; +} + + +void MyEditor::editorUpdateDecryptedtxt(QString newtxt) +{ + setText(newtxt); +} + +void MyEditor::editorFailedDecryptedtxt(QString newtxt) +{ + if (!slotCheckContent(tempFile,false)) + KMessageBox::detailedSorry(this,i18n("Decryption failed."),newtxt); +} + + +void MyEditor::slotDecodeFile(QString fname) +{ + //////////////// decode file from given url into editor + QFile qfile(QFile::encodeName(fname)); + if (qfile.open(IO_ReadOnly)) { + KgpgInterface *txtDecrypt=new KgpgInterface(); + connect (txtDecrypt,SIGNAL(txtdecryptionfinished(QString)),this,SLOT(editorUpdateDecryptedtxt(QString))); + connect (txtDecrypt,SIGNAL(txtdecryptionfailed(QString)),this,SLOT(editorFailedDecryptedtxt(QString))); + txtDecrypt->KgpgDecryptFileToText(KURL(fname),QStringList::split(QString(" "),KGpgSettings::customDecrypt().simplifyWhiteSpace())); + } else + KMessageBox::sorry(this,i18n("Unable to read file.")); +} + + +void MyEditor::slotProcessResult(QStringList iKeys) +{ + emit refreshImported(iKeys); + KIO::NetAccess::removeTempFile(tempFile); + tempFile=QString::null; +} + + +////////////////////////// main view configuration + +KgpgView::KgpgView(QWidget *parent, const char *name) : QWidget(parent, name) +{ + editor=new MyEditor(this); + windowAutoClose=true; + + ///// layout + + QVBoxLayout *vbox=new QVBoxLayout(this,3); + + editor->setReadOnly( false ); + editor->setUndoRedoEnabled(true); + editor->setUndoDepth(5); + + setAcceptDrops(true); + + KButtonBox *boutonbox=new KButtonBox(this,KButtonBox::Horizontal,15,12); + boutonbox->addStretch(1); + + bouton0=boutonbox->addButton(i18n("S&ign/Verify"),this,SLOT(clearSign()),TRUE); + bouton1=boutonbox->addButton(i18n("En&crypt"),this,SLOT(popuppublic()),TRUE); + bouton2=boutonbox->addButton(i18n("&Decrypt"),this,SLOT(slotdecode()),TRUE); + + QObject::connect(editor,SIGNAL(textChanged()),this,SLOT(modified())); + + boutonbox->layout(); + editor->resize(editor->maximumSize()); + vbox->addWidget(editor); + vbox->addWidget(boutonbox); +} + + +void KgpgView::modified() +{ + /////////////// notify for changes in editor window + KgpgApp *win=(KgpgApp *) parent(); + if (win->fileSave->isEnabled()==false) { + QString capt=win->Docname.fileName(); + if (capt.isEmpty()) + capt=i18n("untitled"); + win->setCaption(capt,true); + win->fileSave->setEnabled(true); + win->editUndo->setEnabled(true); + } + +} + +void KgpgView::slotAskForImport(QString ID) +{ +if (KMessageBox::questionYesNo(0,i18n("Missing signature:
Key id: %1

" + "Do you want to import this key from a keyserver?
").arg(ID),i18n("Missing Key"), QString::null, i18n("Import"), i18n("Do Not Import"))==KMessageBox::Yes) { + keyServer *kser=new keyServer(0,"server_dialog",false,true); + kser->page->kLEimportid->setText(ID); + kser->slotImport(); + windowAutoClose=false; + } + else emit verifyFinished(); +} + +void KgpgView::slotVerifyResult(QString mssge,QString log) +{ +emit verifyFinished(); +//KMessageBox::information(0,mssge); +(void) new KDetailedInfo(0,"verify_result",mssge,log); +} + +void KgpgView::clearSign() +{ + QString mess=editor->text(); + if (mess.startsWith("-----BEGIN PGP SIGNED")) { + ////////////////////// this is a signed message, verify it + KgpgInterface *verifyProcess=new KgpgInterface(); + connect(verifyProcess,SIGNAL(missingSignature(QString)),this,SLOT(slotAskForImport(QString))); + connect(verifyProcess,SIGNAL(verifyOver(QString,QString)),this,SLOT(slotVerifyResult(QString,QString))); + verifyProcess->KgpgVerifyText(mess); + } + else { + ///// Sign the text in Editor + QString signKeyID; + ///// open key selection dialog + KgpgSelKey *opts=new KgpgSelKey(this,0); + + if (opts->exec()==QDialog::Accepted) { + signKeyID=opts->getkeyID(); + } else { + delete opts; + return; + } + delete opts; + + KgpgInterface *signProcess=new KgpgInterface(); + connect(signProcess,SIGNAL(txtSignOver(QString)),this,SLOT(slotSignResult(QString))); + QStringList options=NULL; + if (KGpgSettings::pgpCompatibility()) + options<<"--pgp6"; + signProcess->KgpgSignText(mess,signKeyID,options); +} +} + + +void KgpgView::slotSignResult(QString signResult) +{ +if (signResult.isEmpty()) +KMessageBox::sorry(this,i18n("Signing not possible: bad passphrase or missing key")); +else +{ + editor->setText(signResult); + emit resetEncoding(false); + + KgpgApp *win=(KgpgApp *) parent(); + win->editRedo->setEnabled(false); + win->editUndo->setEnabled(false); +} +} + + + +void KgpgView::popuppublic() +{ + ///// popup dialog to select public key for encryption + + //////// open dialog --> popuppublic.cpp + popupPublic *dialogue=new popupPublic(this, "public_keys", 0,false,((KgpgApp *) parent())->goDefaultKey); + connect(dialogue,SIGNAL(selectedKey(QStringList,QStringList,bool,bool)),this,SLOT(encodetxt(QStringList,QStringList,bool,bool))); + dialogue->exec(); + delete dialogue; +} + + +////////////////////////////////////////////////////////////////////////////////////// decode + +void KgpgView::slotdecode() +{ + /////////////// decode data from the editor. triggered by the decode button + + QString dests,encUsers; + messages=QString::null; + + //QString resultat=KgpgInterface::KgpgDecryptText(editor->text(),encUsers); + KgpgInterface *txtDecrypt=new KgpgInterface(); + connect (txtDecrypt,SIGNAL(txtdecryptionfinished(QString)),this,SLOT(updateDecryptedtxt(QString))); + connect (txtDecrypt,SIGNAL(txtdecryptionfailed(QString)),this,SLOT(failedDecryptedtxt(QString))); + txtDecrypt->KgpgDecryptText(editor->text(),QStringList::split(QString(" "),KGpgSettings::customDecrypt().simplifyWhiteSpace())); + + /* + KgpgApp *win=(KgpgApp *) parent(); + if (!resultat.isEmpty()) { + editor->setText(resultat); + win->editRedo->setEnabled(false); + win->editUndo->setEnabled(false); + }*/ +} + +void KgpgView::updateDecryptedtxt(QString newtxt) +{ + //kdDebug(2100)<<"UTF8 Test Result--------------"<setText(newtxt); + emit resetEncoding(false); +} + +bool KgpgView::checkForUtf8(QString text) +{ //// try to guess if the decrypted text uses utf-8 encoding + QTextCodec *codec =QTextCodec::codecForLocale (); + if (codec->canEncode(text)) return true; + return false; +} + +void KgpgView::failedDecryptedtxt(QString newtxt) +{ + KMessageBox::detailedSorry(this,i18n("Decryption failed."),newtxt); +} + + +void KgpgView::encodetxt(QStringList selec,QStringList encryptOptions,bool, bool symmetric) +{ + ////////////////// encode from editor + if (KGpgSettings::pgpCompatibility()) + encryptOptions<<"--pgp6"; + + if (symmetric) selec.clear(); + + KgpgInterface *txtCrypt=new KgpgInterface(); + connect (txtCrypt,SIGNAL(txtencryptionfinished(QString)),this,SLOT(updatetxt(QString))); + txtCrypt->KgpgEncryptText(editor->text(),selec,encryptOptions); + //KMessageBox::sorry(0,"OVER"); + + //KgpgInterface::KgpgEncryptText(editor->text(),selec,encryptOptions); + //if (!resultat.isEmpty()) editor->setText(resultat); + //else KMessageBox::sorry(this,i18n("Decryption failed.")); +} + +void KgpgView::updatetxt(QString newtxt) +{ + if (!newtxt.isEmpty()) + editor->setText(newtxt); + else + KMessageBox::sorry(this,i18n("Encryption failed.")); +} + + +KgpgView::~KgpgView() +{ +delete editor; +} + +/* +void KgpgView::print(QPrinter *pPrinter) +{ + QPainter printpainter; + printpainter.begin(pPrinter); + + // TODO: add your printing code here + + printpainter.end(); +} +*/ +#include "kgpgview.moc" + diff --git a/kgpg/kgpgview.h b/kgpg/kgpgview.h new file mode 100644 index 0000000..d6183bb --- /dev/null +++ b/kgpg/kgpgview.h @@ -0,0 +1,121 @@ +/************************************************************************** + kgpgview.h - description + ------------------- + begin : Tue Jul 2 12:31:38 GMT 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KGPGVIEW_H +#define KGPGVIEW_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +class QDragEnterEvent; + +//class KgpgDoc; + +/** The KgpgView class provides the view widget for the KgpgApp instance. + * The View instance inherits QWidget as a base class and represents the view object of a KTMainWindow. As KgpgView is part of the + * docuement-view model, it needs a reference to the document object connected with it by the KgpgApp class to manipulate and display + * the document structure provided by the KgpgDoc class. + * + * @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team. + * @version KDevelop version 0.4 code generation + */ + +class MyEditor : public KTextEdit +{ + Q_OBJECT + +public: + MyEditor( QWidget *parent = 0, const char *name = 0); +private: + QString message,messages,tempFile; +public slots: + void slotDecodeFile(QString); + void slotDroppedFile(KURL url); + void slotProcessResult(QStringList iKeys); + bool slotCheckContent(QString fileToCheck, bool checkForPgpMessage=true); + +protected: + void contentsDragEnterEvent( QDragEnterEvent *e ); + void contentsDropEvent( QDropEvent *e ); + +private slots: + void editorUpdateDecryptedtxt(QString newtxt); + void editorFailedDecryptedtxt(QString newtxt); + +signals: + void refreshImported(QStringList); +}; + + +class KgpgView : public QWidget +{ + Q_OBJECT + friend class MyEditor; +public: + /** Constructor for the main view */ + KgpgView(QWidget *parent = 0, const char *name=0); + /** Destructor for the main view */ + ~KgpgView(); + + /** returns a pointer to the document connected to the view instance. Mind that this method requires a KgpgApp instance as a parent + * widget to get to the window document pointer by calling the KgpgApp::getDocument() method. + * + * @see KgpgApp#getDocument + */ + // KgpgDoc *getDocument() const; + + // QTextEdit *editor; + + MyEditor *editor; + KURL fselected; + bool windowAutoClose; + + /** contains the implementation for printing functionality */ + // void print(QPrinter *pPrinter); + + QPushButton *bouton1,*bouton2,*bouton0; +private: + QString messages; + +public slots: + void slotdecode(); + void clearSign(); + +private slots: + void slotVerifyResult(QString mssge,QString log); + void slotSignResult(QString signResult); + void slotAskForImport(QString ID); + void popuppublic(); + void modified(); + void encodetxt(QStringList selec,QStringList encryptOptions,bool, bool symmetric); + void updatetxt(QString); + void updateDecryptedtxt(QString newtxt); + void failedDecryptedtxt(QString newtxt); + bool checkForUtf8(QString text); + +signals: + void resetEncoding(bool); + void verifyFinished(); + void verifyDetach(); +}; + +#endif // KGPGVIEW_H + diff --git a/kgpg/kgpgwizard.ui b/kgpg/kgpgwizard.ui new file mode 100644 index 0000000..36d1501 --- /dev/null +++ b/kgpg/kgpgwizard.ui @@ -0,0 +1,405 @@ + +KgpgWizard + + + KgpgWizard + + + + 0 + 0 + 559 + 356 + + + + KGpg Wizard + + + + page + + + Introduction + + + + unnamed + + + + pixmapLabel1 + + + + 0 + 5 + 0 + 0 + + + + NoFrame + + + Plain + + + image0 + + + false + + + AlignTop + + + + + textLabel1 + + + <h1>Welcome to the KGpg Wizard</h1> +This wizard will first setup some basic configuration options required for KGpg to work properly. Next, it will allow you to create your own key pair, enabling you to encrypt your files and emails. + + + WordBreak|AlignTop + + + + + spacer17 + + + Vertical + + + Expanding + + + + 20 + 41 + + + + + + txtGpgVersion + + + You have GnuPG version: + + + + + + + page + + + Step One: Communication with GnuPG + + + + unnamed + + + + text_optionsfound + + + Unless you want to try some unusual settings, just click on the "next" button. + + + WordBreak|AlignTop + + + + + textLabel2 + + + KGpg needs to know where your GnuPG configuration file is stored. + + + WordBreak|AlignTop + + + + + spacer2_2 + + + Vertical + + + Expanding + + + + 20 + 60 + + + + + + kURLRequester1 + + + + + textLabel3 + + + <br>Path to your GnuPG options file: + + + WordBreak|AlignVCenter + + + + + pixmapLabel1_2 + + + + 0 + 5 + 0 + 0 + + + + NoFrame + + + Plain + + + image1 + + + false + + + AlignTop + + + + + + + page + + + Step Two: Install a Shredder on your Desktop + + + + unnamed + + + + checkBox1 + + + Install shredder on my desktop + + + false + + + + + pixmapLabel1_3 + + + + 0 + 5 + 0 + 0 + + + + NoFrame + + + Plain + + + image1 + + + false + + + AlignTop + + + + + spacer18 + + + Vertical + + + Expanding + + + + 20 + 16 + + + + + + textLabel2_2 + + + <qt>This will install a shredder icon on your desktop.<br> +The shredder securely deletes files (overwriting them 35 times) dropped on to it. +Remember that if you download a file or open one in an editor, parts of the file may be saved in a temporary location. Shredding will not erase these temporary files. +<br><b>Shredding may not be 100% secure if you use a journaling file system.</b></qt> + + + WordBreak|AlignJustify|AlignTop + + + + + + + page + + + Step Three: Ready to Create your Key Pair + + + + unnamed + + + + checkBox2 + + + Start KGpg automatically at KDE startup. + + + true + + + + + spacer7 + + + Vertical + + + Expanding + + + + 20 + 30 + + + + + + layout2 + + + + unnamed + + + + textLabel1_3 + + + Your default key: + + + + + CBdefault + + + + 7 + 0 + 0 + 0 + + + + + + + + textGenerate + + + KGpg will now launch the key generation dialog to create your own key pair for encryption and decryption. + + + WordBreak|AlignTop + + + + + pixmapLabel1_4 + + + + 0 + 5 + 0 + 0 + + + + NoFrame + + + Plain + + + image1 + + + false + + + AlignTop + + + + + + + + + + 789cedbd5b7322c9b2eff9be3fc5b21d6fdbc6e270bfd8d83c8090900081d005098dcd435cf27e4502093836df7d22d2dda3aad7d2daab57155ddd670e8dd1513f323332c3c3e3ef1e9190fa1ffff5b797bbdbbffdd7fff88ff7add846ea6f2a146f7ffb2fbdcbb2c3fffdfffc5ffff33ffeb3de6cfcadd1a8fdaddea835ffd6f8cfffe33ffed3177f537f63b55e4dd57b151f881b35cbe10370bd56afd87f2586ed7a8ddcaa55c7ab2131ec1f3e3aaeb607f7c48d7ec578be7a0ff64f72cbf51a5d4f58009b4fe0fa4262d85f6f1cc3f93d62b8bea2838cd7e7ed89e178553886e37d6238defb705c5daf9f1237eb15678eabedfa1519dba34ac750ff9118ea675bc7d5f149400cf5ab0b6485f50d1c437d8a18ea0b9a8eabfa588318ea4b53c7d5f68c0137d09edea7e3aa7e7e4d0cfb97605fe70fdea3e36a7f7d4446fbea07c770bd0b62bcde2d31d4eff9c8683fafef188ed7c4d83fcc31d8ff9e18eaf367c4adaafdc91a19ed296f1d57f5cb3931d4cf5b8eabfa44410cf6643bc770fd19319c2fb8762caaf35f0193bd95700ced93c438be068eabfaf923319c9f5f38aeb66f426238ffc6735c9d3f6e12b7abf1af46c8d83fba460ce74ffa8ee1fc1d626cff8563d87e438ce7ff700ced9f11c3f937d78eabed01f66f83c6c32531b6b74b0cf5f3a1e3ea7859b7dc70e3211c3b86fea911437dde01d8d99f1163ff371c43fb1e8871fc371dc3781b12c3f5898e63b83e3c3fd9571d1c43fd541fd9f71b57db559b18ea0f53c755fde93531d8371d3baeb66f2e9171fc68e918ce4ff5a3bd03df31b4ef8318ceefed1c57f5876e7fecdfdc319cff99b8536d0f0a64ec9ff88618cfd722467b068eabfa223abfc2f6ae1d57db8b57e026f607138eabed7c408cc7fb8ee178e8cf3ef5bf2e9149bf22c7e05f9c18ec2767c8686fb5770cf515c468ef9ae36a7bb12486ebd70764b497ee1263bc983b86fe1c13a31ead88b17f2e1c833e60fd4d6cafe711a33fbe3b86fa2f89713c5e3906fb4e88e17c41cf31f8cb1119eda502c7d0ff543ff977420cf54563c7d576362046ff6a3986f3dd23a37d833d31d4c7a78eabfdb32631d457bc10779b553cc4fe6d2ad89e3c01b7c87f2a7b34ebd4bf45cd31c4d38018ec272f90b17fe59018edd3740cc77788f1f82930f597ca1d437bdbc4d85f2362687ff9828cfeace978f2e79163e8ff1a31eac1c231d8db1d8ffdd5770c7a302386fef1a97eca7f3e1d833da87ed2ff7bc7d5f162408ce7ab3b06ff3910637fae1d57dbd52532da33168e217e917d486f9863885f6fc4587feeb8da9ed3f914f84f3e762cabfad01f5ad81f7ed7319cff8318ea676bc7105f0ec4507ff14cdc6f55fd83e76be1f8c872c760bf36315e9f765c5d5f04fed8a77894be13837d825b64ec2fd52246ffe83986f63489a17d251d8ffeaefb8e418f7262ecffba6318af0fc4603fe1f687fa75064ce3a1b82486faf23631dabfe7188eff2406fb6d9e90717c788563183f4b62a8bf0c1d833edc13c3f98a07c7e0af747dd85ff9b563387e460cfdc5a87e1a2f8c18ceaf3a8ee1f83d31ea3fd58fe38345c8687f392146bde93b8678cc89d17edf18ce372786fa43184f462fa17e3123c6783d750cf1644d8cf5af1c83bd96c478fdcc31f887478cfe8cfed722bdfa2086e3f9d131d4df26067ba773c7557d2224ee555cf8c8684fafee18da43edc578927d3aae8e0f6f897bd57685fedb42fd48468eabfd73b2a782fd731c7f6d6c7f2e91db707de93d31e84352e979cbc523bf8f4cf9c38d63e8cf3b628cefefc0349ea4700cfb1f8861ffb840a6f81138aef6f74a62d89f8d1c83debd10837d750f19af7f533a067dc988514fdbc4601fbd40a67c933b06ff1e10c3f162488cfa390576fe1b3b86f8322346ffcd1d833fbc12637b3c64d2933931d6ffe618ecb12646fdeb3a86fea7f3a3bd8a4fc7903f61ffb6d05e7c458cf9d18b63686f498cfe3d770cf66e13e378d93886f1f7818cf64d07c4707c42ed477f0f72c7d5f1e51331f8bbd7750cfe4dd7abfaaaf2b71d308d8768420cf58b2bc7d5f1892286fa23e918b6fbc4307e421c3fed361ccf4b62385e648e617c33e43eee9f1363fd2d62a83f1e236b3c1ff657a70eedcb2f8945b5bd84fe10345ecb1b62cc5f42601a9f719718e707b7c8e86f8a3b067f6e1063fed8750ce3e90e19fd29f789617f3d740cdb3d62d4ef09325e7f4efbe3f5875dc7d0be8418c74f0aece2c79218f31fdf316cef11a3bec68e415f07c8680ff98da1bd8218ae2fd93806fb66c4381e6e89c13ff41819f58b058e617c4b626cffc031e82b5d2fdaaf6c12e3787b24c678b24246fb8a0931eac7d8316c277b517e7beb18cedf27c6f67d10833fc7747e05fecb70ff36fa9bd838063d4a88b1bfbe31e8434a8cfdd523c67836750ce31fafbfddc6f9e71331d42f33c7902fec88517f94e3aa3dc19a18ec59148ec15f9ac4703dfe95e3ea7a9223b1a8b840fb1b3da8eae3778e411fde88e17c89700cf65d11a33e5c3986fa47c4a00f198ee7b686fafd8018ea0fc68e418f0ec4a8476bc755fd1bec8f4e1df60f4262bc1ebcfe0eda2b15c4e80f75c7557d598b18ec93557ade6e907e0475c730fed7c8a40f9f8e617cde0253fc0d1a8e61fc3f11637e7f740cfeb644c6f11e4d8971bef9ec18b6d3f1186fe30bc7305eb6c4d0dfe11019db97bf3b86f9152786fad23e31c6bb2b62b0a77a4426bdcf1cc37cfb8318fb83ae87c6a70476e3f3da318c8f1b62b81eb5710ce32b2186ebcbeac458bf8fdcc6fafb8e41ef8ec4985f848ea1fe0e31c66fb457bb8ffad126c678d2750c7a4cc7e3f8ca5f89e17a23621c1fc19218ecc5fb8e21ffbf2086f645816318efcfc4e0cf29dacf8c17c85f6e1d57f5e91531d4a7b78eabe3839418c7f33d32ea0fa7fa707c05d27175bc4fe76fc3f1f9b363d00beccf0eea09fb745c6d8f1ac4b07f4c8ced4dc17e2e3e67303e855b1f13c4e8cf0a99e6bf9218e30d730cf9c71332e5a33b629cbf3d3b86f1181383bfa83a32e9c39e188e175bc7e04f2fc470bc06ff76f12afa24c6e37b8e217f9912833fc557c4d0ff1bee18f2c38818ec5fb8e3c1bee20619c78bfa20c6fcc747eee3f87a730cedd1c4383e7a8e414f07c4b81ed4770cf35bba3e8c47cc43d658dfc6319c2f25c6fade1c837ee5c4509fffe018fcd9d587f1644b0cfe1b637f77eab8fe3b740cf6b92286f3cbc2318cff27621cff6e7f381f77fb83fd59898c7a54be11e37a4cee18fa9b1343fbb23d31d417be13437bd24764b4afbf745cd5a7fac4b8bea71c57f579f7c4505ff0e418c6e703b184f14df643fb971bc7d5f9363b623c5fc731f863440ce7f3a463689f470ce74bde1cebaafe317017ed9b1d88a1be64470cc7cbbde3eaf87881dc57edcaffabf96ec7c5cfe49618e3d53786789023e3f897dc31c4df39318eff2b6037febbc4e87f1bc710cf5e89315fcd1c83ffdd10633ed9730cf12046c6f199ee9169bc751cc37853c478bf22750cf9dc3d31ce3f9ac09d3aeae19418f58c1163be32710cd72f88313f4d88d15f86c8385e58418ce3b1e718c6df8618f52523463d7c730cf10cdbdf21fdf289a17ebf700cf53f1043fdf29218e3f7c131f8ef1d31f8e366e818fc95ce8ff6d70d62f4970b621c5f4762cca7878eabfa38b597f44d3b86f17d4d0ce321467fe8a2bd378c18c77fe0188e9f11c3f17c8b8cf6e429311c1f158e21de7bc4707c70e1b81a8f29b6af8bf6dc648e417fa83eb427ff700ce79f13437d09d58fedf570bcf4b03d79a53f1d177fa30531d83f0a91b13f18d8ef5b3c481d833f4f8861fcb13132f96b4e8ceb3bb78e213e7262f4d76bc7e0af2532faab77458cf9ec8763c83fddfe982fdc3b067d3e10e37cd343467ff422625c6f5e39ae8e9777c4e89f4bc790bfd3f9d15ffdc431e4b7efc4d09fece8b8daaec17f8d5ee3f9178e219e3d10e3786c3806bd9a10a39e1c1d833fd589e1fcfe9363989fbaf381ff08b44f17fbcf5b39067b6c88b1ff3262a85fbf3886f13023c6f1f8e6b8f25f1fed43feef537bd0ff3db71df5a44d0cf585c271559f66c8687f7f478cf54d1d43fb0b62a84fbf3b86ebdb1343fc8cd07e34be822e311ceffb8e617cae8815c463ec8f1ed9e3c131ec8ffed6ebc3fe9b6a3c779b34deb267648c0759808ce3210b89713cac1cc3fab026c6f9cb1532fabbda1163ff3f3986f5903930f9ab2f1dc3f1afc438dec7c4703e593aaeec57de21637bbc0131cebfbb8e211fe6c4505f76498c7af9ee18f472478cf9dcab63e8df0b64b49fa6fad07edec631e8cd9418ce9fce1c83bf1d8971bd79eb18b63362ecff1e32da37a0e3494f9e1d83bf52fb28de3588b17ddc71d5be02fbbb47e3bf410cdb458b18fc3bc890d17efe9a18e3cbc471757c5827c6f1513a8678f7864cf16b418cf9ae745cedafa87ecc5745d371b5dd7b40c6f6f2bd63185f2131ecafaafb0f5d49fe5c3c11a3ff43ff49d2d7e2c331f8f31d31eaeb0532faab7a26c6f5e317c7102f47c4e82f9163d0b33131d847bd11a31e05c8e88f2a740cfe42f5537cbb750cf1ff1199c6f3b36318cf35623cbee518f4cded0ffe135e3a06ff80fe943d1cffba438cf18911e3f88f1dc3f88f88311f1b3886f8b121467b3c39aefa379a23d37c71468cf3c59663a82f25c6f8d1760cfeea1183ffa53b64f4579e10e37cca6d077fcb57c814df3f88e1f8483b86f147f6407f4d415f649ff24fcf318cb706319cdf6b3aaeb6734dac613c2a646c9ffc2486e3c30331ecafabfee8b978e1bd02d3f8c83f8871fd3c21c6f5b25b64f4ff2c2386fe1775c7e05f8fc4a84f0364f4777ded18f2b98018f38fb663c8b7c6c4505fe1f687fe9074bde8ffe91331ce374ac7d07f2131d677e318f498ae9ff407eb73fede25c6f9fade31f8e39c18fa3b538eabfa32b4770feda7b68ec1fe8fc498df6862a82fed3986781713a3ffa2fd7a684ffde818ecd521c6f1f9e018ce1f12a37f6f1d57e70bdcf1703eb6770c7a8efdd1c3fe0825318ee78018d7730bc7a01f07626cefd031f8fb33318e97b663186f4d601a6ff99563c82739311ccf3f1d43fb707cd0f8e28a18f70f88617c25688f3eda8787c4b07fae1cc3f698188e67d8de3eb66753e9454f52fe5eac90b13f83d831c4837b64f4f78d760cfdb923c67cbeee18f28d1498fcbb281d43fc5a12a3bf788e617ddc31e6cb2fc834bf50c4181fa93ed287b663e8ff07628c0f37c8d8fe3226c678f08d617c8f88b1ff7bc460dff20a99d6f7ee1c837f72621c0f74fde88f45cb31f8cb2731e637978e413fb0fe3e7d7fc131ce1f6f1d837db6c418cf32c750df8018cea752c7103f57c4e05ffe1099f2ed4f625caf6c11e378a3eb437f1723c7e0bf3e31d49f4e90d1bec18c18b64bba1eb40f8f88613b17c002dbe35f12e376e6d8abda5be5affd16f97ff98e8cfd93a7c0e4bff98618f5a6eb18fa77400cc76f1432fa67c21d83bf7788617f45f5d1fde6a36398af3f13633c108e21bf8891293e4d88713decc331b467498cd77be7b8aaafcc81c9bf62498ceb5713c7b07f490cf697587f1fdb1fee1c837fce88717eb2720cf1ad460cfe12bafad01fdf90697ea58931df0889d15e6e7fd4ef6762a89fd1f9d0df920299f2db0531ae87341c43bc708cf38b2931d457a2bd04cdff5f89617f9112c3fe31436e83bf06d5fd8bbe22bdd52d60d2db4d828cf6cc707ff21fef1299e68b3131e62b9fc4a897ca31f4ef35318e2f180faa4f7affee18c6d33d31eaf12731ea51e918fcf7488cf975c731e4036b64f4a7b2ef18eea7d0f194bfbbed587f408cd77f874cf9a0e718c6279d8ffca7e118fcf38218e341e118f4b38d8cf6157362acefd631d8571263fbb563c8cfa6c4e01f39f6b740fbaa8818e34b4a0cf5c55bc7509f63a84fb8fac0dff41b32cd0fae8831bfd83b86fe6911437dded671559f8ffe20047059f99770fa53ee1cc3f58d815dbc4a88d1de2364f2f72bc7d03f7362d83fdb3886faf1fcd4bfeadd31f4df8c18f5ecc631b43746a6fb752131ec9fdc3886f5ba0762b04fd804a6fe4aae1d833ed489b1bd978ea17d3131c637e9b8b26f3845a6f5974bc760cf16311cbfd9220bb4e7b563d87f498cfed4770cf1fc408c7af581eca13d168e21df61c470fee5d671757cd105961de01cea77fa90d790b1bfcb2931daabe518fa6b848cfd5dd68971ff47c7d05eaa1ffd3162c4383f5e3986fe782786f614d0bf6efca97bc7b0bf24c6f1f2824ce32d2246ff7b730cc7bbed78bcdb0ef692d7c8d45f13c760ff3b625c0fb841f670fc4c89d1de0dc7102f9f88e1f800fa57c906da67e418da1312c3f5c56de40e5edfad63589f3c1263fcacf446baf19c6c91d1fe4213e3f8ba0026fb6fa463188f7362d85f8d91d19e791719ed97448e21ded78861ff6ce418daf78a8cf6923b62dcdf6d87fd930760b297f824c6fe491c43ff627bc95e3927c6fc65e818f6ff20f63a95fe617b24b647dd10633e7e410cfb87cfc8347e5f88313f6f11c3fe1ba85f3bfdbb021675d81edd21d3f14d62dc0ee7d7d43ed926c6f669c7104f56c478fea5e36a7b46fb637ba37762f4df9d63e8bf2932f5df9618f3b323319caf7c760cf38b1eb0a2fef31d43fdf7c4b07f3247267f6f38aeb6a7d5f8526df2873842c6fdb33bc7507f8c4ce3fbd671b57db32186ebcf1e91b1bdf903318ea7bd63a83f20c6fe12c0d4def0d531f8df1331ec9f968ea17f26c8d89ea8e618e2c105311c9f978e21de5d23637b9381e36a7b9411e3f5f61c83ffd0f50b1feaa7fd3de44aff9526fbe71d64bcbecd8818ed3940c6f3c50a19ed97a5c4b05d258ec11fbac064bf6c488cfec61d57dbc58118ae376a2193ff8c88b1fd2f8e21be5e2053fc16c438fe7b8ee17ccfc8d89e7c478cf5ef89d17e5b608dedf196c458ffdc31f4c72b31b6a7f277edfc358c91496f268e21df7c04267bc97b64b447e418fbe7dd31d8bf818ce7cbeb8ea1fd4fc8d4fe3931eccfbe31d4f7490ced895f80c91ee507311c9f3c3a86feb82286e3b31e325e6fb12086ede5d0b15f1d9f2063ffca0762f457688f47fe148f90b1fe8d40a6f1b22086f3c977646c7f123a86f33d12637fe6c0d45e1910c3f6a444c6f38b05316c170fc878fd423986eb63c4d0fe708d8cd7275e1c83bf5c037be47fd578f03ad4be68848cfb8b1531f6e727305dbfa839aece1f5f2253ffd41cc3f56d90f1faa33762d8bf908eabfdf33d325e0f7b24c6f30bc750bf06a6f6150d62acbfeeb8da7f53c52bcff5479422e3f5b30532f5bfefb83ade13c8783d2a760cf543fb9cbdc52331d637765ced1f5d2353ffdf3baeb68b25325e4fa81cc3f65764d2a36abeee3bfb474b643cdeff44c6ebcd7360ba1e758d4cd7b3770cfbe3f1743decc131b47f804cfdb5765c6d4f57c03ef9d39d6318cf97c8e44f63c7d5f6b2d207dfa7ebcd17c8b8ddaf23e3f5480f19cfcfc01e3e9d8fdd21e3f1ec1e99ec2b917de0e59633f316ffbb97d6165c7069deec7ff712fde24fef93bf42897ef1a7f7c95fa13cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc5592fbe2acf7a71d68bafcab35e9cf5e2abf2ac1767bdf8aa3cebc52fd40bc535f7b86fde41c5218ffe0a3ef08bf522e6094f79c6735ef0926ff81b7fe75bbee31ffc93eff9e1afe10bbf402f62d3f2231ff021bfe0237ec9aff8d8fceb9adf98d7844ff98cdff2395ffcf9bef007ebc51d5ff27bfec01ff9135ff167fe62ca357fe5355ee70ddee42d639536eff02eeff13ee3dcfb2bf8c4c9f522658c0963830ebf649229a699c77c16b090452c66094b59c67256b0926dd81b7b675bb6631f7cc63ed99e1dfe7cdf38915e287664033664176cc42ed99569ebd8bcafd90d9bb0299bb15b36670b76c796ecbe7a3fb047f6c456ec99bd98633ed89abd72fd67fbc6cfeb05abb1ba694b8335598bb559c7d8a0cb7aaccf626136b25b21d8bd90fff4a584169ef04520421189981d44f2bfaa5e8854642217852885f105f166deef626bacb0131fe253ec7fdbf2afad623e3d88a31888a1b81023335afea418f3537a118a4b71c576bc26c6e29a69712d6ec4444cc54cdc8ab958883bd34ef3164b712f1ec4a378122bf16cca17b116afff60999af1a1ba6888a6a9f74ff18d9fd08bc0fe6565d1115dd1137dd6117dc925338d925249cdeea4675ebe0c64282319cb443099ca4ce6b290a5dc88a37c93ef4643beb38739662b77f2438c4c46f627f8c68fea85fc947b7930b1f35e1e45df7885940339941772242fe5951c8b173697d7f2c658e1526ce4444ee54cde56afb99c9bc8da940b3196777229efe5c377def1221fe59388e5ead7fbc68fea857c9607f922d7f2554c8c3f48e31135599753b1950dd9942dd9961dd9953da6645f713953cc5a41092595b27f4953f9e6a50d05ec46852a628fce3b962a56894ae5ea7f0dbd50a9caf885ec1b9d302f16abdcb4b350a51caa8d7a53eff2466dd58e79463d6636b7501fc607d6ea53e56aaf0ebca10eea685ea51aa8a1ba502375a9aed4585dd3581142dda8895cfdf5f5424dc595e8a899f101a96e4d1be7a68f17ca37decfd49d5aaa7bf5c066ea513da9957a562f6aad5e554dbcabba9ca8866aca217b572d633df8af342f65ff2aaeeaaa9e8b2c0bd5d7fcafaf179ab126bfd72631b051c3f472616ce1a9a396a6f7375a692ddeb4a77d1de850d574a4636d3de35a8c7522263ad599ce75a14bb444a137d5f166c4c8a37e634bb0867ed75bbdfb6beb85fed09f664ef12ca67a2f993ea8a13eaa42cef5400ff5851ee94b7da5c7fa5adfe8899eea999462ab567acfa6fad61c33d70b7d676cb1d4b9f50dde3047de57d62cf4839c8bae7e14185bf4935ee9e7bfae5ec8957e615bb9363a10b0a93ae8b569c7857ed5355e63a9aeeb06f37553b7ec5fba15ef2c54022287ac6969f6ee1adbe52ad73d16e99eb1485f171ef7981961c69ed5ab64a10e3ccc554d585666cefb17d50b4fb3ad69f59bd8e9b9e7591fd76bfdeaf95ee085b26b74e2ca8bbcd84bbc54a766f40c588bdf9bdcfc43e4f6fffcd1cbd4d144d48697abb95e7a85571ab5c9cd9edaf8d6ada9edc1d823f736262a5731c57bf3debdbfa85e783bef434e5860328691f769c2a3b5c3de3b48e91dbd8137f42ebc9177e95dc9116fb00b6fccdfbc6bef46b4bc09db7b536fe6dd7a7311780bfea894c7ec1c5e7779dbc41569e2edb0d20ee31d72e1995cadf28ca577ef3dfc25f5626bbca225762ce63533ce1fd4d17b5403ef5177bd276fa55ebc67efc55b7baf72ead5bcbad7f09a5ecb44c6dfe690ca6b7b1dafcb84d7b3f1c7c493b6b148a1a4d7c771a2d5c0e7268baf54436e7dc683bfa05e5cf9c671d99b898d0c46b7e9c7d278f84c367c93709b044afb9ed7e70fa6ff9b6696f54fea3139a5e7fb7ec0046fd94cc3e8ae5113ded6033fac7ca3d42687f3a36a9c3cf05b3ffeabe9859ff8a99fe9a59feb5cde7afbca1a46f578cd2ff4b55ffa1bff4d264af207ffddff1df589d4dff91f7c6c6308fb309ed1540739afbcc3c45b738627ffd3465736f73a6afa57d20b7fcf3efc036fb1d8e6dbc61225f4a1c7c4d83f7a437fe00ffd0b7f64fc9dfddebef02ff9c2bf32d628784b1746378c8acaba7ef5435bb73af8633b9ff5affd1b7fe24fff3a7ae107fe4c797ac0a652787babf795e62bdef66fd5833ff717fe9d995b487ff9efcc31fd7b335a1eac0af136af9b5c7e68e635f3cae34c8e6e66754f36bafa8ffed31fbf2efa7bf542aefc952faa4c31b7f1cff69b799b7fb1c47f96777aeabf30a37ee2eadfcf07fc3563feab288c67d4aa0ca4acb20d5f6f78d3afd93cd4af7bb77ee38f9e9ffc5ebdd02ffcc2fb50479323346dbf553e51a8a1dff45b7edbef987c226091df3579e20ff489f7eef74c7ceeaadcef9b18c4ab3cc3b35e17f080b13b761f88401acdf84be845a0bc0f1bfb036d4635cc21ac5f0ce422f0d48377e55de97de007010f7fa84fe22034d94653e54164b2d1ae1e805f98f3c8200e12bbae11a44166f4e52fa017416e46c842954161b51ef200fd2ae74129637dcd3ac1c6c4970faff9a37dc2fde0cdc4a8c264a1fbe05d1d4c5eee075b7316c16e829dcdbb820fe39bd19faf17c167b037b6b03330097e61236a70d087e0180c82a199bb9b6c926f7f662d2ab8e08f66f6da0d2239350a3a375987cd4187e693911c0797c1553016977fbe5ef8cbe0da687d8337821be3c9ca5ac5aec4b0693009a6ec5a8e4cee780c663fd537b1c945b75ecfd8233363e5d69ea5cac76f837960d745f7c19dd7f923d7417f9f5e04cbe09e3f586d331940b35a9fb32b0f826d8287e0514cb464bbe0e9a7ef7d7d042ba3cc4339359a713099686935c9c4ef2278960f6c19bc04ebe0f5cfd50bd3df47ef23a80575dde335338f5a540a7f604d93798f65236804cda0e5af7fb66ffcad696b5b175258fde46db6b37ee1ed65ddcc819fd88310667be7cfd58ba01bf44c5eb8145ccdac5f98716cd72a4ba3f17d13361a6686b20dd9cf7faf42ae42c1cdfcd74455336fd7dd2a766fac355818ca50853af4fce0cfd58ba013fa6cc842d165b1b2ebb630972cc52c0ccc45367cce76662e7982be095ec34832cfe45caa613ca361f4f3c1db1bcfa8794f61cc96de344cf8e2cfd30b131bd2303591742207726dfdc2e4156624ab015f85998a449dbdb356d03d4ddff8bb30379ed197239383166a1fdad8bdf67c168565b8915ef816beff897ae1855b31507339115bb9964c1daa9cd38c12c9c31d7bd21d3d0c3f7e3286b8524d833cfc3417c6ac6f187fa866adfa3528f4850cfc7ab80f94ff07cd59ffb55e84075eb2cbf0c8dec241386491b1c5a69a2f0c58125e84a3f09235c32bf979a23e0a3d294ad91733c1f5321cdb3c03149425facdd8e23a58f38f3fe69edaefd00b1ddef02b2f606f622b26c1777a114ec2a9ff18cef8d853a7ea1b7ef0d7e1adecf327c17d93912bbbd663b271e38bb9df0ee7ec315c84773cfc73f4225c8a8cdf87f75a8831ebb3296f860fe1a3f58bf0295c85cf5a9979c8d3e9fa88d5bc5bd1957d16872f269e1ce08ea3dec8b93c86fb701dbe86b5b0fe47cc59ffb55e840d5ef07b39626fc1468cf96be51743bb16257661331061cbef898bd3f59189acedb0636253cc267a21a7bc65f219630d6f1f76c5518ec35ed8577dffcfd28b3ce2462f0231161b7b4fc446391bf7e524629150e3601fc9489dae8f221d79b2af85ee8969e51976197563236bf018f962a1dfa2e08ff80ee0bfd68bf010be47dc0ba48c4231d67b7da8ee08dbdc33d713194491f7e4d5bdf6a9fac8bf14a988a2d8e8e754ccf4adb6a3c4ae970c4dcedf8f9228b5a3c46b9c7ecefafbf20bf6e1d97be6d7ea43adcc9ca4acfcc2f7fac120caa23c98861f5171ba3e92aba88c36aac3a6622a27aa59ad9457f9a7c9cf3bd15bf41e6dbddb70f9ebf5c2cc473ad14e05d147b0893ec556e5726e66ecbe9d417aabe02ada87a118847761e3547d64e6a2417450b3e8c8e268a0f2685865199e5a98f239ba8846d16574e5bd7bad5fad17763e128d795ba7625c7d8f6254f9ac5d5b288365388aaea31b2f8c265c9fae8ffc6954841dd98fa67a61e4e380d6f754c1a6d1ccf8e26d34f7ee4f3d67fd3df3111e7963b63357b6883ee5abc9c56bd57d91425d18f5bc8b96d17df4103d464fa7eb23334a56416e6349f4cc223955acf20ce38bc1adf71cbdc86db4e66f62f4abf5c296d12bdb9a39eaa3d88889ec2b06f746d450cb70a7e2a86674a31e04271dbf2a6a181f689afc732a474154dd8380396b4f34a256d48e3a3c3ded6f0e7edf7aa7bfe4377c1d75c5c478469f7d5473b3eabea75a463de9b3dba81ff353f651cca2227a8885e88a99c9759be118d6de8d7f746219ab58c94eac456cb4e597ea0517b1c787c61f56ea514a36d5521d2bbf28958cfd3888f2e8c2e41893489fae8fd8210e7919b4d994bd19c38441e4569cbb7e1147711c2771eaef4dfef94bf5c2ae2bc4197f14db7018e76c6ac6efb19aab966a10175ecb8c1211977c1a6f4e397ec343fc16711b4b449745c18d92d59dec859c9b7c7717bfc75b3d1211f77fb55e189fdd8942aec3a15a997cb0ab34dc1fb1df528c3fa25afce9b7d865bc3f65bc1789efcb83b2dfa59de985ceaadcdfc412fd1a1f54188ee263388b07def47473d6df7b7f241e8a22be307ad1658114463d8fd5f81de8576f188fe24b19195b5cfdf8fd91af4a1ec5e3f85aaea3671359cd28d1f736aa0687f8866de2493c0d2ffcdbf844eb26bf5f2f4c997a3bdeb17ea1562ca439825d7352793855717ccb0a638df9a9fa08756a61329bb5cd3ffd51b5fe696668c141093d8fefe453bc54cb60ecef7fad5e54b16415f85a445db512535d547d84be6174dd7e4762a3f7e6ca4e184b96dbf8217e541d3f1733336785bb11ca7e932928e2a77812eee3a7300902fffed7ea85e9a3157f348a1eb0be9e2b7b7fd987fbaa66fc3e87aff18b7a3733fad929638979eb782dba9289a9c9b8982eaa8cf7559572cefaea3d7e8d6bf22e788aebbf562f4c1f35e266a56413b19323d34725e482de3efc8c5b6c11b7d58e4fc2f64973c188f1b81334d89b5d838fedcab8303d50adc1c73df119f7d5929761fd17eb85884326f8059b86437663625c64ae6858cd980ac5121ebeb279c2c241224ef97d4c9124325111573393d508e3195dfbeda56aeda4c6bc709768fd98789e3acd9cf5dff9be56e227017f0e877a6fb4ac5fdd512daa3527cd7ae16b1226913c26b1bf3e652ee8b5d86792246992f17bf6ae6bf6bb8366741e9514d3f8235ecab7601ade05dd5fab17a65cb00bd6d442ada4d499c98a8d2d92bc9abd2f922229fd48ed924df276ca5c50aebcb6de46abe49d5d2ae57ddabb9770675b1ffc22d9da5822ae921ddfff4abdb065f261f4f32dcec5442fe07b18c6167665b666b29fe7e45376d84b248dae9f3096b003f7a3327e8b77fca2b2856f7c439b738fa24fd54d741824fbe4c0f6bf522f6c991c03fbfb80390b4c2ed8ad626af51d7fafcfded47d3248862ce593e4e2a4b184d9df1805dd64945cdad5f7ea9c6656985cb1281927d7c94d3249a6fce3d7ea855d574866bc99dc9a1cc3c69286cd2f608dcb0b646cd4736ee62517b13e692c811cd48fd7d1d88c0f81bfd058787d39631dd3030b3d5259f094dcfd52bd30a5cad856ca64c962336f351960f58d91d2aef725f7c943f21806629c3c25ab53f90495269e3c272f2686acd1177d394fd62c88e6d185ffcc8fbcb4a3e457ea85b9a65793e835e4c0f8c524a92959cda41726d7f0d934a9278d60a7ae92a6373ba54fd8927f26ada46defe27a9f26e73df2073d50cc1f99cc731a4c8c8e65bf5a2fb84c3ad12ea8991c23606f72a4ecfd01f85eea504bf5907423113cb356d2e327bc5f5295f677de1fbc9df4ed77113c6e660185dab3d0bb8a07294f59fa8bf30b5b9a18d1f7188b5329d7a932d77581df4c35b93153c975344ab54ca37aea9d562f184f7dd64a83d064e466fede4c43330f6062a25e8c25a2e0cdcc577f6d7e5195c127bfe035b9568fd633aa5fd0e1f73de5288da3f7f8dd2fd244afa2d529f5c27bf0ea69ca2e25531d955b6be84cf03463dd340fde12c517fffcf8b4f87ddf0bfd81dfa786f25214c62f06c9ad98aabd19251ad6a8655df6c27d5ac6526cd2cd6972c16f65fa96b4bd0ffea00ee9bb99013455ce9fa4892d69926ed3dd3f3f2edea71ffcd67fd25bfd745abdb0a5ff2e0ac1a3a9d50cb5c75cdccce0bdbd19379f514b46e99e4ff9fca47a61caf42d3db0862882a62878d3cc8d2ef8557af426fae3bf3b2e50a2ed5f05a13c18ab0dc25a30fe67fbffc8ef53d3a1b7f34a2de2dcccde79354a8a606be7f0baabc3f4221de9cbf45265a7be7f61fa789d5e05bd74ccafd3ebf4269da4d37ff57d4f5932c637e220bd74c65afc32bd4de7f1e0547a51fd6660c9b63a65815cf39a1925baf20bdf0fe5ad18a78be025bd13fd74e94d4f1c4b8c33f250a5e97dfa9074ecb70efebbfdfda95ca58f622006e9135ba6abf4d968dc95e9ab17b6f69a27d20b53faefe99a7792db689abeea5cd6291754c3f03ebe8b5ed29aba33b1a4fec77e7ffbabd2df06af69236da62dd6f27b619eb6595fefd38eba968d284cbbf226eda5fdafd7657ff4f91719b7ab5cf677aac61635faee8c7ecd98373433e9a7682e367cf6f3b9e0ef2bfda9fef09ae954a5e22aaadba736b1167bd3f334131bfbab7ad661a9fa102c13a291c94464eaabb9f48f3eff2218f0cbc0b7f73bed0a8b9c1bbdb0cf2e18282966c975a6e309db649e88bcd3f77df4ddef483c95faeb74c8b77c138ca34334c97c79543b566481b88ebaa29f85c61f16e140beb2aeec86ad2cf25a59ccd65fadcbfef8f372b2843f5abf10f6ded101be6166ef1ee94330cdd26091652c8964224feb03f6bbc17143c47ce1fbc6026596b375f0c66759a1debd67568877d6119efda52cebb28d0aa375d4914769a27c56ca38db646fd97bb6e5b3a4732abdb065b6131d638b9d5e845d5dd01d3e13530ee1841f62957dc894cf4efdac023fc93eb37d76d02f59ae3f592bfc107e1606d3b8f44bc9cdb8d81b7fcc58a176b2971db3413664457414e3a0343d74e16fb351f6c66530ce2e4fa7175c24929951a2562c66539557bfbf5e5719e880bd6757f16bb295463ff5ea74eb9f46a3de8c161cc39610aac75239328a35c9c6d975facc3626078ded8a9b7d9a4276a3ae3c9d4dd8329b9af17293bcfbad7893cd3299dd66f36c1ba46c7d3abdb0a589dc8f62ab85c94117ace9f5ed77daecf732b4cc16d99d0cb3a5c990b7223e8d4f64f7ec837d640fd98d388a7df4e617a22bdeb3c7ec497c66abec99bdb150ccb21739cdd669e63da5ba7a6ed122dc997e5964affa39adc92b759fd5c2d0a8e7176be73ff37c2dfdc12e8d970ee5404e7457b1ca16d53c8d0559234bd96df49035b3160f7fd627b2b637661f812fd77221d76ce33d074353e6493778898368ce6e5860ecd2510fac2fa63a356377927593c7ea776a5759cf7e4724bb138de486ddca1be31763fe16ffc37ce9e79eaf65474934b5ebe27a597d2bb5c05f03edb37ece73263e72914b91fe58fdfc909b6958cac4304db266e0e71e8bed73fd729f45ea495de5411e26c37066d4729a477a9ac77992a7ec263ab2a9cfbd309bcb0f36cfb33ccf0bf69097516246c955f696186b647b7e3c9d5e54e5d1cc59c7f6ae228b3ccf7e2bc07e2f237c5003d197ed789a6fd4155beb7feffbdb51f09ad582d72037739a49b48bc6e6d5cfdf846f4662ac17da7881f18fbef18b9ec91bfae1d058e29db5439e6f85cc77d94acc8c8e8ccc8c7e937f84b36017e5629d7fe6fb709a1fb2c2fa457e145789f7f7b1e4679fc7975ef3719ce7037d5bfdfa0a9e5f51e8d77c987ee6172aca47f2985ffeab6722e557ace635f5b3fe48ef3c959bd6e7d76992dfc49d7c1276f269f8c49f45379f19dfdfca753ee32bf96af2875027d1c2f4c456f4f35b71cce7f922fe64572c94d3e05dcda341769346d936f9941ebb8feed35ab60d43e31317f95dbe1457c6da27d30b5b8a32f02bcf9849669f53602d617d43d6f2fb4ce70ff963fec4d66af2dfd593af1295f8f973fe925773f02c9199b1c06bd811be7df11793c3aec2017bb34f6312e37060b2c9441ec5c4448dea3ba026abd804717c97d7fc9ac926a672c8db6a6e9f07277b5127590811e5793d6f842b93776eb222dbca386fe6ad53ea852d8366de36b6e81aaf151ad632ecaf07e7a6af3af128ef861f26187efcb3e3d3bb781f9b38195cf9f5bc97f70b6eac20c2a724133e7bb17e60daf32a8f4c99599f7d36d1ab6f06bfb186f10ffe04f7e00b51adbf9ae6d9a751c8a9dfb72b80418d8dd42c9c78abe44625858cd24266af69cde49e8dfcae50e2caff287ef36cc89f7f7ea77d42a3c9f8dfec2a97aed6c44d9ee11b7b5c169e49c27d716566d6ffe4f8e0b3f0f925bf2c82500b5984451476c24e1117317f0907ca8c0936156396164930550fe2dad8c07885697fd76e531dd591ccc4b0a557d8df489ab9c0d0cc9af75aaa5ccd83b6c97a98518e9eec442f429908aba29722358adad14ac64556e445714abd586e4d2a5588b1bad5c69975d76f7a7bfd5aad8d1f8a52c5721cafbefa1d3a3f149be22d34f98294a9643d6f54bc67a1d1c75731f6e6a25b54bac062b163bd6297446c910c0bfb4d5bb3bdf814dde828fbc59ebd1b5fcc74666cd0b29ea0e65254bf1bad15073ee6e3a01d3458578f8aa358fb75f610df4749d80acb342e06b297f87c66e65527d30b2ef4b3f721cd7fd1d4aa7731d40f955f784af3553e2f2e8ad1dffd86609e08fe164df834dab10f33b2247b335a681f6337ad7edd37f3cd88f373eb13561d583798466fec5e88b46bf2acaefddcf8c3a2b8544dfbcc8ce2ca8e08deb69630be305773e32373cb811fb4655f6ca4999be63bf6205e6410f7b34dc8e341312eae8b1b7e2c26a7d40b2ec24b51481e4d53a917aa69b2f1029eb717bce749f2c9736f16a4e943de2ca641ee758d67ced2840d8adb2433a3e15394516cbc7e6bfb9aaf8b395f47b1b1c04bd5f7462ff43c0b4da6228b455c9aed7bb9500dfbbb775d54bf7136afe2ce7a82ca8b43b10c6a86efe173af17d48a87d0b4dbc612e317cbf833d819bdb8281e8ba7c80b3c3ef39353ea855d87d4f75aa84733e407d23e876d80bf8ada17ab64a0d2ecb3782e5e8a359ff0abe2954f8a5bb5117e712bbae180bf70932b44dcfcdf6a43d7fa04bdd0374626b32e4523bd63899ab37768a78959f6392acda266adc06bf6778bd63ef0f9b7377b37f3a576e415c7a25e348448164593dd1637b257b48a76bc4a3efce5e9f4c2c602d50efd7090dcca75d8557b630d4f154547e77e116e8aaeb88d3b45afe89bfeee16ccb4d2c486f8c28c8717ab0b6a567ccab5e57c66b4c0f847f1c962cba69c060d5ef30ac98c8f30db56ab0b952dea660cb4ed6f1579650dfafcefcbe2a07bf6d991c15dc94b568ab4f45aa5940dfb5363e31f617aeb2f4fa717b6f4a6ac61347e2607da6ad7c1e618a5a7f626077f60f7a5efe7c6f3b98918a6f78d30ace125365e284ad135bef1626303f882b1d1d4fa83bd638bfd9ddbf10ffd5c3d15624e9fdb7719fcbd2f7cff56f332346ad42ba32c92db6814beaab1ff9c8cb322ea94713ce033bd0a5e4fa71726c7c8d820f0c5ce64c333737d2d98a1c93a5f650df610eebd90bfb269999879422ec665ea853215d73626f06735031fb07e62c6365333fe24fb65a672afac9e57e7fa38b8d15dbdfce60bc55da597b57fe613b6b4f751c24f79d461368b8392279fe1c81f178fd1accc937a5994259f6497a7d30b5b961b7e617a7aaa1776cd4f0fac5e787db52fdff23dbb0f57f91b9b46dcc4ccb5897117e57bfa59da2caa8a156a063ac1d7fecac495be642646ccedaffbc10f6c5ca8fed5ace284f112d5fcef7ce1b76f7b44682268b9339175517e843dd18893f2b3dc878b6c531e82b7f2783abdb0a57f643b332e27c1bb5778056fda672f9a3c43a8a7a86df47b1994aafa6d217f2e07c95eb6c59a1f4c62b1e6cf720d7a21fb3e0fda71d7f6a49adb1851985e8fbbbc66e6c0b9f109c3ffbd0ffc636946ab7da65b6632b3bc78cc86e5305f941776be1ab1729445ecb6bc1457f195fe389d5e9846ee59437db248cecccc88057665dcae7d4a31f38ee55598b1ae9c588f571d934f5e45b7e5583e99c86ffda22f1756196cde68236250437f689ade27bd687e8b1dffcedb3e05d11e69f2cf24f0c2918d25850c479111a3729fbdc5836c5b5e8bc07b3f955e8894bf659ec931849cea83b86663d38a07253d930347f60932d74998d4a5b4e3bcd8abcfa021efe2d7686e73479f9bf68a2a43c2f10da5f18966796375c158e8e6dff185af4a334bdba65db9938f762d23f90c581665b7f1249679a047490cf39213e845e4d5eddf93086a721e44f6bbdaecc6f6a8caabbcd14c58e25b21c583776532cbd8e41033336f49ed7382adf7436bab279a567d693d03fcc2daa3f2961ff0877ff08f9a5cfb66769a9a70221ebd65d82b27ea3e6a97533367ddf0325de6ab53e84539e337de22f78aa5d29e1fdc88999ef3959943e676e41b1f387a2f7eddbc5a62cbe2b06b7327bdc87d6b093952bc8a8dede0a6bcd57d392ce7dff769512bee7ed627aa31320abbac9b2fa3cb7221fda21ebdc4b18ae475560413fd9cdca42647fa69bd884c36dd886fbc90a5a91911665c76594fcc20e69979639faf4c3edd2eefb416fd2a6760a001c6378c25740f4ac34373cdf2effbd3aae56f3ffb7bfeddef9a3c964b318adee5385cb3c770941fcbfbf2a18ccbc7b0553ea56f22f939bd88eaacc1af649ef272553e173bbd8c0692d93e37f9f324f74dcb5f8d17dce9bc7cd1b9d50b6b8bd2c4def4552fcc1c32b6bf4d0ebbf6f9387216dcda674afdac0f506914eb7b5eca7516da15bff2953d94b53830aa590f67d9451e46b390ab76f0fa337a91bef1b128f88af58b5dbe15fb60649fef22fb760e61628a7d9e239323d3f339bd6c366d3fb3f73574cfbed04732c8217e345efc9eb764d94df098bd85bd28577169e6ae21f7c7e12e9ac532134cf0f4c7f522c822630936321a190a5edecbb72c947d3de4359b7bea5b39b1bf7650dce48f85f109aeedb35f16e5dae4624bf3790394937c05d8c49393f8c457a59a8b9dec857d19aa58ec552cc3ecc244d67a364b8c7f944db6fd51bd2874540feed5dcb6a3ca8c5726a7b67dcecad0e60c36e560a1f103dbef0bd0046b0da322a00f23fbaa4aa63eede7f665d729ff20bf68d8a7dcb05e704c74d663f7f93e2fb359d90a795ecbef8241d9e60f3fa6174156e4ac61e6805ddbab55dfda672197dccc1dcb4e69fcc1e75637ec73c079cde8c1127cc0ec63ac63d79eecf3d22ddb97d115a3a0ec5d35aaf947f7b43e61b270fb9cd4a6ee869facebb7ed4a70d9630fb21d25f1d6cc4bfae2184c373c653fa6171bc66cfb1776ee0071c1ae35caa16a1657769d1163c5d08e0e9dc9a9f509f485a95d91b3eb92faa00f76ae41fe01b1a55aa13b993ff0a692e6ffc0a687582fe5c94df0e27f86eb8d907a234d16bedba88d0e54b0fe31bd88f71bcfc60a33bf7882f9826a1557b6d530ee759686ba6f9faba71ad61ae65f1cf28934b49680f549fb4ac3ef7463748a1cd3e9c3c16670ac89197d4b777d2ec669e4b7e360e3b36594a665f6963564275f6e82f02e18ff985e44c5260cda66fc33fbec12c81bac25aa676f7635ac4a2fdd7a53f57c78fbb9c9a56c4635adfe9e807df59d0f55fb59bda8328d9ff207fb8cd1a4cf5bf6b9febcf9ed73735533b62906f25a8ec51dbb8f6a9b68136f12d98de79b345eff985e6cb28d6983fd4d713e33737153faf619218d2a3af6ad0f98fc62910fab35a991f18dbe190f7b986f58dfa96c437dd8fd3ea6588bfcb06fb4e1ef13f84d5b1ab5fc6ebbb5859d978493609ad6e24b76c7eefccf2851efd1dc6ffbadf08edffea05e14d1cefefd11fb137c88055643ab7b9cd59ad4a6041da9f421b716b25986f9b7c9b2abb79b7354d738ffe61b95ba0e7f349e386df8f26df360318e1e92fd66235ed872f3968e64bc79f7565147afc2bb1fcd2fbce326e497c6efeffc91c92466e423fcc9feb2f65bde60f30d8c21539597b74647bef56546ba6163c837dff87e2debe7630858c872d991cce418c7b80c5b512a7df6b8d9a671380bfbb14cde37bb1fcd2ffce5e6835f1a65b65a31a956a3faa6b4792633f1a57a1b6bf4edca047b37e3a4696306c410d74fc653e8dfdfeb86559653c410a319bff193a066fb271cb0d4d3f23afe4cbaea3ee49bcfb0a5eeb3fbecf0a3f39174987c6cbc2a8f9898f1bfb4b96458e515463f9ee5c49461a51f4b7b6fcb96b6cf297f9033aba3c647ecec03742427dff85a2fec9cecbbf588a6899687df93577cffb9d7b3b921b38b16d32c0aaef2451266c3ecb6bcdceccdd47df7e3f391609ca641bbca9f73f301b36b13d5bdddbecd2321c7c4bcb39a6f58cdb051d3a846d5ef102fecdc544b7b0fb48a34d53e763df35fc612fb57269bffbebf80666c0ed9562cf24fb6f496e1be48a3c4ebf0ec27d62f16f95a141bbb36958ba99d67d85c53df99b190c19cf45bde60ac6295d3ae5740ee39f530aa0637f66e30f806c414f01d5e3f65eef99bb5f4257f162c5fa6173696b0655e4f8671bfdc96c79f59bf48bc34f5169bb28a9c53881830b3a05cd2fa03fcfb7b3da83e2fec28b13e023ee17243339a4ea317ffc42f6c54efb39eff6c32ae8190e9caff4c1e12bdd96d863fb37ee13fb0dde6828f79ddf874ef7b5f30b3f2d0ce53aa7be0a3ef7d044ac8bb14b73e82eb9c7b39b36565b746355ff903e6aa501a5d3bea511cdbbfd82964be90c166e4b39fd10b5386c59c5f7b0bab0b2c345af9f97ddfdbd9da373ff8f66f7c4f21dfa2feda5cca99bd97f1dd31dd6ffd19d4eceb04b1a58a2b26b28e65637365e6abcb72cceeb25e3edf8c373fbbde79dc5c17f7c543d5d7d96ffbfebbd2f6f16f724be30f01f842a51b764cd42b5d1bfdd6774e3b57adfe55379abde4abcd4da13693b257fd65b97d36f199bcfcc9f5cefe2614051f9b31dedb94b60ddfd626be9f7f7e7fff5361ebed3a163c0bdcbeed9ca59ac37eb7ffcffa81999d5539869d9f7c3727999b286f63c954dd8b7b3b4aa26b334ac641f0b3f7473633d6c8bdef7d016285d18b11b1bd2f6ab5b59cdb593c6cb7afcdadf97464e7aed067660e6b676db9f9dc2ae8cfdc0fb199e6c16f9ac8dbfec73ca338d8fb25f27233978ff077e536bed7e0db9fbd3f12f4f845d086fb9cdf7cc27e830ad7aae6f03daa6a3d139e3b5fab3233d00c3bcbcf5137fa9565a6b03eeae62cff4e4cf99df986cd3ff9cade2f918f3696d851c2d3cde267ef8f6497de4e1426e712f609e7dfad43bc5731645aad61fd9d7ed84c5dc1f72aa6dfdd0fa9d63b8c8f64d5dfc4e3952f0dbdf277fb42957bfd1edf09cc4835f3a7eee66eb38458e2d7e57391fdfcfdd4609504de82e205e411b61df46f9a63d83b472eef703e0499951c1657555ce997b7d55f4bcced3a58e51d27f70b1b8f4cbc5a047c73bf79c877f8f7063f368f3f7f3f35f4836b3e2e3b763e6134e0498e82fab73ca36a6f43f6edca1fcc4fe0f3dfea8b8dcae56d392f6fabb1c5e10e926a9c3ebfa0fbb666cebadeac8ac7e8c5af577f9773e4bdfffcfd546fb2f9b03946d5df3d93552c6cfb3daffa356dcde65cd5dc15d733a8cf695dfcef728e65b5efb71cc3f5e5f7b9c869f24f937d76232f6fe48b6a5d6717cf4ef0fd8b78f3cc76fc863f9a11fb18a67ac01b7aa0dac05486a92dfff1f32ff66b1a2f7ea8f8411dd9ce63bc65ffaabd2d894f51f2667af0eac9fbe6dd9f469af1b47eaaef5ffcffa1fccffff7fffc8fff0f4b7fcac3 + + + 789cedbd59732339b2eff97e3e45dbc1dbb1315c52a4b8d8d83c68a5b84994445112c7e6014bec3b1791e2b5f9ee0384bb23b3faa8bbab32d95975e7b264acc89f18810838dcffee4090a1fff15f7f7b9b4dfff65fffe33fd61bb189d4df5428567ffb2fbdcdb2cffffbfff9bffee77ffc67b375f6b7b3b3c6df9a67ddf6dfcefef3fff88ffff4c5dfd4df58a3d750cd5ecd9fc4670dcbe11970b3d1acd96f10c3fbfa1db9dda88f570762d83f6c39aedf0fe6c467fd9a2f907bb07f32b2dc6cd0f5841b60f31bb8be9018f6d7a56338bf2286eb2b17c8787dde8e188e57b963385e13c3f1ded6717dbd7e4adc6ad69c11b76bd64b64ec8f2a1c43fb7b62689f6d1dd7ed2717c4d0be2256d8dea763684f10437b41d771dd1e6b11437be9d871fd7e86ed9da13dbd0fc775fbfc8e18f62f7b353b7ff09e1dd7fbeb4f64b4af7e720cd73b25c6ebfd2006fb791e32dacfeb3b86e325318e0f730cd7372486ebd58fc4d0be3f712c6a7b64c8685f39725c9f4f8e89e17cbcedb86e5fe4c4605ff6e1b87e3fe4c4d8bfd4717dfec09defbc8ec704dba7f150dc31f49f1163fc1d1cd7e7e37362b81e7ee518de3f2786eba9bac478fed8717d7dea1219c74f3788e1fce9ce31b44fed617cb06bc7f0fe9018cebfda3a86f1a0feb6e1fc2bb77fa7bebe402353bcb488b1bf3d62689f5f3aaedb93b55e9db97809678eebf6bc0631b4e7ed81c9feb24f8cfe70e618faf74c8cfdbf2286eb0953c7f5f5887362b0bf7c4346fbaa9d6368bf458cedb71d839e3a86f329b73f9c6f45d7db86f3a57dc760ff1e31d87b758b8cf1a69963b89e0e315c4f103806fda1ebc7f1f0368eebf38509315c4ff9e218aed7b587d7d3740cf15322e3f85553623c3fd917e34ff88eebe3a301319c3f2b88e17ce53d700bc78f49c7f5f1fc8218ed79edb87ebf84ebef937fe80299f42f760cfec789c19e72888cf6571f8ea1bd9c18ed7fe618f4f08218f3d31e19eda5bbc4986f268e617c07c4707cf0460cfd5d5d1383bd62b07fbf85fdf53431faebc631b47f438cf17aeb18ec3b2286f385d231f8cf1d32da4b798e61fca93dd2972131b4173d39aedf6797c438fe5bc7e06f3de26eab3e7f1319ed1d1c88a17d3e765c1f9f53ffd19ff33bc7e02f136268bfa2f7d1be6904dc26ffaae3a7d5a4f12f1f1c433c3062b0afbc40c6f1970762b45fd3311cdf20c6e3ef80693c55e618fadf27c6f1bc26067b54cfc8e8ef9a8e277fbf740cfed12046fdb8770ce3bf2686f6f357c7f5fb71428cfa312306fbfa747d546f6d1d837d26c4d89f27c7a0df0762387fcc1c83bf2d89d19fa68e21bf5e21a37de3dc311c9f12a3be7c3a067fdc1043fbc5d271fd7ef1410cfd5d1d1ccbfa7d4ddcabdf4f6f80db385e7ed771dd5ef24c0ce7634bc7905f77c470be724cdc57f5f8dd22e3786413c760cf36311c9f0f88e1faaa3a7e5b4eaf74df31f813d8cbe94b191363bdb144467ff372c770fc8c18eb23e118f2d18818f3d51531da234226ff61c4988fdb8e217ea97df48f78ee18f488ae1ffb2707c4188f5dc790cfdcfe387e9c18fd6fe718e2078f6fa3bdc49818f3ddc431e8f13b31b6bf705cbf9f85c4680fe118f44f12c3f86637c430be31bd4ff17d490cedf18363389f470cfe2c02e27ebbf6ef6764b4afd7740cfda1fea1de662f8eebf6c257e25ecd0afdab8df1949c398678da12437f0af48f73ea3ff6f7fc1cdacb2262b8dea8d6b77693eab7f49918ec1d3c20933f9d39aedbf77ac4a8171531f63f43467fe14d62d4cfc031c4a3db1ff5e51a98f2afdf2386f7f58763f0ef4b64aa2f3bc4a84f1e31eac5c6716d1f4ded637f5789e3faf82a24c6f3a3fd283e04730cf1312586fdc508d8f97be218f4d9bd0ff629c68ea1ff3931fae7d271fdbe56c8a42f53623cdfda31e8e78218ce273a8ea1bd67621c8fc831d89b11833d195d3fda8b53fb549fbc3986787b2046fb148e61bcbac4d07efa480cfe1edd2153fe3a2386e3934f62ac9fae1cd7e31dd0f9307e3c3a9f82f8c8c8de4ad41c0f8129bea23931b42f6e1cd7ed273b62683f79715cbf1f65c470bee4e0b8ce5f11473e87f678490ced89d431e807faf7791ff7cf89e1fd74450ce78b717ccf3570f804dc3987fe16cc717d3d29d84b50fcfb7d645a5f181363be3a3886f7b7c0546f4b418cfb4bc7504f5d23a3bf7a3e31ecef158e217fdd10833fc917c7e01f6b64f42771818cfea1211e05c563de45c6f8919f8e213e3831ae674c1dc3fbb7c8a8272c740cfd97c438df183a06ff5f10437fd41c19ed2d687fb4b7b8750cef7bc4988f3f1c43fc3688d11ed89f731c0f513a06fba6c4584f0d1d43bcdd1263bc7e10833f277d628ca70df239ea419b18c72f710cf9f79918da0f946388e70631e643c7989f2f1dd7d7e3d3f5a2bf276fc4b2e612fdcbc453dd1e9f3986f85a11637c6f1d437e3e23c6f8168eebf387f7c470fe32725cbf9fed91359ccf0f88e17cc1d031e8cd2b319ecf735cb7b7720ce75b69e04e138e0f2262d4831d32da333d10c3fbeccc71dd7ebe2506fb55753e383f233da8ae1d433cde0253fc27b963a87f1f91295ff588617fd5700cf9b9498cf9f90119e32b1f3986f8bc20c6f9f1d031f8fb1899ea959e63d07f9f188eafbe31e43fbc7ecacfd92d31fa53df318cdf3531dadb43c6fe472fc438ffbb2486e3334d8cf900fb4bfa92bf3b06fb2e88f1fadf8831bfb61d433dfa844cf3c38963184f6a0ff367dc755cfb0753c04e5f068ec13e5d62d4bbd2318c47807c8ec7f71c837fec89b1fe74fb63bef68851ef56c87dd4b70e31ce277a8e41df3262acbf77c4584fe37852bc06cfc4604fc61dc3fce192188fa7ebc1f84c136288a70c8f37f10af5cad431d4af0b62684faf1dd7f62f57c4d07e903986f845ffed603dc1a97d8cf7403a06fd1c12c3f1c58618aeb76821a37dd8de71bd7f2c8861ff244246bdcaeb7c732e285e831631faeb1c19fd2fbc26c6f807ff14543f071d62ac9f5f1c433c5c10837f44b43fea4934710cf5c98c18f62f7a8e61fc3932ea49b623067ba45dc7757f031f19afdfff20c6fa6d4e0cfbeb1898e2271a12c3f161450ce7cb578eebe3c51d32c68fda10a3fd34721fe3ad720cf1e21163bcf41d831e6f89d13e43c7103f2fc4d03f86fd3fd7d8deca319c2f23c6f59a37c7609f2931e643f05793cff07eceb563e8af63684f668ee1fa56c4e8bfd8ff0eea4945fba39eb0c2717d7c9c1243bc867b62ccef0932d60ffecc31e86d9718ceef49c7b0bef5480ced05afc4a817b1635d5f1fdaab837a54a58eebf3ad36c478be8e63f0979018f4c313c470be30765c9f2fb92756e775fbe86f5dd4a3ec9518eb919d63a8179f88a13df9410cedc54de4beaadfcfea7cd171f938cf8029de8ba963c85797c818dfe98563a8bf27c430beea1999e6ab1bc790ef5f89513f768e613c97c8a44f3bc750afaf89d19fde1d833f05c0940f459718e32b24c6f5ad27c7f5f1559b18ebbbc231e48735318c878e90319e53bc1e179f5dc7109f9a18eb7f9f18f3530bb8d3c4fa6b448cf614c4b85efe440cd7cb2bc7503f7f1283bf78387e149fac24c6f83e770cf3ef6b62cccf3931b4cf0b62b087df41267de3c478bd8563689ffa8bf1bd9a12437fe49563888705319c2f5a3b86fadded0ff196a3ff74d0fefa8c18e7b397c418ef1b6238ff8aeca7717eaf88a17d6fe0b88eaf780cdcc5f1481831ea4f488cc74f1cd7c7733c7f97ec9b12637f2f1dd7ef577d62682f5e3baedb0b6e88410fd20632da77e53b86fedd13c3f9f88763b81ef73eb4973491c91e77c03decaf067bb8f979ca1c437e71efc378c457c818ef9213e37c76e618e205fae7f279ec3b867a66458cfefdea18f2df8018e7c3ee7888c772490cf61260ef6ff9b0e318f42320c67cf68c8cf1935f3b86fa76428cfe72e318f42627c6f82a9131be3cda1fe34b6c1d43be7a25c6f9f61d31b45fb489b17d0f19e3c50b89b19e881dd7edc92931e6e737c7506f3c10e37add9818ce172e1d83bf48e02eda37578e213f3c12c3f9e4d2318c678f18f3f32731fa73e618eaeb1531f8efeac9711d3f4223e3f8792f8ea1ff0531c6937b1fd707df1d43ffde8871fda4725c9fcf5f23e3f8f82362ac27568e21feaf8851ef3e1cd7ed853e31c4ab42ffede278f85b626c7fec18fcaf4b8cf6891dd7ed6bba1eac5ffcbde3fafd08f289203d080531ead5c431f4df2746bd8a8935e80dfa638ff4aee3b83e3ec5f1eaf561ffbcf6cf6ecbad472f8931ff6c80297ed91019f39f8c89511f0262ac77ef9031de644a8cfaf14e8ceb6b23c7107fb43fc6935a13e3fa55e518d6b724b08b8737623c5f460ce7f31362ac1fd78e61bde18218d7a3ee91b1ffde8118ae27fb700cf1bd2746ff2f89e17cd9ca31f8db0b319ccfbf4246fbe96b628cb7d231cc17a7c478ff413986f6e97a313efc1631facbbb63c8d7b7c498cf0a64b47770498cf67c750cf506b58ff1b272c7e3fcfe11b887f6f7cf88e17cded031e4eb1c99ecb524c6fc3a720cfede2486f622e618e2ef8a18e2217d42a67cfe408ceb0b1f8e61bed02646fdb8730cfa48fdc178f3a87dec3fdf3b067b3b86fd57b5de7425c5539e20e3f8eb0019e3211b3886fcd620c678c4f7293f24a963f0e73931e6874b64f477b520c678ba2686f1963931faf73931f457558e411f3d64ec4f7cef18fceb9618d703df1c43bddb22c6f15a13a37db78e61feda2086f12ae87ad07edeab63d0932631fa77db31d4abefc4a8df53628c5fe618f41bfbd7437dd21d62cccf1b62acef43c790cf2431aebf5d11a3ff9f3986fe3262f47fb45f0fc72b5c10e3fd940b62684fb488c19fd317648a878a18ded774fde8ef058e478fea972d311c1f158e215e2262383e13c07dec1ff71c43fcbaf7512f5ac4703cd78ebd7a7ff4cf3efa9fdc12c3f1e18018f657f5f8f6bee58f5b625c8f9e22533c7062183f75efb8de5fbd20a37f7b0b62cc7fdc31cc3706c4303e95760cedf9c8e49f743d58af68f73eae8760fbe45f2b498cf92f750cf54d498cf58d720cfa3747a6feae1cc3f137c4a80757c4986fdcfba8072fc4301efa1c19eda3e78e416f5ac4180f2f8e411f36c4e86f9a18eba72bc7f5f9bd1819e33f0c88315e3262eccfd431c4e79a18fd3521c6f5257c9ffcb9108e21bf3591d11e5c11c3f5f28018fc33c5fef551df78480cfbe7b7c4180fb1e3fa787640c6fa54c3f192eab1fc0c98eaa3e2d531ac972c91e9f34163625cef6b10e3f82c1c43febe40a6f9574c8cf5cb9b63f0df7362bc5f3027067bea0132c643f94c8cfefb4e0cfd951130c5837a20c6fb272dc7e0cf0362f4df866318df4b62acf7f17c3db44fdc2346ff6d13637c2e88b1de7c700cf9232646bdbd43467b551e31de0ffec6a0276e7fcc17ca31e48b4f62f0978a98d6731f1c433c6862bcffb324c6f9db9c18f5953986f55dd71e9c2f467feba3be161931f487dd3b86f87e22c678ba700cf3bb15318ef7dc31c4fb3931ce9f668eebf8f0713cfb54cfbf12c3f923458cf54d8f18dae73b62685fa23f52bcf18818cec7410fa420ffb921c6f719b1d7a9fdb9b647bf4df3f172848cf11224c418bf05328e5fd521c6fcb2700cf9ba498cfede06a678083c62d4d7d231d817cf4ffe5e3489b1de081d437cdd11437b5221e3f5e79e63d08f73623cff16993e9fb022467db8720c7afb498cf5fa3531fa7f0c4cfe575d10a3bfcd1cd7c7ab8418e71323c7f5f8491caf3ef63f3c3886f8e1c478ffc52786eb53743de84fdcbd8ffe8afdedd37c4f13a3fd26c4d8fecc71dd7ea188d11e57c470be60edb83e5f3246a6f5aa7762ac1f9b8e411f1931cee7c81ee8ffd52db0a0faee9d18ebb13afefacaf96b4e0cfbe72fc0e49ff99e18f59f3b86fd67c8f4f99d1531fabbe718ae3f43a6f9df8118ebcf6b648c2f754e8ceb692362f41f883f457a97df1363fd36740cf9e18e188fcf1dd7d7b37a2686ebc9b6c438ff7c47c6fe562dc7a0670131f6bf700ce3352186f6abc431d873410ce70b1b8eebf12b9e90a93ea3fed2fadcda31e4a35762385fe91343fbace9b86e3fd6c8686f3125c6f69963c89fd43ec67b211dd7ede50fc002edaf0262b4ff1b31de4fbc2386f6d4d071dd9eae9069fe714d8cf5684e0cc78bc431f40ffd4f08d0ffb08e57e1f459b78169beb812c878befc0299eaa10fc7600fda1ff35375e918f2e91698fc2bef3886faa44246bdaff6c4580f6862385e7c22e378471131b63f760ced3f20e3f8463d62d42ff73efa7fc3311c4fede1f8461298c633e938867c7a4e8cfdbf2586e3454c8ce33147a6f8183b86fe3d12c3f8fa1bc7757b2bb49f10a8cf1dc7b03ed422c678481d433d551263bcb71dd7ed7b6b62b8de00c7477868efc231ccf7c93e1eea3f730cf986fae3417be51bb0ec0057d09e227f2aa13f4eaffc0131c6cfc131e8cd3932da33178e417f1f88d19e0a19fd29d1c4b8feb1700cf1774b8ceb6d1132f9ff3786f6bac4b8ff9b63b02fee4ffe14e6c4a88f7362ccdf9218ec95627b4e0f4ac770bd8e717de4ce717dfeec8c18da9337c8e82f719f188e8f9e913dcc67f43efa4371700c7abc20c67af49318fd09fc41c933acf7278eebe31f37c4b07f922077f0fa968e21fe1431deafa8fd413abd29f6c8146f03c7f5fbd59218e3e10a19fda39a11a3fe53fbf4f9938018fd27710c7ae0f6c7f178745cdba77c02a6f14fde8971ff0bc750dfe0f5d0f856ca31f8d71b328ea70c1c43fb43626cbf720cc73b46fbfbc838bef10b31c6fb9363c8dff7c4e8af787e1adff08218f52c24467fd4c838bef92531dabf4f8cfb6f1c83de44c8d85f3520c67abb4d0cfb871d64ec5fb024c6f9589318f6afeafa4f6af29fe41119c75728c7d0fe1898c6b73a27c6f9ec2b32d5ef37c468cf01325e5f72458cfe5e3986f86e12837df21cd8d81bfab3760cf54b490cfb470fc868ffea8318fbf78d213fee8971be3927f66bceae91713ca25b629c4f3788e1f878818cfd952b62f4f72762685fc1f86985fd8b2ac7500f9d13c3fea940c6fe54af8ec11febfca5ce9d7e0f808dfe427f1bc0643fe918de8f77c8d83f79e618e6437b62cc7f8f8e410ffac8145fd41e8e679402537f93b563b89e2762b4e78363580f9c11e3f8f490d11e31770cd71312a33f3d13c3f1215ebfa2f15c3a067b1d88f17a226238be6c39f6ebf6a93d0f38abf543397f8b3f91b1fd5c13a33d27c8180fd12b31fa67e6188e87fe39ff294ac710bf37c478fd5bc7106f9218ae37ec23a3bdfc67c760cf3631f43fa2f3a33d045eafc2ebcf9bc438fe2362b417f89fd678bdde8c18ebcd376268bf7a715c1f5fd6fea89d3fe757c8140f37c470fd0531da3b7b770ce35322e3f5aa8818ce1f57c064cf6ce418ecd324467bec1dd7d79b6e91d1bed9d2319c5f21e3f5a5e78ec11fbac4d8fe0b32d9bb4f8cf58a700cfa4fd78ffd49f07c64ffaa24c678f9740cf6dc13e3f81d90c93f68ff0ebc1fa4c8e8ef72468cfe50ebb1f65c3e2b91f17afd3930d9773521c6f87d41c6f3cb07646affcc31d877400cc7179fc834be783dd4ff22710cf7131e88d17e73c730be2132c64770e7b87e5f3c23e3f509e918fadf43c6f1136f8ec11ed89e87d793d7fee975c81ec52d329e3f7e44c6fe2697c8d8dfeac6717d7db202a6feca4762783fba40267bfbc4a81f1fc8d89f64428cfe7aefb8debf7a47c6fe9567c4d81ef68ffa5b3e12e3f5d7f9c5f3487fa319308d8f583806fb2f91f17acb5764b44774e3b87e7f95033b7bb789617ff6e218f67f4046fb9733c770fe4764b2c73b328d473dfefe377b7f22e3f16c868cfd8d6364bc5e1502d3f5a85b64bc1e31770cf1db42a6eb79720cfdb944c6eb0b43c790df52609fecfde018e27f808ce7af0e8ee1fc703e9ffa173591f1fcfe0e19cf579d0153ff04be4ffd6173643c5e7ac8783cc3f3d1f58919321dff888cc7b367641ff871c3997989ffddb7d6165c70695eec7ff72dfac59f3e267f852dfac59f3e267f85ed492f4e7af1d5f6a41727bdf86a7bd28b935e7cb53de9c5492fbeda9ef4e2a4175f6d4f7a71d28bafb627bd38e9c557db935e9cf4e2abed492f4e7af1d5f6a41727bdf86a7bd28b935e7cb53de9c5492fbeda9ef4e2a4175f6d4f7a71d28bafb627bd38e9c557db935e9cf4e2abed492f4e7af1d5f6a41727bdf86a7bd28b935e7cb53de9c5492fbeda9ef4e2a4175f6d4f7a71d28bafb627bd38e9c557db935e9cf4e2abed492f4e7af1d5f6a41727bdf86a7bd28b935e7cb53de9c5492fbeda9ef4e2a4175f6d4f7a71d28bafb627bd38e9c557db935e9cf4e2abed492f4e7af1d5f6a41727bdf86a7bd28b935e7cb53de9c5492fbeda9ef4e2a4175f6d4f7a71d28bafb627bd38e9c557db935e9cf4e2abed492f4e7af1d5f6a41727bdf86a7bd28b935e7cb53de9c5492fbeda9ef4e217ea85e29a7bdc37afa0e690477f051ff8c57a11f384a73ce3392f78c92bbee26bbee15bfec1777ccf3fff1abef00bf422363d3ff00b7ec9aff835bfe1b77c60fe75c787e667c4c77cc2a7fc9e3ffcf9bef06fd68b197fe44ffc99cff90b5ff057fe66b6ef7cc91bbcc9cf788bb7f939eff02eeff13ee38c71efafe01347d78b9409268d0dbafc8629a699c77c16b090452c66094b59c67256b092556cc5d66cc3b6ec83edf884edd9273bfcf9be7124bd50ec825db22b76cd6ed82d1b98bede99d7908dd8984dd894ddb30736638fec893dd7af397b610bf6caded8bb3966c796acc1f59fed1b3faf17acc9ce4c5f5aaccdce5987758d0d7aac6fde4a0413c258e1c5d8e0f91ffd082994d0c213be084428227610f1ffaa7a2112918a4ce4a21025bb139579adc4da586123b6e243ecfeaeefffc02a622f3ec5415c884b7165a2e54fca313fa517a1b81637ec8337c4ad18304f0cc49d188a91188b89988a7bf1607a3933af47f1249ec55cbc88857835db37f624deffde3262c9ee454334c59969f74ff18d9fd08b40b4ecdff2161dd1153dd1173dc92593424aa9a4668fd233ca3093fee34606329491103296894c65267359884f59caca68c86fbc46aee45a6ec495a9c8fe04dff851bd905bf9217726773ec9bdb1c48029f9290ff2425eca2b795d8ffd83bc91b7c60a57a294037927877254ff8ce5d864d6969c885b3995f7f2417e6711f1261fe59388e4f3aff78d1fd50b39973bf92217f2550c8d3f48e3116ff25dde89b55cca866cca33d9926d792e3bb22b7bc60e7d6b0565128e124a2aa5b4f991863c3652be0a8cc2923d9e54a82215cbe7ff35f442252ae557b26b74c2fcb04465a69fb92ae44195aa32fe7fab566acd7ca31e635b5ba88df18185daaa4c7da81d3f533bb5373f85fa540775a12ed595ba5637ea167d63c65ed440ddc9e7bfbe5ea8a1b811e76a647c40aab1e9e3c48cf15469e3fd4cddab0735538f6caa9ed4b39aab17b550afea4dbd8b955aca816aa8a63cb08d3a33d613f54f617e846aa9b6fdcbbda41ce25e7555efafaf17aacfdafc499b09a8cd1a669473630ba5f69a99d12fb4d052542604b4f6b4af031dea4847c63306e256c762a8139dea4ce7ba404be4baac8f371123f7ba12a01e8f7aa5d77af3d7d60bbdd51f664ef12a467a2799deab83fe54b91ceb83bed097fa4a5feb1b7dab07fa4e0ff5488fa5146b35d73b36d11373cc54dfeb07638b99ceac6f70f3d28fb53573fd64fefdace7e209bc43bfe8857efdebea857cd66f6c2b1746074236513bfd6efa71a197bac11b2cd34d7dc602ddd26dfb9774c58a458a43e6906f9a99bdbbc67699ca748fc5ba672cd2d7b9c73d66226c6fdab13f058bb4a742a83d3ce1491eff55f5c2536c6b7abd161b3df5b4f571fdae97f64fa27a816c1b9d1878a11779b197e8c444cfa7f0f993a9cd7722b3ffe7732f557b9351cfbc4c4df4cccbbdc2a84d66f694c6b746a6b527638fcc2bc51c728a57792b6ffdd7d40b6fe36de58085a662b8f43ecc54c2da61e7eda5f43ebd8377e15d7a57deb577232ff919bbf66ef9ca1b7877ded01bb14f6fec4dbca9a9d67def9ecf95f0989dc3eb2eef98bcc24cbe3dd4da61bc434ebc877a0ef7eccdbc47efe92fa917669ecddb62c312de30b1fda4f6deb3faf49e75d79b7b2fdec27bf5debc776f29efbc86d7f4cebc96d73699f1b735a4f2cebd8ed765d2ebd9fc63f289a9bc74ae98d7c73891ead3e7620aaa21573ee3c15f502f6e7d21195b1baf80eb2ecc3816c6c34772e94bf3a37ced7b5e9f3f7b53af656659ffa01d53537abeef074cf2b6ad348cee1a35e11d7df0c3da370abd14433faa6de1f1a9ff4b6ad03fa2177ee2a7bec9007eae3339f276b5358ceaf1865fe8815ffa95bf929162fcd95ffbbfa33d91f85bff830f6c0ef136c6339a6a27c7b577987c6bce30f777f50ceec1eba8e15f492ffc3ddbf99fbccd125b6f1b4b1430869ea92a7ca314fe857fe95ff9d7bca5fabf772cfc1bfee0df1a6be4bcad73a31b4645a5d1623fb46dab9d3fb0f359ffce1ffa237ffcd7d10b3ff027661a71601329bc9dd5fb5af305eff853f5e85dfaf7fe83995b307ff647e698fea3899627ab42bcc39ba6963f9879cdb8f63853a38bd2af67f6fedc7ff9f7af8bfe5ebd90cffec2879a39b3f9cf8e9b79997fb1d47ff5dff4c87f3713adbeb8f9e3f580bf64c26f88dc7846a3ae408abadad0bae42dbf69eb50e97953ffecdf3d3ff9bd7ae1b7f895b73579636366db63f4895c1dd895dff6cffd8ea9273c16fb5d5327fec098782bbf67f27357657edfe4205ed719ca7a5dc003663ce3311081349af197d08b40795b9bfb036da21ae610d62f3ee524f04c84dc7837811f0441c8c31f1a9338884cb5d15259109b6ab4ab0fe017e63c2c4882d4ae6b0459901b7df90be84550980899aa2228add6431da097721c5432d403d60d5626bf7c78ad1f1d93601d6c4c8eca4d15fa116cd5ced4e53af83067e16c14eca4c79e83bdf1cde8cfd78be03338185bd8191803bfb01935b8d0fbe032b80aaecddc7d62aaedcdcfac4505377c6e66afdd2096774641c7a6eab035e8c1fce656cc834170170cc5f59faf17fe2c1819ad3fe367c1d878726d15bb12c326c12498b2a1bc34b5e321b8ffa9b1894d2dbaf57ac61ea98995077b96ba1e1f05b3c0e412b10b9ebccebf731df4f7e945f01cccf9b3d5365301b4eaf539bbf2c0d92a78091662a819fb085e7ffaded747f06694f920ef8c66ec4d255a584d32f93b0fdee54ccc8265d0089a7fae5e98f13e78dbe02c68e91e6f9879d4b456f88ba02d97c1b97975826ed0f3973f3b36fec6f4d5cce2a5b0fac93b21b77ee1ede4bb17f8f5bdb6a011b23f572f42119a79839e09a646d62f4c1cdb1aa0d02c54a1964b3343d986decf7fae423e873e1fc94b9355cdbc5d77ebdc5d5a6bb0280cc2308cc2d80ffe5cbd08599884298bf4334b94f58bbc9e4b16621c66616e66659c7d98b9e411c626688685649ea9b994a9bacc9c6faf9fbc9df18c376f1e9662e68dc38a3ffc797a617243aa5a26930ee4a75c58bf3075858964f5c917e14a05a2c136ec3c3cd2d8f8db706d3ca32b2f4d0d9aab8f70637ce3dd33755cb80d3fd853b80bf77fa25e78e1a738a8891c88b55c48bb52f704b305c9c34378a13bfa22bcfcc91ce2b66a185e85d78249667dc3f8433d6bd5cba0d497d267f3f02650e1ed9fa517e18097ec36bc63eb70188e586c6c51d6f3854f9686e370124e593bbc97db238d51e889f04176c558303d0b67b6ce000565a9aea4173e060dfef1efb9a7f63bf442874ffcd6f3d95aacc530e87cd38bf0399c872fe1820f3c79acb1e19ffe327c955dfe22989f07b1329a61ab71e38b997f1ebeb197f03d5cf2f0cfd18bb02152fe14363517b7e61713de0acfc296f58bb01d9e871d2dcc3ce4f57863c49ade547464972561d7e4931ddc71d4a51ccb7d7813f6c27ec423f6ef98b3fe6bbd88042ff893bc64eb60256ef9b2f68b835d8b129b480622527e4f5c1e6f8ce473a423cfe4a6848df5bdbce36d53cf186b78bbc88f02318fc228525dffcfd28b3c8a8d5e84c62f4a7b4fc466399bf7e5204aa254dd0487288bf2e38d515444a5ec6aae7b62547b86bd0957dacc1a2ca24adceb2a5afd3b3e03f8aff5221c44eb28f67c29a38db8d53bbdafef08dbda338bb6d28f3ebcb9d7f4ce8f3546fe8d484418ed8c7e8ec4584fccf964bd5e7250e682a37df469a3c43b3bfe9cf5f7d5176ce769311403b551733327296abfd05e3fb88a0ed145300d2fa3cbe38d918992abe85ab5d9448ce44035eb95f2bafe34f5792bba896e23ed4dc3c6afd70b13252c1a282fba0b56d150acede70b3cebb76606e9bd0477d128ccc5215c46471b2333170da2b11a4513964453e37df77595a1d4d46c5fa28768163db2dc5b79ed5fad17763e123df18e4ec46dfd398acbda67cbfade270f27e2297af682686e6fbb1f6b8cfc71741979b21bbde87b16eb3d5a5fa99c4da285f1c5d7e8cd7b3cf69cf5f7cc47a277ef36e4e6ca96d150be9a5afcadbe2f92ab0ba39e8da8199d45ada81d9d1f6f8c4cc6f4c32b9b4ba20eb36b3bfdda338c2f060fde6bd495aba8c757e2ea57eb85dd467db63573d427518aa1992bf4e1de883a9899ea4185310fae621684478d5f150b3689a5a93fcdcc3588eb7b103067ed8b66ac621d7b3c3dee770e7edf7aa73fe343fe1efb621807b2eb6deab9597ddf330ee3288ed97d9cc4e931c728cea24bff2dcef5b3189b5ab719ce60edddf8473b2ee232ae642b5e89c868cb2fd50b2ee23537734793439ea46413cdd4bef68b42b178136fe38f78676a8c79541c6f8cd821def332e8b3095b9baa2b0a62b7e2dcf58bf833dec587f8c2df9b68faa57a61d715e24b3e17eb70145fb189bcb3eb0ab52d3ee36b91a8d0545c0f7c1cdf1c337ec3417c1bc53697e867160763c5ea3bd95339169bf0100fe23b7d25c260fdabf5c2f8ec50e472118ed4dcd4835d25e1fe88fd94623c3293c6a5df66b7f1f898f95ec4f144ee545b744cc575afd3baf637b9442fe3697c1f4ee2877021e7def87873d6df7b7fc4fb14793c337ae1b3500aa39efb3a7e3ff5d2bb881fc55206c6164f3f7e7fe4ab6df41e3fc773b9883a26b39a28d18f36ab0617ec9cade2977811bfc66ff1fbafd60bb34dbd0def5abf507316d11cc1ae39a92c9c9b5cb264a5b1c6916bc1b8692a9b775b7ffad7f5faa799a105178aeb697ce63fc7adb81d0cfdfdafd58b3a972c8240f3d8577331d2793d46e81b46d7cfd98357ea9db9b223e692c74ddc89bbaaede7626ce6ac703742d84f320565dc8bfbe14dc2c32ab1f7ea7fa95e703361e273a3e8a130a3a29a768ce0beaa5e2632ec272ad166463f39662e312f9d78a2239918998a8be9bcae7897aa30fac9139df84920a7c16b12fe5abd78dc245112abb6c9f743b19197668c0aa805bd5d78ed6fe2384992948f227dd45a30622cc9820e5bdb35f824e7678a9b11a8d7e093427c24651cf232a97eb15e8878cf243719351c31334a416caee850cf9872d94f56c99a3d249b70986c8ff9794c11271fc92e8ad5c85435a6e83019ac50a25e3b79637e7848f67a9e7c7af23873d63ff279ade4905cf0d770a47746cbfaf51dd5bc5e7392ac6fa2e432b992fbe4da5f1eb316f4da6c9fdc24b7c9803fb18d6ed8cf0e9ae8dc2b1337c95ddc4a86c1345c86bf582fccf6815db3b6e66a2ea54e4d556c6c918cead9fb241927133f52eb649adc1fb31694cfc9835e27b368cc6e95f0eca710f0ceb6defb45f2687389b8499ef8fe57ea85dd26cf463fd7f19518ea7bf81c86b1855d996d283fec2473d962efc98bd1f523e6127608d6d1557c1b0ff9796d0b6d7c439a735f9ab9914af661962c92d7e4e157ea459d4bde025b774e4d36199bd8ddd367fcbd3e5b27efc93269b08c8f9223af2bd8ef188522394bead5f7fa9c665698b4599c9c279da49bf4923efff8b57a61d71552ce5b29333586cd2567b6be80352ecf97217b488599975cc5aba3e6927a1bac138f5d9af8e0f80d8da9d79743d655b354ea2b95a62afde9efb7fed1cf83ab946da54c3d969879ebce5c99a8e768b91ca57e1aa4619889db344a8ffed9fee4234d4c8785fd5e42ed8b5a8ed38c85d15bbcf35ff98197ecf3d7ea0567699e5c041df969fc62909a397b3d939e9a5ac36393b48cce829dba4eab203ca64fd82ddfa5ab746defe27a1fa6e6ddf3677d907dff3aee85f36062742cfbd57ac165ba8906c199a93142b69697c6333ef173a9f613dd8fe9364a8377769e7e70753c9fa8b71f6cc976bc93eeec67113c6e6601b9fa60917723e7e93efd4c8ff07df83ffafd11ff9171cf1483e9855ca497e6bacef193a9f6537d9da413cdf4ab8c63965e1d572f184baf8d8d6f22df545ca96aa6b7661ec0c4d05b184b0c828d99affedafaa2de069ffc8a37e4423d59cfa8bf41879ff79497e95d741b0ffc221dea453a3aa65e784f5e3335358664aaad326b0d9d0a964e582f9d069b64c71ffe892fdfffbecf85fec0f753c3f441e4c62f3e5353fba90f132512d6a8e5bb3c0f6fd2595c88327d3c4e2df86d9b3ea56b6fcb9fd52e7d363380a6caf88b5cb0cb7498ced3977f7c5c3c4e177ceabfe8b57e39ae5ed8adbf16b960d18bd50cf581b5b899c17b3b1337afb14adfd2773ee6f747d50bb335d658b296c883aec879cbcc8daef96dda489b7afbcf8e0b9468fbb7412477c66a67110f86ff68ff1ff97e6ab8f2365ea1797ca5a7b25747491e7cd839bceea6adb49d9eebebb4a3d263dfbf3075af97764399f6f85ddacf78c632f1af3eef297326789549f6942976ce6f329d79997f2cbda8bf3330635b9db0502e78c34489acfd42fba11c89db2c0896aa277a59e81d75fdb3de463c5449166571ba096ffff9fefe583e6789388883f2c52c4bb3cc68dcb53fcd72b6f45a47d20bb3f5d759c1bba98993acd4997ca75a501dc2667c1675b34addc72c5bfd7b3fbffdd5d6b76bf677d93adbb073bf17ae334f70bdcbb66c2e97d126fb48baf14db6fb7a5df6479f7f91eded2a97fd9eaab1c51b7d76462fb34fef226ef9cfd19b28f9e4e76bc1dfb7f5c77aebb532a112711333fbd42676ced67a9a4e4469bf55cfba2c531b21b283686617c936bbfc6a2efda3cfbfc8aef84d10d8fb9d7685458e8d5ed867177c2a26c6e95b761dbfb055762342ef88f72f701b7df73d124fc5fe325cf10daf8261348ee6d9addc27292b752006b16f227560fc61190ee52bebc976a4b24a24d91d5b7eb52efbe3cfcbc9867c6efd428ce45dfddc02bb2e5ea84fbd0fa6d92878ccc62c4d5e928fe3fa80fd6c701289883ff8beb140994dd832d8f049364db4f7ca4ab1625da1ed3765598fade2fbec3ef6e45e4a93e51f64983d64b3ec317be29374732cbdb0dbec599c1b5b6cf47de4eb9ceef0999cb20b9fbd755c657319f3c9b19f55e027d94bb6c85efd5636d11f26331c84970d82a97af04bc94d5cec8c3fbeb13249e5793ccadeb3252ba389b80d2a33420d35cc9ac61a67c1306b1d4f2f8c5fb4d96d1028bb363e5159fdfdebf7ba023db04d709ef8c9a39cc64c2f8eb7fe99ed93add18243a4d88beab04c5e1ac51a64e75927cbd8cad4a0895d71b34f53c8baeada6864cfe48f3e2bb36eb8f4dbde59ceb38b9ce5227b0a32b63c9e5ed86d2eed3d56cd4d0d3a09da5edf7ea6cd7e2e4333e320fa71937ba6429e8b23e592dc673bb6cb83ac2b3ec52ebaf10bfd2c56799847e2238ff384ad5924c6792aeff22c9d7873fd6abfc128eec3439ee7455e8aabbc92d76aa6e2304fb6f9ea987ac1a5deb25b761e8ee4a71c18fd045bd4f33416e6eb6cc4eea356bec9b7fca7ef5fe41fde2ddb05815cc889a9bb57de6b706db645ba0d96f1367a6366de6cecb2538f828b91b6f96d98eff3cffa7b6a7779fd19915c8b66d265f7f2d6f8c590af12713cbdb05b1b25d18b5d17d7b3fa53a9397e1be823bfc82ff32bb1cdaff31b91fc58fbfc33bfcd07e9a7b84887f95d10e44396d8e7fae5f693d8cfea3a1fe793a4112e445f8cf2a91ee5f7f9433e63f6735e139f7b41b4901bf6903f8a5dfe24bdfc39dae73cd1d92c9f674fd9821f8ea717f5f660e6ac037b5791c59eb69f0ab09fcb08edb31e7af22c5ee42fea9a2df5f60fdd0b8f8266be089ae19599d38ca241f4143de5aff99bf0a4fdfcc1bd9eb291f18faef18bbec9193c1c194bbcb34ebecc1bec396fe6b1181b1db93433fa323f0b17c12efe604f792b6f87f3fc3c9b5abfc83be226f9fcfb5cf2b3cfe34bfb7c105fe55d3da9bf7d05cfafc8f532efa5af795f050597fb82fdab672215a2905e4bbfea6da13c59e8e8a9f0d26161924611445e1186f6392c9d2232bebf968b22e2f6f94d8368a3e3686946622d7a451c054522766259987258de055b3589a659371d644fc9dc7e8f317cc9abec29cc8d4f348aacc8c58db9b8a3e985dd860f41507bc65832fb9c026b09eb1bf2ad28b2eba22caa62c596eaee9fb553ac935d94159b625b7c444fe9301bcac458601779a2fee1b6865d8443b6b64f6312b7e1d05493a9dc8ba1c91a23fb19505355ac82243e2bf67ed3541377f2c03b6a629f076732ab9717ec25fe283e8b43786eeace876c5a5cc8b0b82cae8ea917761b748b6b35d7cfc66b85b185c46f0f8ecd58dd14b7c520bc2ceef8c73f3abe50f1387ee287e08ecd83cf62588c222fbf0edbc94078ecddfa81e9cfabe95f47dca617f6dfc5b898186b18ffe02f700fbe98d6ebaf32beaa9f4671e7f7ed0a6070c66ed4c8d43a2ff95c45d14df419dd14f77915a9e2c1f8c54cdcf81fc5e311f5c26ced131a4dc5bfb6ab5cba5e1337758636f6b82a9e541855e226fb87c79bde3ff31b7e53ccc3883d679be225f28c472c8a057f0b87cae802337512cb8a57534d3d8a81b181f18a622c3af63dd5566dc94c0e9b79b9fd8ea4c96507336bfed04c656a12f44dd5c38c729ccb56d415923d0a19758bb75cc89616c62fde8b65f19bfbb03ffffcce3815b9b85563cd7daebbeccadbe965bd36be2b9a712ce6c5d957df43e79f45ab6887977920657ac1fac579d1c98c2f181db82dba461b7a5617582236ac1fb76510c745bfe4d62fc46dc944279ac86e29d8c6f862aa53638333eb096a2245fdbdd1862942077c10f4830eebe9ab52b1273353f5e2f3681fa952979ea9cccf9383a9ddaf8ea7175c94beb795e6bfe8c5aa7719e8a7da2f94927c51246558467ff71d827b533daea2391f4703b6339125d9da68a17d8cdd44744ced38f217c61663eb13561d582f984637a66e7ac93e4c9dd5b1bf37fe302963d5b4cfcc28131b11bc632d617c61a226c64726968320e8cbae28e5d2d49b4de98937e99769f6106a392fb332d73e3f94c531f5c258a314a6048d5ed20b7daf9aa61acfe1797bc1367f48e63c2fab72e50d8a46b90eafbc6eb12c37e9b0dc961fc9a05894467da39df1fab51d6bfe5eeef87bb4331678afc7dee8859e668372cf9ecb4ff560de1772a2ecb7f2263aafbfe36c7eca83f5049595b2bc088c7f9497f07baf179c9557e1b0bcb6b984cdc54c980c6be6aa8df2a6bc2d07e51d9ff8c931f5c2ae439643cdd593e6a602bdb34f92c26f457d94a364e99d672fe5b89c94533ee2b7e53d1f951faa145ef9213ae190bff177d98d62f37fab0d1deb13f483be7129c6e98368aa1e4bd5846da09f2667d9e7a834cb076b05deb0df5bb4f681df7f7bb18d992f75a2b254e5ac34be9517e513bb2f9fe579392f782292677f763cbdb0b92068972fe130657211f9eac35843a9bc5ce8cc2fcad7f2ad7c4fb2725936cc78770ad35f9b1be299898777ab0b6a549ae32c1791d18a9ee89446f12c9bed24e8f086974b667c84d9be5a5da86dd13431d0b7df55e40d6b0dfafddf6f4ba97bf6d991c153d92ccfca56d91649792e9765a77ccf1ad926d3feec787a61b76597b58cc68fe5a7f18fcc7e12d30fcb9efa10dbb2cf9e2b5e8c8de7c7266398d137c2b0801f517a41f8203ac637de6c6e005f3036b2738e89bd638be39dd9f88771ae9f0a31a1dfdb57c5fede17be7fa949258c1a9d57b2527215cd92b5baf15f2b9d4d63aff2e49c4ff43a681e4f2f4c8d9197db20101b31323561a3feeea0ad31de8d7a3ed8ef947a015fb249e59b7982c93955e0053216039b13f8ab1a810f583f31f972a246fc4576ab50655e513fafce8d7130d65d3dfbe60be5a1d6cbb37fe413766befa384d7729fb6721e6fcb66320f27c179795345559c96a55f257c94b58ea717765bd9e7792ecc1ceddeaef9e983d50bafaf3eaa2c6fb3c7f03c7f6393283639736172dc6595a7af7ecb5691d607d4087482bffb769ed195cce48889fd763ff881cd0bf5bf9a759e305ea29affcc177efbb2478443e31945a9c47d55569568c687e4ae5a85efd943b50e36d5e6787a61b7c13bfb30713908b65eeee5bc659fbd68ea0cae9e632d66712ba84c8dc8cd3cf3b5da268bcacc96bcb58c4dedf82a17a017b2ebf3a09fd423a9263647940f6a92d8e709cd54667cc2f03ff781ffbe35d16a9fe9969aca2c2d6fb265f9c9e6d5cece57cba76a6fc2eb5e96e2267ed2dbe3e90567f198b5d496c5726866462cb0cf1ab46b9f4c8cbdcfea335cb19e1c588f576d534f5e47afd5c17f3699dffa45574eac32d8ba31a82b26f487a6197dd28be6b7dcf1475ef62988f648537fa681174e6c2e896ec249945417d52a9b49337baf2e855f5d1d4b2f44c2ed9a772e85bcd37b316077a617cf8a79a6068ea6c175e227976929a58df352a86dd091d33c8fde6cede873d35f51574818dfb0353ed1acaead2e180b8dff882f7cb535b3b475f621d7d58d5dcb48e601cbaa9cc52fd5453e4eef926b98971c412f22af69ff9e447026c7416c3fabcd4676445556d78d4c8878c99ec5b377632acbc4d41063336f49ec7382adf7436feb279ad663693d03fcc2daa3f6961ff087ffe61f0db9f08beca96c470731f7665555dd26efb1ae06d9347be0651616eb63e84575c787de7d3e2c2f94f4bc602cc67acaed1c32b3916f7c60efbdd9b980df166b9644bead9df47d3eb2969097b257e7c64e30ae86ba2f0fd5e8fb312d1fcac3cffa441d239791cf7a455e8dab1b363391d2ae262a48fc6c1a4cc4553e4f3fed036f7e522fa274c85ad5d4334e974ecd9c91d57f4b600c39cfcc1bbbdcce283ad5bd96a257d70c0c34c0f886b184eec1d6b0ed33fbfbf1b46af9dbdffd3dffee5743eefd37be8b6ec53cecb197709277f4b07aa8bc6a16a9a0489f44fc737a1133d6e2b7324df7d563f514b7f52c3216b163eee772908f4ccf97c60b1e74563debccea85b5453517a3acd4f7660e99d8ef2647be7d3e8e1c060ff699523feb03b4358af53dcfe4221bd815bfeac5ccd296f1367b8a92709135f24915853a6807cd9fd18bf4890f446e469e578bbcc1e6c1ad7dbe8becda3984c929f6798ecc44c1a5e929fed86adafeceded7d03dfb833e92420df1a3f9e2f7bc24cbbac122335a117fa8b07acd2e42ed0fc243b4a82eb20393d1e58feb4590b34b91b31ba3919160d55e96d94076f5056fd8da534f4c6f9f4dbf7ba67eb4cffbec99d7a59c5473538bcdccdca201ca49be026cf2c9517ce2abad9a888d3c8fa2c78d0ac54e858f9bac515d44a68049cb7051bdb1ed8fea45f118b360ae26b61f7565bc3035b51d7356095b330866bf3d68fcc08efb0434c15ac3a808e8c3a5fda9b74c6dedefed8f5da7fc37f9855de719b07e7099ecf3839923bd4761ceab65a88b7d91055745973fff985e0479f1c15a660e68674ff518d7cf422e7823e8578daa2999cfad6ed8e780f386d18319f880d9c758c7ae3dd9e7a52bb488d115a3a06ca31af5fca37b5c9f3055b8d5db96ee86d7ace79fdb95e0ea4c7ad547b48fefccbca4253e8369d54e3f7f4c2f12ab990d5b2f525eb06b8df2a09a6562d71931571c6c74e854de599f405fb8b32b72765d52eff5dece35c83f20b7d42b7447f307de5266168b6cae95f5d37dd20d96d559d84b2ea5aeced97d5514cdaa13a8a0f1637a118fabaecd15667ef102f305755626b6d710f73a4d6f75df3e574f35ac35cc3b3da827d25b6b09589fb43fe9ed77ba71798c1ad3e9c3ce5670411b2bfa336d6a5c719b0e643bde563d318b3ecb76362b1e64abc8bd45b80c863fa617559f9f077d13ffcc3ebb04ea066b89fad99b5d0dabd233b7de543f1fdefeded452b6a2baabff9e80fdf9e643f57e562fea4ae3a7fcc13e6334ddf1b67daebf7dda36fdde5cd588ad565cde88b9fd9b39315f3175be122bb9522bbdf27e4c2f56fe2a303a606c5044662e6eb659a8eaf8373ed0b73e60ea8b49deabd7a42e8d6ff44d3c7cc07cc3fa4e6d1b1ac3eef739c55ae4877da3057f9f805dd92dffcd9cd6dac2ce4bc2e7609a5762c91ec5ac3a5b85ab287af3cffd76b8e4d31fd38b551c0decdf1f31b922865c6035b4bec759af49adb0beacf521b316b25586f9b7a9b2eb979b73d4d738f9e61bb5ba1e7e349f386df8f265eb60711bb556e92a136f62b6cad37319ae0aef25f6f4225aff687db12af939bf317effe05fcb81a91dd147f88bfd66edb7bac1d61b9843ee54560d8d8e7c1bcb9474c3e6906fbef1fd5ad6cfe710b090e5ca5c91a931f6ea21526c667e5e56d56a152ea2a8ba58ad579b1fad2ffcd96acb6f8c325bad18d4ab515d39a8eb4c66f24bfd32d6b0339206db983869da9c0139c48d93f114faf7f7ba6195e51839c468c66ffc2438b3e3130e5916df18cd581665f21eead547a492f7dc5fed7e743e12ae92e7aa5bd71103653387a925ed67f87d6ef4a32307661bd5fa31b3f7b6ecd68e39d50f726875d4f8889d7d808e64e41b5feb859d937db71ed132d972f77bea8aef7feff56c6d68c62e0da659b5dab37972992d7326cb34f70fce2f7e603e120cd371d0afebe7cc3e4bd0ae4dd4f776bbb68e841a13ebce7abe6135c3664da31af5b843beb07353cdec3dd03ad3d4fbd8f5cc7f994b6a7bfc717f01cd28eeb227719fb7c4cc9b8537c55bb4f73aabcf9f58bf78581d44beba905d3f17233bcfb0b5a67e30b190c29cf45bdd60ac62957366734aad8e771e66d5606cef06836f404e01dfe1cd63d69ebf594b9ff157218a3c6ddb5c2266f12069946938ad7e582fec36f94cc7defd2aa933e71d640c9859502d69fd01fefdbd1ed4bfcf6d94581f019f70b5a189a6e3e8c53ff00b9bd5bbacefbfc6dbd5257bced2ea2c0d92fd6ab3bafa99f50bff897dacaef980378d4ff7bef705332b8fec3ca5ae382fbff711d842dd257bd647709df3430eedb6b65ba39eaffc1be6aab035bab6d757f14eccea4ffaeda4bfbaf1d9cfe885d9863ee777debdd5051619addc7e3ff676b6f6cd0fbefd1b5f77506fd178ad6ee5d0decbf8ee98eeb7f10cceeccf11724b9d57a4fd7b5bcbd5203f987aebc01ef34391acee929f5def3cac86ab5179558f75fadbb1ff6e6bc7f837b5a5f1071f7ca1d60d1b13cd5ad72e7feb3bc79dabd6ff6a1acd9ef1c56a9c2f5793eaacfecb72f3ac67fc62fa73eb9d8cf37391f38189f1de2ab17df8b636f1fdfcf3fbfb9f0a7b6fd7b1e059e0f665e72cf51cf6bbfd7fd60fccecacae31ecfce4bb39c9c46479934b56f7612e9e6c94ac1e4c94dc05e1cfde1f59cd582b1f7eef0b902b8c5e5c12dbfba2565bab919dc5c3fbf667f5687e7b69e7ae3066660e6b676d99f9bd55d09fb91f622bcd1dbbe26754737eff7e29edfd92d554dd5437f03791aa9e77c67f4e2fcc3694fc2ae8c37dce6f3e613f41856b5513f81c55bd9e09cf9d87ca0c34c3cef233d48d7e6d993b581f7573963f92537e67bd61eb4f5edf2f918f3697d828e1e9eae967ef8f642d6f2372537309fb84f3efd621b6750eb9abd7b0fe4e3f6ca56eb736137f773fa45eef303e92dabf8967d749ed6713bde277fb02fc35acdfe13bc199caccfca9b77a5ecd2197b0b99caf5e7efe7e6af0965c78f7942fa08eb0fda07fd31cc3de39727587f321a8ace4a14ceabcd2af86f55f4bccec3a58ed1d47f70b9b8f4cbe9aac16abd7d55bdec4bf37b85dbdfffcfdd43009467c5035ec7cc268c0525e06ad6f7546dd5f3347b32b7f303f81dfff565f6c56ae86d5a81ad6eba17807c97e2eebd8f505ddb73573d6c5aa51de445d36afff2ee795b7faf9fba96973b5b535463dde3d53554c6cff3d5d7f9bb6616bae7aee8aeb1934e6b42efe7735c7acdef75b8de1c6f2fb5ae438f5a7a93e7b51591c581d27feb6ac8ef0f98b78d534f5e796cf4dc4ce5767fac0cd4bb58069bb3ab3dbfffefb2ff66b192f7eaef959ed43ee31de665bd8121f63cb5be5d46baed6ab56781b158c799fc7fafcc5ff1fb6fff9fffe9ffff1ff01d65fbc39 + + + + finishButton_clicked() + + + + kactivelabel.h + kpushbutton.h + + diff --git a/kgpg/listkeys.cpp b/kgpg/listkeys.cpp new file mode 100644 index 0000000..2a10a1c --- /dev/null +++ b/kgpg/listkeys.cpp @@ -0,0 +1,3149 @@ +/*************************************************************************** + listkeys.cpp - description + ------------------- + begin : Thu Jul 4 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +////////////////////////////////////////////////////// code for the key management + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "newkey.h" +#include "kgpg.h" +#include "kgpgeditor.h" +#include "kgpgview.h" +#include "listkeys.h" +#include "keyexport.h" +#include "sourceselect.h" +#include "adduid.h" +#include "groupedit.h" +#include "kgpgrevokewidget.h" +#include "keyservers.h" +#include "keyserver.h" +#include "kgpginterface.h" +#include "kgpgsettings.h" +#include "keygener.h" +#include "kgpgoptions.h" +#include "keyinfowidget.h" + +////////////// KListviewItem special + +class UpdateViewItem : public KListViewItem +{ +public: + UpdateViewItem(QListView *parent, QString name,QString email, QString tr, QString val, QString size, QString creat, QString id,bool isdefault,bool isexpired); + UpdateViewItem(QListViewItem *parent=0, QString name=QString::null,QString email=QString::null, QString tr=QString::null, QString val=QString::null, QString size=QString::null, QString creat=QString::null, QString id=QString::null); + virtual void paintCell(QPainter *p, const QColorGroup &cg,int col, int width, int align); + virtual int compare( QListViewItem * item, int c, bool ascending ) const; + virtual QString key( int column, bool ) const; + bool def,exp; +}; + +UpdateViewItem::UpdateViewItem(QListView *parent, QString name,QString email, QString tr, QString val, QString size, QString creat, QString id,bool isdefault,bool isexpired) + : KListViewItem(parent) +{ + def=isdefault; + exp=isexpired; + setText(0,name); + setText(1,email); + setText(2,tr); + setText(3,val); + setText(4,size); + setText(5,creat); + setText(6,id); +} + +UpdateViewItem::UpdateViewItem(QListViewItem *parent, QString name,QString email, QString tr, QString val, QString size, QString creat, QString id) + : KListViewItem(parent) +{ + setText(0,name); + setText(1,email); + setText(2,tr); + setText(3,val); + setText(4,size); + setText(5,creat); + setText(6,id); +} + + +void UpdateViewItem::paintCell(QPainter *p, const QColorGroup &cg,int column, int width, int alignment) +{ + QColorGroup _cg( cg ); + if (depth()==0) + { + if ((def) && (column<2)) { + QFont font(p->font()); + font.setBold(true); + p->setFont(font); + } + else if ((exp) && (column==3)) _cg.setColor( QColorGroup::Text, Qt::red ); + } + else + if (column<2) { + QFont font(p->font()); + font.setItalic(true); + p->setFont(font); + } + + + KListViewItem::paintCell(p,_cg, column, width, alignment); +} + +#include +using namespace std; + +int UpdateViewItem :: compare( QListViewItem * item, int c, bool ascending ) const +{ + int rc = 0; + if ((c==3) || (c==5)) { + QDate d = KGlobal::locale()->readDate(text(c)); + QDate itemDate = KGlobal::locale()->readDate(item->text(c)); + bool itemDateValid = itemDate.isValid(); + if (d.isValid()) { + if (itemDateValid) { + if (d < itemDate) + rc = -1; + else if (d > itemDate) + rc = 1; + } else + rc = -1; + } else if (itemDateValid) + rc = 1; + return rc; + } + if (c==2) /* sorting by pixmap */ + { + const QPixmap* pix = pixmap(c); + const QPixmap* itemPix = item->pixmap(c); + int serial,itemSerial; + if (!pix) + serial=0; + else + serial=pix->serialNumber(); + if (!itemPix) + itemSerial=0; + else + itemSerial=itemPix->serialNumber(); + if (serialitemSerial) + rc=1; + return rc; + } + return QListViewItem::compare(item,c,ascending); +} + +QString UpdateViewItem::key( int column, bool ) const +{ + return text( column ).lower(); +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////// Secret key selection dialog, used when user wants to sign a key +KgpgSelKey::KgpgSelKey(QWidget *parent, const char *name,bool allowMultipleSelection, QString preselected): +KDialogBase( parent, name, true,i18n("Private Key List"),Ok | Cancel) +{ + QString keyname; + page = new QWidget(this); + QLabel *labeltxt; + KIconLoader *loader = KGlobal::iconLoader(); + keyPair=loader->loadIcon("kgpg_key2",KIcon::Small,20); + + setMinimumSize(350,100); + keysListpr = new KListView( page ); + keysListpr->setRootIsDecorated(true); + keysListpr->addColumn( i18n( "Name" )); + keysListpr->addColumn( i18n( "Email" )); + keysListpr->addColumn( i18n( "ID" )); + keysListpr->setShowSortIndicator(true); + keysListpr->setFullWidth(true); + keysListpr->setAllColumnsShowFocus(true); + if (allowMultipleSelection) keysListpr->setSelectionMode(QListView::Extended); + + labeltxt=new QLabel(i18n("Choose secret key:"),page); + vbox=new QVBoxLayout(page); + + if (preselected==QString::null) preselected = KGpgSettings::defaultKey(); + + FILE *fp,*fp2; + QString fullname,tst,tst2; + char line[300]; + + bool selectedok=false; + bool warn=false; + KListViewItem *item; + + fp = popen("gpg --no-tty --with-colons --list-secret-keys", "r"); + while ( fgets( line, sizeof(line), fp)) { + tst=QString::fromUtf8(line); + if (tst.startsWith("sec")) { + QStringList keyString=QStringList::split(":",tst,true); + QString val=keyString[6]; + QString id=QString("0x"+keyString[4].right(8)); + if (val.isEmpty()) + val=i18n("Unlimited"); + fullname=keyString[9]; + + fp2 = popen(QFile::encodeName(QString("gpg --no-tty --with-colons --list-key %1").arg(KShellProcess::quote(id))), "r"); + bool dead=true; + while ( fgets( line, sizeof(line), fp2)) { + tst2=QString::fromUtf8(line); + if (tst2.startsWith("pub")) { + const QString trust2=tst2.section(':',1,1); + switch( trust2[0] ) { + case 'f': + dead=false; + break; + case 'u': + dead=false; + break; + case '-': + if (tst2.section(':',11,11).find('D')==-1) warn=true; + break; + default: + break; + } + if (tst2.section(':',11,11).find('D')!=-1) + dead=true; + break; + } + } + pclose(fp2); + if (!fullname.isEmpty() && (!dead)) { + QString keyMail,keyName; + if (fullname.find("<")!=-1) { + keyMail=fullname.section('<',-1,-1); + keyMail.truncate(keyMail.length()-1); + keyName=fullname.section('<',0,0); + } else { + keyMail=QString::null; + keyName=fullname; + } + + keyName=KgpgInterface::checkForUtf8(keyName); + + + item=new KListViewItem(keysListpr,keyName,keyMail,id); + //KListViewItem *sub= new KListViewItem(item,i18n("ID: %1, trust: %2, expiration: %3").arg(id).arg(trust).arg(val)); + KListViewItem *sub= new KListViewItem(item,i18n("Expiration:"),val); + sub->setSelectable(false); + item->setPixmap(0,keyPair); + if (preselected.find(id,0,false)!=-1) { + keysListpr->setSelected(item,true); + keysListpr->setCurrentItem(item); + selectedok=true; + } + } + } + } + pclose(fp); + + if (warn) + { + KMessageBox::information(this,i18n("Some of your secret keys are untrusted.
Change their trust if you want to use them for signing.
"),QString::null,"warnUntrusted"); + } + QObject::connect(keysListpr,SIGNAL(doubleClicked(QListViewItem *,const QPoint &,int)),this,SLOT(slotpreOk())); + QObject::connect(keysListpr,SIGNAL(clicked(QListViewItem *)),this,SLOT(slotSelect(QListViewItem *))); + + + if (!selectedok) + { + keysListpr->setSelected(keysListpr->firstChild(),true); + keysListpr->setCurrentItem(keysListpr->firstChild()); + } + + vbox->addWidget(labeltxt); + vbox->addWidget(keysListpr); + setMainWidget(page); +} + + +void KgpgSelKey::slotpreOk() +{ + if (keysListpr->currentItem()->depth()!=0) + return; + else + slotOk(); +} + +void KgpgSelKey::slotOk() +{ + if (keysListpr->currentItem()==NULL) + reject(); + else + accept(); +} + +void KgpgSelKey::slotSelect(QListViewItem *item) +{ + if (item==NULL) + return; + if (item->depth()!=0) { + keysListpr->setSelected(item->parent(),true); + keysListpr->setCurrentItem(item->parent()); + } +} + + +QString KgpgSelKey::getkeyID() +{ + ///// emit selected key + if (keysListpr->currentItem()==NULL) + return(QString::null); + QString result; + QPtrList< QListViewItem > list = keysListpr->selectedItems(false); + QListViewItem *item; + for ( item = list.first(); item; item = list.next() ) + { + result.append(item->text(2)); + if (item!=list.getLast()) result.append(" "); + } + return(result); +} + +QString KgpgSelKey::getkeyMail() +{ + QString username; + ///// emit selected key + if (keysListpr->currentItem()==NULL) + return(QString::null); + else { + username=keysListpr->currentItem()->text(0); + //username=username.section(' ',0,0); + username=username.stripWhiteSpace(); + return(username); + } +} + + + +///////////////////////////////////////////////////////////////////////////////////////////// + +KeyView::KeyView( QWidget *parent, const char *name ) + : KListView( parent, name ) +{ + KIconLoader *loader = KGlobal::iconLoader(); + + pixkeyOrphan=loader->loadIcon("kgpg_key4",KIcon::Small,20); + pixkeyGroup=loader->loadIcon("kgpg_key3",KIcon::Small,20); + pixkeyPair=loader->loadIcon("kgpg_key2",KIcon::Small,20); + pixkeySingle=loader->loadIcon("kgpg_key1",KIcon::Small,20); + pixsignature=loader->loadIcon("signature",KIcon::Small,20); + pixuserid=loader->loadIcon("kgpg_identity",KIcon::Small,20); + pixuserphoto=loader->loadIcon("kgpg_photo",KIcon::Small,20); + pixRevoke=loader->loadIcon("stop",KIcon::Small,20); + QPixmap blankFrame; + blankFrame.load(locate("appdata", "pics/kgpg_blank.png")); + + trustunknown.load(locate("appdata", "pics/kgpg_fill.png")); + trustunknown.fill(KGpgSettings::colorUnknown()); + bitBlt(&trustunknown,0,0,&blankFrame,0,0,50,15); + + trustbad.load(locate("appdata", "pics/kgpg_fill.png")); + trustbad.fill(KGpgSettings::colorBad());//QColor(172,0,0)); + bitBlt(&trustbad,0,0,&blankFrame,0,0,50,15); + + trustrevoked.load(locate("appdata", "pics/kgpg_fill.png")); + trustrevoked.fill(KGpgSettings::colorRev());//QColor(30,30,30)); + bitBlt(&trustrevoked,0,0,&blankFrame,0,0,50,15); + + trustgood.load(locate("appdata", "pics/kgpg_fill.png")); + trustgood.fill(KGpgSettings::colorGood());//QColor(144,255,0)); + bitBlt(&trustgood,0,0,&blankFrame,0,0,50,15); + + connect(this,SIGNAL(expanded (QListViewItem *)),this,SLOT(expandKey(QListViewItem *))); + header()->setMovingEnabled(false); + setAcceptDrops(true); + setDragEnabled(true); +} + + + +void KeyView::droppedfile (KURL url) +{ + if (KMessageBox::questionYesNo(this,i18n("

Do you want to import file %1 into your key ring?

").arg(url.path()), QString::null, i18n("Import"), i18n("Do Not Import"))!=KMessageBox::Yes) + return; + + KgpgInterface *importKeyProcess=new KgpgInterface(); + importKeyProcess->importKeyURL(url); + connect(importKeyProcess,SIGNAL(importfinished(QStringList)),this,SLOT(slotReloadKeys(QStringList))); +} + +void KeyView::contentsDragMoveEvent(QDragMoveEvent *e) +{ + e->accept (KURLDrag::canDecode(e)); +} + +void KeyView::contentsDropEvent (QDropEvent *o) +{ + KURL::List list; + if ( KURLDrag::decode( o, list ) ) + droppedfile(list.first()); +} + +void KeyView::startDrag() +{ + FILE *fp; + char line[200]=""; + QString keyid=currentItem()->text(6); + if (!keyid.startsWith("0x")) + return; + QString gpgcmd="gpg --display-charset=utf-8 --no-tty --export --armor "+KShellProcess::quote(keyid.local8Bit()); + + QString keytxt; + fp=popen(QFile::encodeName(gpgcmd),"r"); + while ( fgets( line, sizeof(line), fp)) /// read output + if (!QString(line).startsWith("gpg:")) + keytxt+=QString::fromUtf8(line); + pclose(fp); + + QDragObject *d = new QTextDrag( keytxt, this ); + d->dragCopy(); + // do NOT delete d. +} + + +mySearchLine::mySearchLine(QWidget *parent, KeyView *listView, const char *name) +:KListViewSearchLine(parent,listView,name) +{ +searchListView=listView; +setKeepParentsVisible(false); +} + +mySearchLine::~ mySearchLine() +{} + + +bool mySearchLine::itemMatches(const QListViewItem *item, const QString & s) const +{ +if (item->depth()!=0) return true; +else return KListViewSearchLine::itemMatches(item,s); +} + + + +void mySearchLine::updateSearch(const QString& s) +{ + KListViewSearchLine::updateSearch(s); + if (searchListView->displayOnlySecret || !searchListView->displayDisabled) + { + int disabledSerial=searchListView->trustbad.serialNumber(); + QListViewItem *item=searchListView->firstChild(); + while (item) + { + if (item->isVisible() && !(item->text(6).isEmpty())) + { + if (searchListView->displayOnlySecret && searchListView->secretList.find(item->text(6))==-1) + item->setVisible(false); + if (!searchListView->displayDisabled && item->pixmap(2)) + if (item->pixmap(2)->serialNumber()==disabledSerial) + item->setVisible(false); + } + item=item->nextSibling(); + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////// main window for key management + +listKeys::listKeys(QWidget *parent, const char *name) : DCOPObject( "KeyInterface" ), KMainWindow(parent, name,0) +{ + //KWin::setType(Qt::WDestructiveClose); + + keysList2 = new KeyView(this); + keysList2->photoKeysList=QString::null; + keysList2->groupNb=0; + keyStatusBar=NULL; + readOptions(); + + if (showTipOfDay) + installEventFilter(this); + setCaption(i18n("Key Management")); + + (void) new KAction(i18n("&Open Editor"), "edit",0,this, SLOT(slotOpenEditor()),actionCollection(),"kgpg_editor"); + KAction *exportPublicKey = new KAction(i18n("E&xport Public Keys..."), "kgpg_export", KStdAccel::shortcut(KStdAccel::Copy),this, SLOT(slotexport()),actionCollection(),"key_export"); + KAction *deleteKey = new KAction(i18n("&Delete Keys"),"editdelete", Qt::Key_Delete,this, SLOT(confirmdeletekey()),actionCollection(),"key_delete"); + signKey = new KAction(i18n("&Sign Keys..."), "kgpg_sign", 0,this, SLOT(signkey()),actionCollection(),"key_sign"); + KAction *delSignKey = new KAction(i18n("Delete Sign&ature"),"editdelete", 0,this, SLOT(delsignkey()),actionCollection(),"key_delsign"); + KAction *infoKey = new KAction(i18n("&Edit Key"), "kgpg_info", Qt::Key_Return,this, SLOT(listsigns()),actionCollection(),"key_info"); + KAction *importKey = new KAction(i18n("&Import Key..."), "kgpg_import", KStdAccel::shortcut(KStdAccel::Paste),this, SLOT(slotPreImportKey()),actionCollection(),"key_import"); + KAction *setDefaultKey = new KAction(i18n("Set as De&fault Key"),0, 0,this, SLOT(slotSetDefKey()),actionCollection(),"key_default"); + importSignatureKey = new KAction(i18n("Import Key From Keyserver"),"network", 0,this, SLOT(preimportsignkey()),actionCollection(),"key_importsign"); + importAllSignKeys = new KAction(i18n("Import &Missing Signatures From Keyserver"),"network", 0,this, SLOT(importallsignkey()),actionCollection(),"key_importallsign"); + refreshKey = new KAction(i18n("&Refresh Keys From Keyserver"),"reload", 0,this, SLOT(refreshKeyFromServer()),actionCollection(),"key_server_refresh"); + + KAction *createGroup=new KAction(i18n("&Create Group with Selected Keys..."), 0, 0,this, SLOT(createNewGroup()),actionCollection(),"create_group"); + KAction *delGroup= new KAction(i18n("&Delete Group"), 0, 0,this, SLOT(deleteGroup()),actionCollection(),"delete_group"); + KAction *editCurrentGroup= new KAction(i18n("&Edit Group"), 0, 0,this, SLOT(editGroup()),actionCollection(),"edit_group"); + + KAction *newContact=new KAction(i18n("&Create New Contact in Address Book"), "kaddressbook", 0,this, SLOT(addToKAB()),actionCollection(),"add_kab"); + (void) new KAction(i18n("&Go to Default Key"), "gohome",QKeySequence(CTRL+Qt::Key_Home) ,this, SLOT(slotGotoDefaultKey()),actionCollection(),"go_default_key"); + + KStdAction::quit(this, SLOT(quitApp()), actionCollection()); + KStdAction::find(this, SLOT(findKey()), actionCollection()); + KStdAction::findNext(this, SLOT(findNextKey()), actionCollection()); + (void) new KAction(i18n("&Refresh List"), "reload", KStdAccel::reload(),this, SLOT(refreshkey()),actionCollection(),"key_refresh"); + KAction *openPhoto= new KAction(i18n("&Open Photo"), "image", 0,this, SLOT(slotShowPhoto()),actionCollection(),"key_photo"); + KAction *deletePhoto= new KAction(i18n("&Delete Photo"), "delete", 0,this, SLOT(slotDeletePhoto()),actionCollection(),"delete_photo"); + KAction *addPhoto= new KAction(i18n("&Add Photo"), 0, 0,this, SLOT(slotAddPhoto()),actionCollection(),"add_photo"); + + KAction *addUid= new KAction(i18n("&Add User Id"), 0, 0,this, SLOT(slotAddUid()),actionCollection(),"add_uid"); + KAction *delUid= new KAction(i18n("&Delete User Id"), 0, 0,this, SLOT(slotDelUid()),actionCollection(),"del_uid"); + + KAction *editKey = new KAction(i18n("Edit Key in &Terminal"), "kgpg_term", QKeySequence(ALT+Qt::Key_Return),this, SLOT(slotedit()),actionCollection(),"key_edit"); + KAction *exportSecretKey = new KAction(i18n("Export Secret Key..."), 0, 0,this, SLOT(slotexportsec()),actionCollection(),"key_sexport"); + KAction *revokeKey = new KAction(i18n("Revoke Key..."), 0, 0,this, SLOT(revokeWidget()),actionCollection(),"key_revoke"); + + KAction *deleteKeyPair = new KAction(i18n("Delete Key Pair"), 0, 0,this, SLOT(deleteseckey()),actionCollection(),"key_pdelete"); + KAction *generateKey = new KAction(i18n("&Generate Key Pair..."), "kgpg_gen", KStdAccel::shortcut(KStdAccel::New),this, SLOT(slotgenkey()),actionCollection(),"key_gener"); + + KAction *regeneratePublic = new KAction(i18n("&Regenerate Public Key"), 0, 0,this, SLOT(slotregenerate()),actionCollection(),"key_regener"); + + (void) new KAction(i18n("&Key Server Dialog"), "network", 0,this, SLOT(showKeyServer()),actionCollection(),"key_server"); + KStdAction::preferences(this, SLOT(showOptions()), actionCollection(),"options_configure"); + (void) new KAction(i18n("Tip of the &Day"), "idea", 0,this, SLOT(slotTip()), actionCollection(),"help_tipofday"); + (void) new KAction(i18n("View GnuPG Manual"), "contents", 0,this, SLOT(slotManpage()),actionCollection(),"gpg_man"); + + (void) new KToggleAction(i18n("&Show only Secret Keys"), "kgpg_show", 0,this, SLOT(slotToggleSecret()),actionCollection(),"show_secret"); + keysList2->displayOnlySecret=false; + + (void) new KToggleAction(i18n("&Hide Expired/Disabled Keys"),0, 0,this, SLOT(slotToggleDisabled()),actionCollection(),"hide_disabled"); + keysList2->displayDisabled=true; + + sTrust=new KToggleAction(i18n("Trust"),0, 0,this, SLOT(slotShowTrust()),actionCollection(),"show_trust"); + sSize=new KToggleAction(i18n("Size"),0, 0,this, SLOT(slotShowSize()),actionCollection(),"show_size"); + sCreat=new KToggleAction(i18n("Creation"),0, 0,this, SLOT(slotShowCreat()),actionCollection(),"show_creat"); + sExpi=new KToggleAction(i18n("Expiration"),0, 0,this, SLOT(slotShowExpi()),actionCollection(),"show_expi"); + + + photoProps = new KSelectAction(i18n("&Photo ID's"),"kgpg_photo", actionCollection(), "photo_settings"); + connect(photoProps, SIGNAL(activated(int)), this, SLOT(slotSetPhotoSize(int))); + + // Keep the list in kgpg.kcfg in sync with this one! + QStringList list; + list.append(i18n("Disable")); + list.append(i18n("Small")); + list.append(i18n("Medium")); + list.append(i18n("Large")); + photoProps->setItems(list); + + int pSize = KGpgSettings::photoProperties(); + photoProps->setCurrentItem( pSize ); + slotSetPhotoSize(pSize); + + keysList2->setRootIsDecorated(true); + keysList2->addColumn( i18n( "Name" ),200); + keysList2->addColumn( i18n( "Email" ),200); + keysList2->addColumn( i18n( "Trust" ),60); + keysList2->addColumn( i18n( "Expiration" ),100); + keysList2->addColumn( i18n( "Size" ),100); + keysList2->addColumn( i18n( "Creation" ),100); + keysList2->addColumn( i18n( "Id" ),100); + keysList2->setShowSortIndicator(true); + keysList2->setAllColumnsShowFocus(true); + keysList2->setFullWidth(true); + keysList2->setAcceptDrops (true) ; + keysList2->setSelectionModeExt(KListView::Extended); + + + popup=new QPopupMenu(); + exportPublicKey->plug(popup); + deleteKey->plug(popup); + signKey->plug(popup); + infoKey->plug(popup); + editKey->plug(popup); + refreshKey->plug(popup); + setDefaultKey->plug(popup); + popup->insertSeparator(); + importAllSignKeys->plug(popup); + + popupsec=new QPopupMenu(); + exportPublicKey->plug(popupsec); + signKey->plug(popupsec); + infoKey->plug(popupsec); + editKey->plug(popupsec); + refreshKey->plug(popupsec); + setDefaultKey->plug(popupsec); + popupsec->insertSeparator(); + importAllSignKeys->plug(popupsec); + popupsec->insertSeparator(); + addPhoto->plug(popupsec); + addUid->plug(popupsec); + exportSecretKey->plug(popupsec); + deleteKeyPair->plug(popupsec); + revokeKey->plug(popupsec); + + popupgroup=new QPopupMenu(); + editCurrentGroup->plug(popupgroup); + delGroup->plug(popupgroup); + + popupout=new QPopupMenu(); + importKey->plug(popupout); + generateKey->plug(popupout); + + popupsig=new QPopupMenu(); + importSignatureKey->plug(popupsig); + delSignKey->plug(popupsig); + + popupphoto=new QPopupMenu(); + openPhoto->plug(popupphoto); + deletePhoto->plug(popupphoto); + + popupuid=new QPopupMenu(); + delUid->plug(popupuid); + + popuporphan=new QPopupMenu(); + regeneratePublic->plug(popuporphan); + deleteKeyPair->plug(popuporphan); + + editCurrentGroup->setEnabled(false); + delGroup->setEnabled(false); + createGroup->setEnabled(false); + infoKey->setEnabled(false); + editKey->setEnabled(false); + signKey->setEnabled(false); + refreshKey->setEnabled(false); + exportPublicKey->setEnabled(false); + newContact->setEnabled(false); + + setCentralWidget(keysList2); + keysList2->restoreLayout(KGlobal::config(), "KeyView"); + + QObject::connect(keysList2,SIGNAL(returnPressed(QListViewItem *)),this,SLOT(listsigns())); + QObject::connect(keysList2,SIGNAL(doubleClicked(QListViewItem *,const QPoint &,int)),this,SLOT(listsigns())); + QObject::connect(keysList2,SIGNAL(selectionChanged ()),this,SLOT(checkList())); + QObject::connect(keysList2,SIGNAL(contextMenuRequested(QListViewItem *,const QPoint &,int)), + this,SLOT(slotmenu(QListViewItem *,const QPoint &,int))); + QObject::connect(keysList2,SIGNAL(destroyed()),this,SLOT(annule())); + + + /////////////// get all keys data + keyStatusBar=statusBar(); + + setupGUI(KMainWindow::Create | Save | ToolBar | StatusBar | Keys, "listkeys.rc"); + toolBar()->insertLineSeparator(); + + QToolButton *clearSearch = new QToolButton(toolBar()); + clearSearch->setTextLabel(i18n("Clear Search"), true); + clearSearch->setIconSet(SmallIconSet(QApplication::reverseLayout() ? "clear_left" + : "locationbar_erase")); + (void) new QLabel(i18n("Search: "),toolBar()); + listViewSearch = new mySearchLine(toolBar(),keysList2); + connect(clearSearch, SIGNAL(pressed()), listViewSearch, SLOT(clear())); + + + (void)new KAction(i18n("Filter Search"), Qt::Key_F6, listViewSearch, SLOT(setFocus()),actionCollection(), "search_focus"); + + sTrust->setChecked(KGpgSettings::showTrust()); + sSize->setChecked(KGpgSettings::showSize()); + sCreat->setChecked(KGpgSettings::showCreat()); + sExpi->setChecked(KGpgSettings::showExpi()); + + statusbarTimer = new QTimer(this); + + keyStatusBar->insertItem("",0,1); + keyStatusBar->insertFixedItem(i18n("00000 Keys, 000 Groups"),1,true); + keyStatusBar->setItemAlignment(0, AlignLeft); + keyStatusBar->changeItem("",1); + QObject::connect(keysList2,SIGNAL(statusMessage(QString,int,bool)),this,SLOT(changeMessage(QString,int,bool))); + QObject::connect(statusbarTimer,SIGNAL(timeout()),this,SLOT(statusBarTimeout())); + + s_kgpgEditor= new KgpgApp(parent, "editor",WType_Dialog,actionCollection()->action("go_default_key")->shortcut(),true); + connect(s_kgpgEditor,SIGNAL(refreshImported(QStringList)),keysList2,SLOT(slotReloadKeys(QStringList))); + connect(this,SIGNAL(fontChanged(QFont)),s_kgpgEditor,SLOT(slotSetFont(QFont))); + connect(s_kgpgEditor->view->editor,SIGNAL(refreshImported(QStringList)),keysList2,SLOT(slotReloadKeys(QStringList))); +} + + +listKeys::~listKeys() +{} + +void listKeys::showKeyManager() +{ +show(); +} + +void listKeys::slotOpenEditor() +{ + KgpgApp *kgpgtxtedit = new KgpgApp(this, "editor",WType_TopLevel | WDestructiveClose,actionCollection()->action("go_default_key")->shortcut()); + connect(kgpgtxtedit,SIGNAL(refreshImported(QStringList)),keysList2,SLOT(slotReloadKeys(QStringList))); + connect(kgpgtxtedit,SIGNAL(encryptFiles(KURL::List)),this,SIGNAL(encryptFiles(KURL::List))); + connect(this,SIGNAL(fontChanged(QFont)),kgpgtxtedit,SLOT(slotSetFont(QFont))); + connect(kgpgtxtedit->view->editor,SIGNAL(refreshImported(QStringList)),keysList2,SLOT(slotReloadKeys(QStringList))); + kgpgtxtedit->show(); +} + +void listKeys::statusBarTimeout() +{ + keyStatusBar->changeItem("",0); +} + +void listKeys::changeMessage(QString msg, int nb, bool keep) +{ + statusbarTimer->stop(); + if ((nb==0) & (!keep)) + statusbarTimer->start(10000, true); + keyStatusBar->changeItem(" "+msg+" ",nb); +} + + +void KeyView::slotRemoveColumn(int d) +{ + hideColumn(d); + header()->setResizeEnabled(false,d); + header()->setStretchEnabled(true,6); +} + +void KeyView::slotAddColumn(int c) +{ + header()->setResizeEnabled(true,c); + adjustColumn(c); +} + +void listKeys::slotShowTrust() +{ + if (sTrust->isChecked()) + keysList2->slotAddColumn(2); + else + keysList2->slotRemoveColumn(2); +} + +void listKeys::slotShowExpi() +{ + if (sExpi->isChecked()) + keysList2->slotAddColumn(3); + else + keysList2->slotRemoveColumn(3); +} + +void listKeys::slotShowSize() +{ + if (sSize->isChecked()) + keysList2->slotAddColumn(4); + else + keysList2->slotRemoveColumn(4); +} + +void listKeys::slotShowCreat() +{ + if (sCreat->isChecked()) + keysList2->slotAddColumn(5); + else + keysList2->slotRemoveColumn(5); +} + + +bool listKeys::eventFilter( QObject *, QEvent *e ) +{ + if ((e->type() == QEvent::Show) && (showTipOfDay)) { + KTipDialog::showTip(this, QString("kgpg/tips"), false); + showTipOfDay=false; + } + return FALSE; +} + + +void listKeys::slotToggleSecret() +{ + QListViewItem *item=keysList2->firstChild(); + if (!item) + return; + + keysList2->displayOnlySecret=!keysList2->displayOnlySecret; + listViewSearch->updateSearch(listViewSearch->text()); +} + +void listKeys::slotToggleDisabled() +{ + QListViewItem *item=keysList2->firstChild(); + if (!item) + return; + + keysList2->displayDisabled=!keysList2->displayDisabled; + listViewSearch->updateSearch(listViewSearch->text()); +} + +void listKeys::slotGotoDefaultKey() +{ + QListViewItem *myDefaulKey = keysList2->findItem(KGpgSettings::defaultKey(),6); + keysList2->clearSelection(); + keysList2->setCurrentItem(myDefaulKey); + keysList2->setSelected(myDefaulKey,true); + keysList2->ensureItemVisible(myDefaulKey); +} + + + +void listKeys::refreshKeyFromServer() +{ + if (keysList2->currentItem()==NULL) + return; + QString keyIDS; + keysList=keysList2->selectedItems(); + bool keyDepth=true; + for ( uint i = 0; i < keysList.count(); ++i ) + if ( keysList.at(i) ) { + if ((keysList.at(i)->depth()!=0) || (keysList.at(i)->text(6).isEmpty())) + keyDepth=false; + else + keyIDS+=keysList.at(i)->text(6)+" "; + } + if (!keyDepth) { + KMessageBox::sorry(this,i18n("You can only refresh primary keys. Please check your selection.")); + return; + } + kServer=new keyServer(0,"server_dialog",false); + kServer->page->kLEimportid->setText(keyIDS); + kServer->slotImport(); + connect( kServer, SIGNAL( importFinished(QString) ) , this, SLOT(refreshFinished())); +} + + +void listKeys::refreshFinished() +{ + if (kServer) + kServer=0L; + + for ( uint i = 0; i < keysList.count(); ++i ) + if (keysList.at(i)) + keysList2->refreshcurrentkey(keysList.at(i)); +} + + +void listKeys::slotDelUid() +{ + QListViewItem *item=keysList2->currentItem(); + while (item->depth()>0) + item=item->parent(); + + KProcess *conprocess=new KProcess(); + KConfig *config = KGlobal::config(); + config->setGroup("General"); + *conprocess<< config->readPathEntry("TerminalApplication","konsole"); + *conprocess<<"-e"<<"gpg"; + *conprocess<<"--edit-key"<text(6)<<"uid"; + conprocess->start(KProcess::Block); + keysList2->refreshselfkey(); +} + + +void listKeys::slotregenerate() +{ + FILE *fp; + QString tst; + char line[300]; + QString cmd="gpg --display-charset=utf-8 --no-secmem-warning --export-secret-key "+keysList2->currentItem()->text(6)+" | gpgsplit --no-split --secret-to-public | gpg --import"; + + fp = popen(QFile::encodeName(cmd), "r"); + while ( fgets( line, sizeof(line), fp)) { + tst+=QString::fromUtf8(line); + } + pclose(fp); + QString regID=keysList2->currentItem()->text(6); + keysList2->takeItem(keysList2->currentItem()); + keysList2->refreshcurrentkey(regID); +} + +void listKeys::slotAddUid() +{ + addUidWidget=new KDialogBase(KDialogBase::Swallow, i18n("Add New User Id"), KDialogBase::Ok | KDialogBase::Cancel,KDialogBase::Ok,this,0,true); + addUidWidget->enableButtonOK(false); + AddUid *keyUid=new AddUid(); + addUidWidget->setMainWidget(keyUid); + //keyUid->setMinimumSize(keyUid->sizeHint()); + keyUid->setMinimumWidth(300); + connect(keyUid->kLineEdit1,SIGNAL(textChanged ( const QString & )),this,SLOT(slotAddUidEnable(const QString & ))); + if (addUidWidget->exec()!=QDialog::Accepted) + return; + KgpgInterface *addUidProcess=new KgpgInterface(); + addUidProcess->KgpgAddUid(keysList2->currentItem()->text(6),keyUid->kLineEdit1->text(),keyUid->kLineEdit2->text(),keyUid->kLineEdit3->text()); + connect(addUidProcess,SIGNAL(addUidFinished()),keysList2,SLOT(refreshselfkey())); + connect(addUidProcess,SIGNAL(addUidError(QString)),this,SLOT(slotGpgError(QString))); +} + +void listKeys::slotAddUidEnable(const QString & name) +{ + addUidWidget->enableButtonOK(name.length()>4); +} + + +void listKeys::slotAddPhoto() +{ + QString mess=i18n("The image must be a JPEG file. Remember that the image is stored within your public key." + "If you use a very large picture, your key will become very large as well! Keeping the image " + "close to 240x288 is a good size to use."); + + if (KMessageBox::warningContinueCancel(this,mess)!=KMessageBox::Continue) + return; + + QString imagePath=KFileDialog::getOpenFileName (QString::null,"image/jpeg",this); + if (imagePath.isEmpty()) + return; + KgpgInterface *addPhotoProcess=new KgpgInterface(); + addPhotoProcess->KgpgAddPhoto(keysList2->currentItem()->text(6),imagePath); + connect(addPhotoProcess,SIGNAL(addPhotoFinished()),this,SLOT(slotUpdatePhoto())); + connect(addPhotoProcess,SIGNAL(addPhotoError(QString)),this,SLOT(slotGpgError(QString))); +} + +void listKeys::slotGpgError(QString errortxt) +{ + KMessageBox::detailedSorry(this,i18n("Something unexpected happened during the requested operation.\nPlease check details for full log output."),errortxt); +} + + +void listKeys::slotDeletePhoto() +{ + if (KMessageBox::warningContinueCancel(this,i18n("Are you sure you want to delete Photo id %1
from key %2 <%3> ?
").arg(keysList2->currentItem()->text(6)).arg(keysList2->currentItem()->parent()->text(0)).arg(keysList2->currentItem()->parent()->text(1)),i18n("Warning"),KGuiItem(i18n("Delete"),"editdelete"))!=KMessageBox::Continue) + return; + + KgpgInterface *delPhotoProcess=new KgpgInterface(); + delPhotoProcess->KgpgDeletePhoto(keysList2->currentItem()->parent()->text(6),keysList2->currentItem()->text(6)); + connect(delPhotoProcess,SIGNAL(delPhotoFinished()),this,SLOT(slotUpdatePhoto())); + connect(delPhotoProcess,SIGNAL(delPhotoError(QString)),this,SLOT(slotGpgError(QString))); +} + +void listKeys::slotUpdatePhoto() +{ + keysList2->refreshselfkey(); +} + + +void listKeys::slotSetPhotoSize(int size) +{ + switch( size) { + case 1: + showPhoto=true; + keysList2->previewSize=22; + break; + case 2: + showPhoto=true; + keysList2->previewSize=42; + break; + case 3: + showPhoto=true; + keysList2->previewSize=65; + break; + default: + showPhoto=false; + break; + } + keysList2->displayPhoto=showPhoto; + + ///////////////////////////// refresh keys with photo id + + QListViewItem *newdef = keysList2->firstChild(); + while (newdef) { + //if ((keysList2->photoKeysList.find(newdef->text(6))!=-1) && (newdef->childCount ()>0)) + if (newdef->childCount ()>0) { + bool hasphoto=false; + QListViewItem *newdefChild = newdef->firstChild(); + while (newdefChild) { + if (newdefChild->text(0)==i18n("Photo id")) { + hasphoto=true; + break; + } + newdefChild = newdefChild->nextSibling(); + } + if (hasphoto) { + while (newdef->firstChild()) + delete newdef->firstChild(); + keysList2->expandKey(newdef); + } + } + newdef = newdef->nextSibling(); + } +} + +void listKeys::findKey() +{ + KFindDialog fd(this,"find_dialog",0,""); + if ( fd.exec() != QDialog::Accepted ) + return; + searchString=fd.pattern(); + searchOptions=fd.options(); + findFirstKey(); +} + +void listKeys::findFirstKey() +{ + if (searchString.isEmpty()) + return; + bool foundItem=true; + QListViewItem *item=keysList2->firstChild(); + if (!item) + return; + QString searchText=item->text(0)+" "+item->text(1)+" "+item->text(6); + + + // + KFind *m_find = new KFind(searchString, searchOptions,this); + m_find->setData(searchText); + while (m_find->find()==KFind::NoMatch) { + if (!item->nextSibling()) { + foundItem=false; + break; + } else { + item = item->nextSibling(); + searchText=item->text(0)+" "+item->text(1)+" "+item->text(6); + m_find->setData(searchText); + } + } + delete m_find; + + if (foundItem) { + + keysList2->clearSelection(); + keysList2->setCurrentItem(item); + keysList2->setSelected(item,true); + keysList2->ensureItemVisible(item); + } else + KMessageBox::sorry(this,i18n("Search string '%1' not found.").arg(searchString)); +} + +void listKeys::findNextKey() +{ + //kdDebug(2100)<<"find next"<currentItem(); + if (!item) + return; + while(item->depth() > 0) + item = item->parent(); + item=item->nextSibling(); + QString searchText=item->text(0)+" "+item->text(1)+" "+item->text(6); + //kdDebug(2100)<<"Next string:"<setData(searchText); + while (m_find->find()==KFind::NoMatch) { + if (!item->nextSibling()) { + foundItem=false; + break; + } else { + item = item->nextSibling(); + searchText=item->text(0)+" "+item->text(1)+" "+item->text(6); + m_find->setData(searchText); + //kdDebug(2100)<<"Next string:"<clearSelection(); + keysList2->setCurrentItem(item); + keysList2->setSelected(item,true); + keysList2->ensureItemVisible(item); + } else + findFirstKey(); +} + + + + +void listKeys::addToKAB() +{ + KABC::Key key; + if (!keysList2->currentItem()) return; + //QString email=extractKeyMail(keysList2->currentItem()).stripWhiteSpace(); + QString email=keysList2->currentItem()->text(1); + + KABC::AddressBook *ab = KABC::StdAddressBook::self(); + if ( !ab->load() ) { + KMessageBox::sorry(this,i18n("Unable to contact the address book. Please check your installation.")); + return; + } + + KABC::Addressee::List addresseeList = ab->findByEmail(email); + kapp->startServiceByDesktopName( "kaddressbook" ); + DCOPRef call( "kaddressbook", "KAddressBookIface" ); + if( !addresseeList.isEmpty() ) { + call.send( "showContactEditor(QString)", addresseeList.first().uid() ); + } + else { + call.send( "addEmail(QString)", QString (keysList2->currentItem()->text(0))+" <"+email+">" ); + } +} + +/* +void listKeys::allToKAB() +{ + KABC::Key key; + QString email; + QStringList keylist; + KABC::Addressee a; + + KABC::AddressBook *ab = KABC::StdAddressBook::self(); + if ( !ab->load() ) { + KMessageBox::sorry(this,i18n("Unable to contact the address book. Please check your installation.")); + return; + } + + QListViewItem * myChild = keysList2->firstChild(); + while( myChild ) { + //email=extractKeyMail(myChild).stripWhiteSpace(); + email=myChild->text(1); + KABC::Addressee::List addressees = ab->findByEmail( email ); + if (addressees.count()==1) { + a=addressees.first(); + KgpgInterface *ks=new KgpgInterface(); + key.setTextData(ks->getKey(myChild->text(6),true)); + a.insertKey(key); + ab->insertAddressee(a); + keylist<text(6)+": "+email; + } + // doSomething( myChild ); + myChild = myChild->nextSibling(); + } + KABC::StdAddressBook::save(); + if (!keylist.isEmpty()) + KMessageBox::informationList(this,i18n("The following keys were exported to the address book:"),keylist); + else + KMessageBox::sorry(this,i18n("No entry matching your keys were found in the address book.")); +} +*/ + +void listKeys::slotManpage() +{ + kapp->startServiceByDesktopName("khelpcenter", QString("man:/gpg"), 0, 0, 0, "", true); +} + +void listKeys::slotTip() +{ + KTipDialog::showTip(this, QString("kgpg/tips"), true); +} + +void listKeys::closeEvent ( QCloseEvent * e ) +{ + //kapp->ref(); // prevent KMainWindow from closing the app + //KMainWindow::closeEvent( e ); + e->accept(); + // hide(); + // e->ignore(); +} + +void listKeys::showKeyServer() +{ + keyServer *ks=new keyServer(this); + connect(ks,SIGNAL( importFinished(QString) ) , keysList2, SLOT(refreshcurrentkey(QString))); + ks->exec(); + if (ks) + delete ks; + refreshkey(); +} + + +void listKeys::checkList() +{ + QPtrList exportList=keysList2->selectedItems(); + if (exportList.count()>1) + { + stateChanged("multi_selected"); + for ( uint i = 0; i < exportList.count(); ++i ) + { + if (exportList.at(i) && !(exportList.at(i)->isVisible())) + exportList.at(i)->setSelected(false); + } + } + else { + if (keysList2->currentItem()->text(6).isEmpty()) + stateChanged("group_selected"); + else + stateChanged("single_selected"); + + } + int serial=keysList2->currentItem()->pixmap(0)->serialNumber(); + if (serial==keysList2->pixkeySingle.serialNumber()) { + if (keysList2->currentItem()->depth()==0) + changeMessage(i18n("Public Key"),0); + else + changeMessage(i18n("Sub Key"),0); + } else if (serial==keysList2->pixkeyPair.serialNumber()) + changeMessage(i18n("Secret Key Pair"),0); + else if (serial==keysList2->pixkeyGroup.serialNumber()) + changeMessage(i18n("Key Group"),0); + else if (serial==keysList2->pixsignature.serialNumber()) + changeMessage(i18n("Signature"),0); + else if (serial==keysList2->pixuserid.serialNumber()) + changeMessage(i18n("User ID"),0); + else if (keysList2->currentItem()->text(0)==i18n("Photo id")) + changeMessage(i18n("Photo ID"),0); + else if (serial==keysList2->pixRevoke.serialNumber()) + changeMessage(i18n("Revocation Signature"),0); + else if (serial==keysList2->pixkeyOrphan.serialNumber()) + changeMessage(i18n("Orphaned Secret Key"),0); + +} + +void listKeys::annule() +{ + ///////// close window + close(); +} + +void listKeys::quitApp() +{ + ///////// close window + exit(1); +} + +void listKeys::readOptions() +{ + + clipboardMode=QClipboard::Clipboard; + if (KGpgSettings::useMouseSelection() && (kapp->clipboard()->supportsSelection())) + clipboardMode=QClipboard::Selection; + + /////// re-read groups in case the config file location was changed + QStringList groups=KgpgInterface::getGpgGroupNames(KGpgSettings::gpgConfigPath()); + KGpgSettings::setGroups(groups.join(",")); + keysList2->groupNb=groups.count(); + if (keyStatusBar) + changeMessage(i18n("%1 Keys, %2 Groups").arg(keysList2->childCount()-keysList2->groupNb).arg(keysList2->groupNb),1); + + showTipOfDay= KGpgSettings::showTipOfDay(); +} + + +void listKeys::showOptions() +{ + if (KConfigDialog::showDialog("settings")) + return; + kgpgOptions *optionsDialog=new kgpgOptions(this,"settings"); + connect(optionsDialog,SIGNAL(settingsUpdated()),this,SLOT(readAllOptions())); + connect(optionsDialog,SIGNAL(homeChanged()),this,SLOT(refreshkey())); + connect(optionsDialog,SIGNAL(reloadKeyList()),this,SLOT(refreshkey())); + connect(optionsDialog,SIGNAL(refreshTrust(int,QColor)),keysList2,SLOT(refreshTrust(int,QColor))); + connect(optionsDialog,SIGNAL(changeFont(QFont)),this,SIGNAL(fontChanged(QFont))); + connect(optionsDialog,SIGNAL(installShredder()),this,SIGNAL(installShredder())); + optionsDialog->exec(); + delete optionsDialog; +} + +void listKeys::readAllOptions() +{ + readOptions(); + emit readAgainOptions(); +} + +void listKeys::slotSetDefKey() +{ + slotSetDefaultKey(keysList2->currentItem()); +} + +void listKeys::slotSetDefaultKey(QString newID) +{ + QListViewItem *newdef = keysList2->findItem(newID,6); + if (newdef) + slotSetDefaultKey(newdef); +} + +void listKeys::slotSetDefaultKey(QListViewItem *newdef) +{ + //kdDebug(2100)<<"------------------start ------------"<pixmap(2)==NULL)) + return; + //kdDebug(2100)<text(6)<text(6)==KGpgSettings::defaultKey()) + return; + if (newdef->pixmap(2)->serialNumber()!=keysList2->trustgood.serialNumber()) { + KMessageBox::sorry(this,i18n("Sorry, this key is not valid for encryption or not trusted.")); + return; + } + + QListViewItem *olddef = keysList2->findItem(KGpgSettings::defaultKey(),6); + + KGpgSettings::setDefaultKey(newdef->text(6)); + KGpgSettings::writeConfig(); + if (olddef) + keysList2->refreshcurrentkey(olddef); + keysList2->refreshcurrentkey(newdef); + keysList2->ensureItemVisible(keysList2->currentItem()); +} + + + +void listKeys::slotmenu(QListViewItem *sel, const QPoint &pos, int ) +{ + //////////// popup a different menu depending on which key is selected + if (sel!=NULL) { + if (keysList2->selectedItems().count()>1) { + QPtrList exportList=keysList2->selectedItems(); + bool keyDepth=true; + for ( uint i = 0; i < exportList.count(); ++i ) + if ( exportList.at(i) ) + if (exportList.at(i)->depth()!=0) + keyDepth=false; + if (!keyDepth) { + signKey->setEnabled(false); + refreshKey->setEnabled(false); + popupout->exec(pos); + return; + } else { + signKey->setEnabled(true); + refreshKey->setEnabled(true); + } + } + + if (sel->depth()!=0) { + //kdDebug(2100)<text(0)<text(4)=="-") && (sel->text(6).startsWith("0x"))) { + if ((sel->text(2)=="-") || (sel->text(2)==i18n("Revoked"))) { + if ((sel->text(0).startsWith("[")) && (sel->text(0).endsWith("]"))) ////// ugly hack to detect unknown keys + importSignatureKey->setEnabled(true); + else + importSignatureKey->setEnabled(false); + popupsig->exec(pos); + return; + } + } else if (sel->text(0)==i18n("Photo id")) + popupphoto->exec(pos); + else if (sel->text(6)==("-")) + popupuid->exec(pos); + } else { + keysList2->setSelected(sel,TRUE); + if (keysList2->currentItem()->text(6).isEmpty()) + popupgroup->exec(pos); + else { + if ((keysList2->secretList.find(sel->text(6))!=-1) && (keysList2->selectedItems().count()==1)) + popupsec->exec(pos); + else + if ((keysList2->orphanList.find(sel->text(6))!=-1) && (keysList2->selectedItems().count()==1)) + popuporphan->exec(pos); + else + popup->exec(pos); + } + return; + } + } else + popupout->exec(pos); +} + + + +void listKeys::slotrevoke(QString keyID,QString revokeUrl,int reason,QString description) +{ + revKeyProcess=new KgpgInterface(); + revKeyProcess->KgpgRevokeKey(keyID,revokeUrl,reason,description); +} + + +void listKeys::revokeWidget() +{ + KDialogBase *keyRevokeWidget=new KDialogBase(KDialogBase::Swallow, i18n("Create Revocation Certificate"), KDialogBase::Ok | KDialogBase::Cancel,KDialogBase::Ok,this,0,true); + + KgpgRevokeWidget *keyRevoke=new KgpgRevokeWidget(); + + keyRevoke->keyID->setText(keysList2->currentItem()->text(0)+" ("+keysList2->currentItem()->text(1)+") "+i18n("ID: ")+keysList2->currentItem()->text(6)); + keyRevoke->kURLRequester1->setURL(QDir::homeDirPath()+"/"+keysList2->currentItem()->text(1).section('@',0,0)+".revoke"); + keyRevoke->kURLRequester1->setMode(KFile::File); + + keyRevoke->setMinimumSize(keyRevoke->sizeHint()); + keyRevoke->show(); + keyRevokeWidget->setMainWidget(keyRevoke); + + if (keyRevokeWidget->exec()!=QDialog::Accepted) + return; + if (keyRevoke->cbSave->isChecked()) { + slotrevoke(keysList2->currentItem()->text(6),keyRevoke->kURLRequester1->url(),keyRevoke->comboBox1->currentItem(),keyRevoke->textDescription->text()); + if (keyRevoke->cbPrint->isChecked()) + connect(revKeyProcess,SIGNAL(revokeurl(QString)),this,SLOT(doFilePrint(QString))); + if (keyRevoke->cbImport->isChecked()) + connect(revKeyProcess,SIGNAL(revokeurl(QString)),this,SLOT(slotImportRevoke(QString))); + } else { + slotrevoke(keysList2->currentItem()->text(6),QString::null,keyRevoke->comboBox1->currentItem(),keyRevoke->textDescription->text()); + if (keyRevoke->cbPrint->isChecked()) + connect(revKeyProcess,SIGNAL(revokecertificate(QString)),this,SLOT(doPrint(QString))); + if (keyRevoke->cbImport->isChecked()) + connect(revKeyProcess,SIGNAL(revokecertificate(QString)),this,SLOT(slotImportRevokeTxt(QString))); + } +} + + +void listKeys::slotImportRevoke(QString url) +{ + KgpgInterface *importKeyProcess=new KgpgInterface(); + importKeyProcess->importKeyURL(KURL::fromPathOrURL( url )); + connect(importKeyProcess,SIGNAL(importfinished(QStringList)),keysList2,SLOT(refreshselfkey())); +} + +void listKeys::slotImportRevokeTxt(QString revokeText) +{ + KgpgInterface *importKeyProcess=new KgpgInterface(); + importKeyProcess->importKey(revokeText); + connect(importKeyProcess,SIGNAL(importfinished(QStringList)),keysList2,SLOT(refreshselfkey())); +} + +void listKeys::slotexportsec() +{ + ////////////////////// export secret key + QString warn=i18n("Secret keys SHOULD NOT be saved in an unsafe place.\n" + "If someone else can access this file, encryption with this key will be compromised!\nContinue key export?"); + int result=KMessageBox::questionYesNo(this,warn,i18n("Warning"), i18n("Export"), i18n("Do Not Export")); + if (result!=KMessageBox::Yes) + return; + + QString sname=keysList2->currentItem()->text(1).section('@',0,0); + sname=sname.section('.',0,0); + if (sname.isEmpty()) + sname=keysList2->currentItem()->text(0).section(' ',0,0); + sname.append(".asc"); + sname.prepend(QDir::homeDirPath()+"/"); + KURL url=KFileDialog::getSaveURL(sname,"*.asc|*.asc Files", this, i18n("Export PRIVATE KEY As")); + + if(!url.isEmpty()) { + QFile fgpg(url.path()); + if (fgpg.exists()) + fgpg.remove(); + + KProcIO *p=new KProcIO(QTextCodec::codecForLocale()); + *p<<"gpg"<<"--no-tty"<<"--output"<currentItem()->text(6); + p->start(KProcess::Block); + + if (fgpg.exists()) + KMessageBox::information(this,i18n("Your PRIVATE key \"%1\" was successfully exported.\nDO NOT leave it in an insecure place.").arg(url.path())); + else + KMessageBox::sorry(this,i18n("Your secret key could not be exported.\nCheck the key.")); + } + +} + + +void listKeys::slotexport() +{ + ///////////////////// export key + if (keysList2->currentItem()==NULL) + return; + if (keysList2->currentItem()->depth()!=0) + return; + + + QPtrList exportList=keysList2->selectedItems(); + if (exportList.count()==0) + return; + + QString sname; + + if (exportList.count()==1) { + sname=keysList2->currentItem()->text(1).section('@',0,0); + sname=sname.section('.',0,0); + if (sname.isEmpty()) + sname=keysList2->currentItem()->text(0).section(' ',0,0); + } else + sname="keyring"; + sname.append(".asc"); + sname.prepend(QDir::homeDirPath()+"/"); + + KDialogBase *dial=new KDialogBase( KDialogBase::Swallow, i18n("Public Key Export"), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, this, "key_export",true); + + KeyExport *page=new KeyExport(); + dial->setMainWidget(page); + page->newFilename->setURL(sname); + page->newFilename->setCaption(i18n("Save File")); + page->newFilename->setMode(KFile::File); + page->show(); + + if (dial->exec()==QDialog::Accepted) { + ////////////////////////// export to file + QString expname; + bool exportAttr=page->exportAttributes->isChecked(); + if (page->checkServer->isChecked()) { + keyServer *expServer=new keyServer(0,"server_export",false); + expServer->page->exportAttributes->setChecked(exportAttr); + QStringList exportKeysList; + for ( uint i = 0; i < exportList.count(); ++i ) + if ( exportList.at(i) ) + exportKeysList << exportList.at(i)->text(6).stripWhiteSpace(); + expServer->slotExport(exportKeysList); + return; + } + KProcIO *p=new KProcIO(QTextCodec::codecForLocale()); + *p<<"gpg"<<"--no-tty"; + if (page->checkFile->isChecked()) { + expname=page->newFilename->url().stripWhiteSpace(); + if (!expname.isEmpty()) { + QFile fgpg(expname); + if (fgpg.exists()) + fgpg.remove(); + *p<<"--output"<text(6)).stripWhiteSpace(); + + + p->start(KProcess::Block); + if (fgpg.exists()) + KMessageBox::information(this,i18n("Your public key \"%1\" was successfully exported\n").arg(expname)); + else + KMessageBox::sorry(this,i18n("Your public key could not be exported\nCheck the key.")); + } + } else { + + QStringList klist; + + for ( uint i = 0; i < exportList.count(); ++i ) + if ( exportList.at(i) ) + klist.append(exportList.at(i)->text(6).stripWhiteSpace()); + + KgpgInterface *kexp=new KgpgInterface(); + + QString result=kexp->getKey(klist,exportAttr); + if (page->checkClipboard->isChecked()) + slotProcessExportClip(result); + //connect(kexp,SIGNAL(publicKeyString(QString)),this,SLOT(slotProcessExportClip(QString))); + else + slotProcessExportMail(result); + //connect(kexp,SIGNAL(publicKeyString(QString)),this,SLOT(slotProcessExportMail(QString))); + + } + } + delete dial; +} + + + +void listKeys::slotProcessExportMail(QString keys) +{ + /// start default Mail application + kapp->invokeMailer(QString::null, QString::null, QString::null, QString::null, + keys, //body + QString::null, + QString::null); // attachments +} + +void listKeys::slotProcessExportClip(QString keys) +{ + kapp->clipboard()->setText(keys,clipboardMode); +} + + +void listKeys::showKeyInfo(QString keyID) +{ + KgpgKeyInfo *opts=new KgpgKeyInfo(this,"key_props",keyID); + opts->show(); +} + + +void listKeys::slotShowPhoto() +{ + KTrader::OfferList offers = KTrader::self()->query("image/jpeg", "Type == 'Application'"); + KService::Ptr ptr = offers.first(); + //KMessageBox::sorry(0,ptr->desktopEntryName()); + KProcIO *p=new KProcIO(QTextCodec::codecForLocale()); + *p<<"gpg"<<"--no-tty"<<"--photo-viewer"<desktopEntryName()+" %i")<<"--edit-key"<currentItem()->parent()->text(6)<<"uid"<currentItem()->text(6)<<"showphoto"<<"quit"; + p->start(KProcess::DontCare,true); +} + +void listKeys::listsigns() +{ + //kdDebug(2100)<<"Edit -------------------------------"<currentItem()==NULL) + return; + if (keysList2->currentItem()->depth()!=0) { + if (keysList2->currentItem()->text(0)==i18n("Photo id")) { + ////////////////////////// display photo + slotShowPhoto(); + } + return; + } + + if (keysList2->currentItem()->pixmap(0)->serialNumber()==keysList2->pixkeyOrphan.serialNumber()) { + if (KMessageBox::questionYesNo(this,i18n("This key is an orphaned secret key (secret key without public key.) It is currently not usable.\n\n" + "Would you like to regenerate the public key?"), QString::null, i18n("Generate"), i18n("Do Not Generate"))==KMessageBox::Yes) + slotregenerate(); + return; + } + + ///////////// open a key info dialog (KgpgKeyInfo, see begining of this file) + QString key=keysList2->currentItem()->text(6); + if (!key.isEmpty()) { + KgpgKeyInfo *opts=new KgpgKeyInfo(this,"key_props",key); + connect(opts,SIGNAL(keyNeedsRefresh()),keysList2,SLOT(refreshselfkey())); + opts->exec(); + } else + editGroup(); +} + +void listKeys::groupAdd() +{ + QPtrList addList=gEdit->availableKeys->selectedItems(); + for ( uint i = 0; i < addList.count(); ++i ) + if ( addList.at(i) ) { + gEdit->groupKeys->insertItem(addList.at(i)); + } +} + +void listKeys::groupRemove() +{ + QPtrList remList=gEdit->groupKeys->selectedItems(); + for ( uint i = 0; i < remList.count(); ++i ) + if ( remList.at(i) ) { + gEdit->availableKeys->insertItem(remList.at(i)); + } +} + +void listKeys::deleteGroup() +{ + if (!keysList2->currentItem() || !keysList2->currentItem()->text(6).isEmpty()) + return; + + int result=KMessageBox::warningContinueCancel(this,i18n("Are you sure you want to delete group %1 ?").arg(keysList2->currentItem()->text(0)),i18n("Warning"),KGuiItem(i18n("Delete"),"editdelete")); + if (result!=KMessageBox::Continue) + return; + KgpgInterface::delGpgGroup(keysList2->currentItem()->text(0), KGpgSettings::gpgConfigPath()); + QListViewItem *item=keysList2->currentItem()->nextSibling(); + delete keysList2->currentItem(); + if (!item) + item=keysList2->lastChild(); + keysList2->setCurrentItem(item); + keysList2->setSelected(item,true); + + QStringList groups=KgpgInterface::getGpgGroupNames(KGpgSettings::gpgConfigPath()); + KGpgSettings::setGroups(groups.join(",")); + keysList2->groupNb=groups.count(); + changeMessage(i18n("%1 Keys, %2 Groups").arg(keysList2->childCount()-keysList2->groupNb).arg(keysList2->groupNb),1); +} + +void listKeys::groupChange() +{ + QStringList selected; + QListViewItem *item=gEdit->groupKeys->firstChild(); + while (item) { + selected+=item->text(2); + item=item->nextSibling(); + } + KgpgInterface::setGpgGroupSetting(keysList2->currentItem()->text(0),selected,KGpgSettings::gpgConfigPath()); +} + +void listKeys::createNewGroup() +{ + QStringList badkeys,keysGroup; + + if (keysList2->selectedItems().count()>0) { + QPtrList groupList=keysList2->selectedItems(); + bool keyDepth=true; + for ( uint i = 0; i < groupList.count(); ++i ) + if ( groupList.at(i) ) { + if (groupList.at(i)->depth()!=0) + keyDepth=false; + else if (groupList.at(i)->text(6).isEmpty()) + keyDepth=false; + else if (groupList.at(i)->pixmap(2)) { + if (groupList.at(i)->pixmap(2)->serialNumber()==keysList2->trustgood.serialNumber()) + keysGroup+=groupList.at(i)->text(6); + else + badkeys+=groupList.at(i)->text(0)+" ("+groupList.at(i)->text(1)+") "+groupList.at(i)->text(6); + } + + } + if (!keyDepth) { + KMessageBox::sorry(this,i18n("You cannot create a group containing signatures, subkeys or other groups.")); + return; + } + QString groupName=KInputDialog::getText(i18n("Create New Group"),i18n("Enter new group name:"),QString::null,0,this); + if (groupName.isEmpty()) + return; + if (!keysGroup.isEmpty()) { + if (!badkeys.isEmpty()) + KMessageBox::informationList(this,i18n("Following keys are not valid or not trusted and will not be added to the group:"),badkeys); + KgpgInterface::setGpgGroupSetting(groupName,keysGroup,KGpgSettings::gpgConfigPath()); + QStringList groups=KgpgInterface::getGpgGroupNames(KGpgSettings::gpgConfigPath()); + KGpgSettings::setGroups(groups.join(",")); + keysList2->refreshgroups(); + QListViewItem *newgrp = keysList2->findItem(groupName,0); + + keysList2->clearSelection(); + keysList2->setCurrentItem(newgrp); + keysList2->setSelected(newgrp,true); + keysList2->ensureItemVisible(newgrp); + keysList2->groupNb=groups.count(); + changeMessage(i18n("%1 Keys, %2 Groups").arg(keysList2->childCount()-keysList2->groupNb).arg(keysList2->groupNb),1); + } else + KMessageBox::sorry(this,i18n("No valid or trusted key was selected. The group %1 will not be created.").arg(groupName)); + } +} + +void listKeys::groupInit(QStringList keysGroup) +{ + kdDebug(2100)<<"preparing group"<availableKeys->firstChild(); + foundId=false; + while (item) { + kdDebug(2100)<<"Searching in key: "<text(0)<text(2).right(8).lower()) { + gEdit->groupKeys->insertItem(item); + foundId=true; + break; + } + item=item->nextSibling(); + } + if (!foundId) + lostKeys+=QString(*it); + } + if (!lostKeys.isEmpty()) + KMessageBox::informationList(this,i18n("Following keys are in the group but are not valid or not in your keyring. They will be removed from the group."),lostKeys); +} + +void listKeys::editGroup() +{ + if (!keysList2->currentItem() || !keysList2->currentItem()->text(6).isEmpty()) + return; + QStringList keysGroup; + //KDialogBase *dialogGroupEdit=new KDialogBase( this, "edit_group", true,i18n("Group Properties"),KDialogBase::Ok | KDialogBase::Cancel); + KDialogBase *dialogGroupEdit=new KDialogBase(KDialogBase::Swallow, i18n("Group Properties"), KDialogBase::Ok | KDialogBase::Cancel,KDialogBase::Ok,this,0,true); + + gEdit=new groupEdit(); + gEdit->buttonAdd->setPixmap(KGlobal::iconLoader()->loadIcon("down",KIcon::Small,20)); + gEdit->buttonRemove->setPixmap(KGlobal::iconLoader()->loadIcon("up",KIcon::Small,20)); + + connect(gEdit->buttonAdd,SIGNAL(clicked()),this,SLOT(groupAdd())); + connect(gEdit->buttonRemove,SIGNAL(clicked()),this,SLOT(groupRemove())); + // connect(dialogGroupEdit->okClicked(),SIGNAL(clicked()),this,SLOT(groupChange())); + connect(gEdit->availableKeys,SIGNAL(doubleClicked (QListViewItem *, const QPoint &, int)),this,SLOT(groupAdd())); + connect(gEdit->groupKeys,SIGNAL(doubleClicked (QListViewItem *, const QPoint &, int)),this,SLOT(groupRemove())); + QListViewItem *item=keysList2->firstChild(); + if (item==NULL) + return; + if (item->pixmap(2)) { + if (item->pixmap(2)->serialNumber()==keysList2->trustgood.serialNumber()) + (void) new KListViewItem(gEdit->availableKeys,item->text(0),item->text(1),item->text(6)); + } + while (item->nextSibling()) { + item=item->nextSibling(); + if (item->pixmap(2)) { + if (item->pixmap(2)->serialNumber()==keysList2->trustgood.serialNumber()) + (void) new KListViewItem(gEdit->availableKeys,item->text(0),item->text(1),item->text(6)); + } + } + keysGroup=KgpgInterface::getGpgGroupSetting(keysList2->currentItem()->text(0),KGpgSettings::gpgConfigPath()); + groupInit(keysGroup); + dialogGroupEdit->setMainWidget(gEdit); + gEdit->availableKeys->setColumnWidth(0,200); + gEdit->availableKeys->setColumnWidth(1,200); + gEdit->availableKeys->setColumnWidth(2,100); + gEdit->availableKeys->setColumnWidthMode(0,QListView::Manual); + gEdit->availableKeys->setColumnWidthMode(1,QListView::Manual); + gEdit->availableKeys->setColumnWidthMode(2,QListView::Manual); + + gEdit->groupKeys->setColumnWidth(0,200); + gEdit->groupKeys->setColumnWidth(1,200); + gEdit->groupKeys->setColumnWidth(2,100); + gEdit->groupKeys->setColumnWidthMode(0,QListView::Manual); + gEdit->groupKeys->setColumnWidthMode(1,QListView::Manual); + gEdit->groupKeys->setColumnWidthMode(2,QListView::Manual); + + gEdit->setMinimumSize(gEdit->sizeHint()); + gEdit->show(); + if (dialogGroupEdit->exec()==QDialog::Accepted) + groupChange(); + delete dialogGroupEdit; +} + +void listKeys::signkey() +{ + /////////////// sign a key + if (keysList2->currentItem()==NULL) + return; + if (keysList2->currentItem()->depth()!=0) + return; + + signList=keysList2->selectedItems(); + bool keyDepth=true; + for ( uint i = 0; i < signList.count(); ++i ) + if ( signList.at(i) ) + if (signList.at(i)->depth()!=0) + keyDepth=false; + if (!keyDepth) { + KMessageBox::sorry(this,i18n("You can only sign primary keys. Please check your selection.")); + return; + } + + + if (signList.count()==1) { + FILE *pass; + char line[200]=""; + QString opt,fingervalue; + QString gpgcmd="gpg --no-tty --no-secmem-warning --with-colons --fingerprint "+KShellProcess::quote(keysList2->currentItem()->text(6)); + pass=popen(QFile::encodeName(gpgcmd),"r"); + while ( fgets( line, sizeof(line), pass)) { + opt=QString::fromUtf8(line); + if (opt.startsWith("fpr")) { + fingervalue=opt.section(':',9,9); + // format fingervalue in 4-digit groups + uint len = fingervalue.length(); + if ((len > 0) && (len % 4 == 0)) + for (uint n = 0; 4*(n+1) < len; n++) + fingervalue.insert(5*n+4, ' '); + } + } + pclose(pass); + opt= i18n("You are about to sign key:

%1
ID: %2
Fingerprint:
%3.

" + "You should check the key fingerprint by phoning or meeting the key owner to be sure that someone " + "is not trying to intercept your communications
").arg(keysList2->currentItem()->text(0)+" ("+keysList2->currentItem()->text(1)+")").arg(keysList2->currentItem()->text(6)).arg(fingervalue); + + if (KMessageBox::warningContinueCancel(this,opt)!=KMessageBox::Continue) + return; + + } else { + QStringList signKeyList; + for ( uint i = 0; i < signList.count(); ++i ) + if ( signList.at(i) ) + signKeyList+=signList.at(i)->text(0)+" ("+signList.at(i)->text(1)+")"+": "+signList.at(i)->text(6); + if (KMessageBox::warningContinueCancelList(this,i18n("You are about to sign the following keys in one pass.
If you have not carefully checked all fingerprints, the security of your communications may be compromised.
"),signKeyList)!=KMessageBox::Continue) + return; + } + + + ////////////////// open a secret key selection dialog (KgpgSelKey, see begining of this file) + KgpgSelKey *opts=new KgpgSelKey(this); + + QLabel *signCheck = new QLabel(""+i18n("How carefully have you checked that the key really " + "belongs to the person with whom you wish to communicate:", + "How carefully have you checked that the %n keys really " + "belong to the people with whom you wish to communicate:",signList.count()),opts->page); + opts->vbox->addWidget(signCheck); + QComboBox *signTrust=new QComboBox(opts->page); + signTrust->insertItem(i18n("I Will Not Answer")); + signTrust->insertItem(i18n("I Have Not Checked at All")); + signTrust->insertItem(i18n("I Have Done Casual Checking")); + signTrust->insertItem(i18n("I Have Done Very Careful Checking")); + opts->vbox->addWidget(signTrust); + + QCheckBox *localSign = new QCheckBox(i18n("Local signature (cannot be exported)"),opts->page); + opts->vbox->addWidget(localSign); + + QCheckBox *terminalSign = new QCheckBox(i18n("Do not sign all user id's (open terminal)"),opts->page); + opts->vbox->addWidget(terminalSign); + if (signList.count()!=1) + terminalSign->setEnabled(false); + + opts->setMinimumHeight(300); + + if (opts->exec()!=QDialog::Accepted) { + delete opts; + return; + } + + globalkeyID=QString(opts->getkeyID()); + globalkeyMail=QString(opts->getkeyMail()); + globalisLocal=localSign->isChecked(); + globalChecked=signTrust->currentItem(); + keyCount=0; + delete opts; + globalCount=signList.count(); + if (!terminalSign->isChecked()) + signLoop(); + else { + KProcess kp; + + KConfig *config = KGlobal::config(); + config->setGroup("General"); + kp<< config->readPathEntry("TerminalApplication","konsole"); + kp<<"-e" + <<"gpg" + <<"--no-secmem-warning" + <<"-u" + <text(6); + if (globalisLocal) + kp<<"lsign"; + else + kp<<"sign"; + kp.start(KProcess::Block); + keysList2->refreshcurrentkey(keysList2->currentItem()); + } +} + +void listKeys::signLoop() +{ + if (keyCountKgpgSignKey(signList.at(keyCount)->text(6),globalkeyID,globalkeyMail,globalisLocal,globalChecked); + } + } +} + +void listKeys::signatureResult(int success) +{ + if (success==3) + keysList2->refreshcurrentkey(signList.at(keyCount)); + + else if (success==2) + KMessageBox::sorry(this,i18n("Bad passphrase, key %1 not signed.").arg(signList.at(keyCount)->text(0)+i18n(" (")+signList.at(keyCount)->text(1)+i18n(")"))); + + keyCount++; + signLoop(); +} + + +void listKeys::importallsignkey() +{ + if (keysList2->currentItem()==NULL) + return; + if (! keysList2->currentItem()->firstChild()) { + keysList2->currentItem()->setOpen(true); + keysList2->currentItem()->setOpen(false); + } + QString missingKeysList; + QListViewItem *current = keysList2->currentItem()->firstChild(); + while (current) { + if ((current->text(0).startsWith("[")) && (current->text(0).endsWith("]"))) ////// ugly hack to detect unknown keys + missingKeysList+=current->text(6)+" "; + current = current->nextSibling(); + } + if (!missingKeysList.isEmpty()) + importsignkey(missingKeysList); + else + KMessageBox::information(this,i18n("All signatures for this key are already in your keyring")); +} + + +void listKeys::preimportsignkey() +{ + if (keysList2->currentItem()==NULL) + return; + else + importsignkey(keysList2->currentItem()->text(6)); +} + +bool listKeys::importRemoteKey(QString keyID) +{ + + kServer=new keyServer(0,"server_dialog",false,true); + kServer->page->kLEimportid->setText(keyID); + kServer->page->Buttonimport->setDefault(true); + kServer->page->tabWidget2->setTabEnabled(kServer->page->tabWidget2->page(1),false); + kServer->show(); + kServer->raise(); + connect( kServer, SIGNAL( importFinished(QString) ) , this, SLOT( dcopImportFinished())); + + return true; +} + + + +void listKeys::dcopImportFinished() +{ + if (kServer) + kServer=0L; + QByteArray params; + QDataStream stream(params, IO_WriteOnly); + stream << true; + kapp->dcopClient()->emitDCOPSignal("keyImported(bool)", params); + refreshkey(); +} + +void listKeys::importsignkey(QString importKeyId) +{ + /////////////// sign a key + kServer=new keyServer(0,"server_dialog",false); + kServer->page->kLEimportid->setText(importKeyId); + //kServer->Buttonimport->setDefault(true); + kServer->slotImport(); + //kServer->show(); + connect( kServer, SIGNAL( importFinished(QString) ) , this, SLOT( importfinished())); +} + + +void listKeys::importfinished() +{ + if (kServer) + kServer=0L; + refreshkey(); +} + + +void listKeys::delsignkey() +{ + /////////////// sign a key + if (keysList2->currentItem()==NULL) + return; + if (keysList2->currentItem()->depth()>1) { + KMessageBox::sorry(this,i18n("Edit key manually to delete this signature.")); + return; + } + + QString signID,parentKey,signMail,parentMail; + + ////////////////// open a key selection dialog (KgpgSelKey, see begining of this file) + parentKey=keysList2->currentItem()->parent()->text(6); + signID=keysList2->currentItem()->text(6); + parentMail=keysList2->currentItem()->parent()->text(0)+" ("+keysList2->currentItem()->parent()->text(1)+")"; + signMail=keysList2->currentItem()->text(0)+" ("+keysList2->currentItem()->text(1)+")"; + + if (parentKey==signID) { + KMessageBox::sorry(this,i18n("Edit key manually to delete a self-signature.")); + return; + } + QString ask=i18n("Are you sure you want to delete signature
%1 from key:
%2?
").arg(signMail).arg(parentMail); + + if (KMessageBox::questionYesNo(this,ask,QString::null,KStdGuiItem::del(),KStdGuiItem::cancel())!=KMessageBox::Yes) + return; + KgpgInterface *delSignKeyProcess=new KgpgInterface(); + delSignKeyProcess->KgpgDelSignature(parentKey,signID); + connect(delSignKeyProcess,SIGNAL(delsigfinished(bool)),this,SLOT(delsignatureResult(bool))); +} + +void listKeys::delsignatureResult(bool success) +{ + if (success) { + QListViewItem *top=keysList2->currentItem(); + while (top->depth()!=0) + top=top->parent(); + while (top->firstChild()!=0) + delete top->firstChild(); + keysList2->refreshcurrentkey(top); + } else + KMessageBox::sorry(this,i18n("Requested operation was unsuccessful, please edit the key manually.")); +} + +void listKeys::slotedit() +{ + if (!keysList2->currentItem()) + return; + if (keysList2->currentItem()->depth()!=0) + return; + if (keysList2->currentItem()->text(6).isEmpty()) + return; + + KProcess kp; + + KConfig *config = KGlobal::config(); + config->setGroup("General"); + kp<< config->readPathEntry("TerminalApplication","konsole"); + kp<<"-e" + <<"gpg" + <<"--no-secmem-warning" + <<"--utf8-strings" + <<"--edit-key" + <currentItem()->text(6) + <<"help"; + kp.start(KProcess::Block); + keysList2->refreshcurrentkey(keysList2->currentItem()); +} + + +void listKeys::slotgenkey() +{ + ////////// generate key + keyGenerate *genkey=new keyGenerate(this,0); + if (genkey->exec()==QDialog::Accepted) { + if (!genkey->getmode()) /// normal mode + { + //// extract data + QString ktype=genkey->getkeytype(); + QString ksize=genkey->getkeysize(); + int kexp=genkey->getkeyexp(); + QString knumb=genkey->getkeynumb(); + newKeyName=genkey->getkeyname(); + newKeyMail=genkey->getkeymail(); + QString kcomment=genkey->getkeycomm(); + delete genkey; + + //genkey->delayedDestruct(); + QCString password; + bool goodpass=false; + while (!goodpass) + { + int code=KPasswordDialog::getNewPassword(password,i18n("Enter passphrase for %1:
Passphrase should include non alphanumeric characters and random sequences").arg(newKeyName+" <"+newKeyMail+">")); + if (code!=QDialog::Accepted) + return; + if (password.length()<5) + KMessageBox::sorry(this,i18n("This passphrase is not secure enough.\nMinimum length= 5 characters")); + else + goodpass=true; + } + + pop = new KPassivePopup((QWidget *)parent(),"new_key"); + pop->setTimeout(0); + + QWidget *wid=new QWidget(pop); + QVBoxLayout *vbox=new QVBoxLayout(wid,3); + + QVBox *passiveBox=pop->standardView(i18n("Generating new key pair."),QString::null,KGlobal::iconLoader()->loadIcon("kgpg",KIcon::Desktop),wid); + + + QMovie anim; + anim=QMovie(locate("appdata", "pics/kgpg_anim.gif")); + + QLabel *tex=new QLabel(wid); + QLabel *tex2=new QLabel(wid); + tex->setAlignment(AlignHCenter); + tex->setMovie(anim); + tex2->setText(i18n("\nPlease wait...")); + vbox->addWidget(passiveBox); + vbox->addWidget(tex); + vbox->addWidget(tex2); + + pop->setView(wid); + + pop->show(); + changeMessage(i18n("Generating New Key..."),0,true); + + QRect qRect(QApplication::desktop()->screenGeometry()); + int iXpos=qRect.width()/2-pop->width()/2; + int iYpos=qRect.height()/2-pop->height()/2; + pop->move(iXpos,iYpos); + pop->setAutoDelete(false); + KProcIO *proc=new KProcIO(QTextCodec::codecForLocale()); + message=QString::null; + //*proc<<"gpg"<<"--no-tty"<<"--no-secmem-warning"<<"--batch"<<"--passphrase-fd"<start(KProcess::NotifyOnExit,true); + + if (ktype=="RSA") + proc->writeStdin("Key-Type: 1"); + else + { + proc->writeStdin("Key-Type: DSA"); + proc->writeStdin("Subkey-Type: ELG-E"); + proc->writeStdin(QString("Subkey-Length:%1").arg(ksize)); + } + proc->writeStdin(QString("Passphrase:%1").arg(password)); + proc->writeStdin(QString("Key-Length:%1").arg(ksize)); + proc->writeStdin(QString("Name-Real:%1").arg(newKeyName)); + if (!newKeyMail.isEmpty()) + proc->writeStdin(QString("Name-Email:%1").arg(newKeyMail)); + if (!kcomment.isEmpty()) + proc->writeStdin(QString("Name-Comment:%1").arg(kcomment)); + if (kexp==0) + proc->writeStdin(QString("Expire-Date:0")); + if (kexp==1) + proc->writeStdin(QString("Expire-Date:%1").arg(knumb)); + if (kexp==2) + proc->writeStdin(QString("Expire-Date:%1w").arg(knumb)); + + if (kexp==3) + proc->writeStdin(QString("Expire-Date:%1m").arg(knumb)); + + if (kexp==4) + proc->writeStdin(QString("Expire-Date:%1y").arg(knumb)); + proc->writeStdin("%commit"); + QObject::connect(proc,SIGNAL(readReady(KProcIO *)),this,SLOT(readgenprocess(KProcIO *))); + proc->closeWhenDone(); + } else ////// start expert (=konsole) mode + { + KProcess kp; + + KConfig *config = KGlobal::config(); + config->setGroup("General"); + kp<< config->readPathEntry("TerminalApplication","konsole"); + kp<<"-e" + <<"gpg" + <<"--gen-key"; + kp.start(KProcess::Block); + refreshkey(); + } + } +} + +void listKeys::readgenprocess(KProcIO *p) +{ + QString required; + while (p->readln(required,true)!=-1) { + if (required.find("KEY_CREATED")!=-1) + newkeyFinger=required.stripWhiteSpace().section(' ',-1); + message+=required+"\n"; + } + + // sample: [GNUPG:] KEY_CREATED B 156A4305085A58C01E2988229282910254D1B368 +} + +void listKeys::genover(KProcess *) +{ + newkeyID=QString::null; + continueSearch=true; + KProcIO *conprocess=new KProcIO(QTextCodec::codecForLocale()); + *conprocess<< "gpg"; + *conprocess<<"--no-secmem-warning"<<"--with-colons"<<"--fingerprint"<<"--list-keys"<start(KProcess::NotifyOnExit,true); +} + + +void listKeys::slotReadFingerProcess(KProcIO *p) +{ + QString outp; + while (p->readln(outp)!=-1) { + if (outp.startsWith("pub") && (continueSearch)) { + newkeyID=outp.section(':',4,4).right(8).prepend("0x"); + + } + if (outp.startsWith("fpr")) { + if (newkeyFinger.lower()==outp.section(':',9,9).lower()) + continueSearch=false; + // kdDebug(2100)<refreshcurrentkey(newkeyID); + changeMessage(i18n("%1 Keys, %2 Groups").arg(keysList2->childCount()-keysList2->groupNb).arg(keysList2->groupNb),1); + KDialogBase *keyCreated=new KDialogBase( this, "key_created", true,i18n("New Key Pair Created"), KDialogBase::Ok); + newKey *page=new newKey(keyCreated); + page->TLname->setText(""+newKeyName+""); + page->TLemail->setText(""+newKeyMail+""); + if (!newKeyMail.isEmpty()) + page->kURLRequester1->setURL(QDir::homeDirPath()+"/"+newKeyMail.section("@",0,0)+".revoke"); + else + page->kURLRequester1->setURL(QDir::homeDirPath()+"/"+newKeyName.section(" ",0,0)+".revoke"); + page->TLid->setText(""+newkeyID+""); + page->LEfinger->setText(newkeyFinger); + page->CBdefault->setChecked(true); + page->show(); + //page->resize(page->maximumSize()); + keyCreated->setMainWidget(page); + delete pop; + keyCreated->exec(); + + QListViewItem *newdef = keysList2->findItem(newkeyID,6); + if (newdef) + if (page->CBdefault->isChecked()) + slotSetDefaultKey(newdef); + else { + keysList2->clearSelection(); + keysList2->setCurrentItem(newdef); + keysList2->setSelected(newdef,true); + keysList2->ensureItemVisible(newdef); + } + if (page->CBsave->isChecked()) { + slotrevoke(newkeyID,page->kURLRequester1->url(),0,i18n("backup copy")); + if (page->CBprint->isChecked()) + connect(revKeyProcess,SIGNAL(revokeurl(QString)),this,SLOT(doFilePrint(QString))); + } else if (page->CBprint->isChecked()) { + slotrevoke(newkeyID,QString::null,0,i18n("backup copy")); + connect(revKeyProcess,SIGNAL(revokecertificate(QString)),this,SLOT(doPrint(QString))); + } +} + +void listKeys::doFilePrint(QString url) +{ + QFile qfile(url); + if (qfile.open(IO_ReadOnly)) { + QTextStream t( &qfile ); + doPrint(t.read()); + } else + KMessageBox::sorry(this,i18n("Cannot open file %1 for printing...").arg(url)); +} + +void listKeys::doPrint(QString txt) +{ + KPrinter prt; + //kdDebug(2100)<<"Printing..."<currentItem()->text(0)+" ("+keysList2->currentItem()->text(1)+")"; + int result=KMessageBox::warningContinueCancel(this, + i18n("

Delete SECRET KEY pair %1?

Deleting this key pair means you will never be able to decrypt files encrypted with this key again.").arg(res), + i18n("Warning"), + KGuiItem(i18n("Delete"),"editdelete")); + if (result!=KMessageBox::Continue) + return; + + KProcess *conprocess=new KProcess(); + KConfig *config = KGlobal::config(); + config->setGroup("General"); + *conprocess<< config->readPathEntry("TerminalApplication","konsole"); + *conprocess<<"-e"<<"gpg" + <<"--no-secmem-warning" + <<"--delete-secret-key"<currentItem()->text(6); + QObject::connect(conprocess, SIGNAL(processExited(KProcess *)),this, SLOT(reloadSecretKeys())); + conprocess->start(KProcess::NotifyOnExit,KProcess::AllOutput); +} + +void listKeys::reloadSecretKeys() +{ + FILE *fp; + char line[300]; + keysList2->secretList=QString::null; + fp = popen("gpg --no-secmem-warning --no-tty --with-colons --list-secret-keys", "r"); + while ( fgets( line, sizeof(line), fp)) { + QString lineRead=QString::fromUtf8(line); + if (lineRead.startsWith("sec")) + keysList2->secretList+="0x"+lineRead.section(':',4,4).right(8)+","; + } + pclose(fp); + deletekey(); +} + +void listKeys::confirmdeletekey() +{ + if (keysList2->currentItem()->depth()!=0) { + if ((keysList2->currentItem()->depth()==1) && (keysList2->currentItem()->text(4)=="-") && (keysList2->currentItem()->text(6).startsWith("0x"))) + delsignkey(); + return; + } + if (keysList2->currentItem()->text(6).isEmpty()) { + deleteGroup(); + return; + } + if (((keysList2->secretList.find(keysList2->currentItem()->text(6))!=-1) || (keysList2->orphanList.find(keysList2->currentItem()->text(6))!=-1)) && (keysList2->selectedItems().count()==1)) + deleteseckey(); + else { + QStringList keysToDelete; + QString secList; + QPtrList exportList=keysList2->selectedItems(); + bool secretKeyInside=false; + for ( uint i = 0; i < exportList.count(); ++i ) + if ( exportList.at(i) ) { + if (keysList2->secretList.find(exportList.at(i)->text(6))!=-1) { + secretKeyInside=true; + secList+=exportList.at(i)->text(0)+" ("+exportList.at(i)->text(1)+")
"; + exportList.at(i)->setSelected(false); + } else + keysToDelete+=exportList.at(i)->text(0)+" ("+exportList.at(i)->text(1)+")"; + } + + if (secretKeyInside) { + int result=KMessageBox::warningContinueCancel(this,i18n("The following are secret key pairs:
%1They will not be deleted.
").arg(secList)); + if (result!=KMessageBox::Continue) + return; + } + if (keysToDelete.isEmpty()) + return; + int result=KMessageBox::warningContinueCancelList(this,i18n("Delete the following public key?","Delete the following %n public keys?",keysToDelete.count()),keysToDelete,i18n("Warning"),KStdGuiItem::del()); + if (result!=KMessageBox::Continue) + return; + else + deletekey(); + } +} + +void listKeys::deletekey() +{ + QPtrList exportList=keysList2->selectedItems(); + if (exportList.count()==0) + return; + KProcess gp; + gp << "gpg" + << "--no-tty" + << "--no-secmem-warning" + << "--batch" + << "--yes" + << "--delete-key"; + for ( uint i = 0; i < exportList.count(); ++i ) + if ( exportList.at(i) ) + gp<<(exportList.at(i)->text(6)).stripWhiteSpace(); + gp.start(KProcess::Block); + + for ( uint i = 0; i < exportList.count(); ++i ) + if ( exportList.at(i) ) + keysList2->refreshcurrentkey(exportList.at(i)); + if (keysList2->currentItem()) { + QListViewItem * myChild = keysList2->currentItem(); + while(!myChild->isVisible()) { + myChild = myChild->nextSibling(); + if (!myChild) + break; + } + if (!myChild) { + QListViewItem * myChild = keysList2->firstChild(); + while(!myChild->isVisible()) { + myChild = myChild->nextSibling(); + if (!myChild) + break; + } + } + if (myChild) { + myChild->setSelected(true); + keysList2->setCurrentItem(myChild); + } + } + else stateChanged("empty_list"); + changeMessage(i18n("%1 Keys, %2 Groups").arg(keysList2->childCount()-keysList2->groupNb).arg(keysList2->groupNb),1); +} + + +void listKeys::slotPreImportKey() +{ + KDialogBase *dial=new KDialogBase( KDialogBase::Swallow, i18n("Key Import"), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, this, "key_import",true); + + SrcSelect *page=new SrcSelect(); + dial->setMainWidget(page); + page->newFilename->setCaption(i18n("Open File")); + page->newFilename->setMode(KFile::File); + page->resize(page->minimumSize()); + dial->resize(dial->minimumSize()); + + if (dial->exec()==QDialog::Accepted) { + if (page->checkFile->isChecked()) { + QString impname=page->newFilename->url().stripWhiteSpace(); + if (!impname.isEmpty()) { + changeMessage(i18n("Importing..."),0,true); + ////////////////////////// import from file + KgpgInterface *importKeyProcess=new KgpgInterface(); + importKeyProcess->importKeyURL(KURL::fromPathOrURL( impname )); + connect(importKeyProcess,SIGNAL(importfinished(QStringList)),keysList2,SLOT(slotReloadKeys(QStringList))); + connect(importKeyProcess,SIGNAL(refreshOrphaned()),keysList2,SLOT(slotReloadOrphaned())); + } + } else { + QString keystr = kapp->clipboard()->text(clipboardMode); + if (!keystr.isEmpty()) { + changeMessage(i18n("Importing..."),0,true); + KgpgInterface *importKeyProcess=new KgpgInterface(); + importKeyProcess->importKey(keystr); + connect(importKeyProcess,SIGNAL(importfinished(QStringList)),keysList2,SLOT(slotReloadKeys(QStringList))); + connect(importKeyProcess,SIGNAL(refreshOrphaned()),keysList2,SLOT(slotReloadOrphaned())); + } + } + } + delete dial; +} + + +void KeyView::expandGroup(QListViewItem *item) +{ + + QStringList keysGroup=KgpgInterface::getGpgGroupSetting(item->text(0),KGpgSettings::gpgConfigPath()); + kdDebug(2100)<setPixmap(0,pixkeyGroup); + item2->setExpandable(false); + } +} + +QPixmap KeyView::slotGetPhoto(QString photoId,bool mini) +{ + KTempFile *phototmp=new KTempFile(); + QString popt="cp %i "+phototmp->name(); + KProcIO *p=new KProcIO(QTextCodec::codecForLocale()); + *p<<"gpg"<<"--show-photos"<<"--photo-viewer"<start(KProcess::Block); + + QPixmap pixmap; + + pixmap.load(phototmp->name()); + QImage dup=pixmap.convertToImage(); + QPixmap dup2; + if (!mini) + dup2.convertFromImage(dup.scale(previewSize+5,previewSize,QImage::ScaleMin)); + else + dup2.convertFromImage(dup.scale(22,22,QImage::ScaleMin)); + phototmp->unlink(); + delete phototmp; + return dup2; +} + +void KeyView::expandKey(QListViewItem *item) +{ + + if (item->childCount()!=0) + return; // key has already been expanded + FILE *fp; + QString cycle; + QStringList tst; + char tmpline[300]; + UpdateViewItem *itemsub=NULL; + UpdateViewItem *itemuid=NULL; + UpdateViewItem *itemsig=NULL; + UpdateViewItem *itemrev=NULL; + QPixmap keyPhotoId; + int uidNumber=2; + bool dropFirstUid=false; + + kdDebug(2100)<<"Expanding Key: "<text(6)<text(6))), "r"); + + while ( fgets( tmpline, sizeof(tmpline), fp)) { + QString line = QString::fromUtf8( tmpline ); + tst=QStringList::split(":",line,true); + if ((tst[0]=="pub") && (tst[9].isEmpty())) /// Primary User Id is separated from public key + uidNumber=1; + if (tst[0]=="uid" || tst[0]=="uat") { + if (dropFirstUid) { + dropFirstUid=false; + } else { + gpgKey uidKey=extractKey(line); + + if (tst[0]=="uat") { + kdDebug(2100)<<"Found photo at uid "<setAutoDelete(true); + QString pgpgOutput="cp %i "+kgpgphototmp->name(); + KProcIO *p=new KProcIO(QTextCodec::codecForLocale()); + *p<<"gpg"<<"--no-tty"<<"--photo-viewer"<text(6)<<"uid"<start(KProcess::Block); + QPixmap pixmap; + pixmap.load(kgpgphototmp->name()); + QImage dup=pixmap.convertToImage(); + QPixmap dup2; + dup2.convertFromImage(dup.scale(previewSize+5,previewSize,QImage::ScaleMin)); + itemuid->setPixmap(0,dup2); + delete kgpgphototmp; + //itemuid->setPixmap(0,keyPhotoId); + } else + itemuid->setPixmap(0,pixuserphoto); + itemuid->setPixmap(2,uidKey.trustpic); + cycle="uid"; + } else { + kdDebug(2100)<<"Found uid at "<setPixmap(2,uidKey.trustpic); + if (noID) { + item->setText(0,uidKey.gpgkeyname); + item->setText(1,uidKey.gpgkeymail); + noID=false; + } + itemuid->setPixmap(0,pixuserid); + cycle="uid"; + } + } + uidNumber++; + } else + if (tst[0]=="rev") { + gpgKey revKey=extractKey(line); + if (cycle=="uid" || cycle=="uat") + itemrev= new UpdateViewItem(itemuid,revKey.gpgkeyname,revKey.gpgkeymail+i18n(" [Revocation signature]"),"-","-","-",revKey.gpgkeycreation,revKey.gpgkeyid); + else if (cycle=="pub") { //////////////public key revoked + itemrev= new UpdateViewItem(item,revKey.gpgkeyname,revKey.gpgkeymail+i18n(" [Revocation signature]"),"-","-","-",revKey.gpgkeycreation,revKey.gpgkeyid); + dropFirstUid=true; + } else if (cycle=="sub") + itemrev= new UpdateViewItem(itemsub,revKey.gpgkeyname,revKey.gpgkeymail+i18n(" [Revocation signature]"),"-","-","-",revKey.gpgkeycreation,revKey.gpgkeyid); + itemrev->setPixmap(0,pixRevoke); + } else + + + if (tst[0]=="sig") { + gpgKey sigKey=extractKey(line); + + if (tst[10].endsWith("l")) + sigKey.gpgkeymail+=i18n(" [local]"); + + if (cycle=="pub") + itemsig= new UpdateViewItem(item,sigKey.gpgkeyname,sigKey.gpgkeymail,"-",sigKey.gpgkeyexpiration,"-",sigKey.gpgkeycreation,sigKey.gpgkeyid); + if (cycle=="sub") + itemsig= new UpdateViewItem(itemsub,sigKey.gpgkeyname,sigKey.gpgkeymail,"-",sigKey.gpgkeyexpiration,"-",sigKey.gpgkeycreation,sigKey.gpgkeyid); + if (cycle=="uid") + itemsig= new UpdateViewItem(itemuid,sigKey.gpgkeyname,sigKey.gpgkeymail,"-",sigKey.gpgkeyexpiration,"-",sigKey.gpgkeycreation,sigKey.gpgkeyid); + + itemsig->setPixmap(0,pixsignature); + } else + if (tst[0]=="sub") { + gpgKey subKey=extractKey(line); + itemsub= new UpdateViewItem(item,i18n("%1 subkey").arg(subKey.gpgkeyalgo),QString::null,QString::null,subKey.gpgkeyexpiration,subKey.gpgkeysize,subKey.gpgkeycreation,subKey.gpgkeyid); + itemsub->setPixmap(0,pixkeySingle); + itemsub->setPixmap(2,subKey.trustpic); + cycle="sub"; + + } + } + pclose(fp); +} + + +void listKeys::refreshkey() +{ + keysList2->refreshkeylist(); + listViewSearch->updateSearch(listViewSearch->text()); +} + +void KeyView::refreshkeylist() +{ + emit statusMessage(i18n("Loading Keys..."),0,true); + kapp->processEvents(); + //////// update display of keys in main management window + kdDebug(2100)<<"Refreshing key list"<depth() > 0) { + current = current->parent(); + } + takeItem(current); + } + + // refill + clear(); + FILE *fp2,*fp; + QStringList issec; + secretList=QString::null; + orphanList=QString::null; + fp2 = popen("gpg --no-secmem-warning --no-tty --with-colons --list-secret-keys", "r"); + while ( fgets( line, sizeof(line), fp2)) { + QString lineRead=QString::fromUtf8(line); + kdDebug(2100) << k_funcinfo << "Read one secret key line: " << lineRead << endl; + if (lineRead.startsWith("sec")) + issec<setPixmap(2,pubKey.trustpic); + item->setExpandable(true); + + + QStringList::Iterator ite; + ite=issec.find(pubKey.gpgkeyid.right(8)); + if (ite!=issec.end()) { + item->setPixmap(0,pixkeyPair); + secretList+=pubKey.gpgkeyid; + issec.remove(*ite); + } else item->setPixmap(0,pixkeySingle); + + if (openKeys.find(pubKey.gpgkeyid)!=-1) + item->setOpen(true); + } + + } + pclose(fp); + if (!issec.isEmpty()) + insertOrphanedKeys(issec); + if (emptyList) { + kdDebug(2100)<<"No key found"<setPixmap(0,pixkeyGroup); + item->setExpandable(false); + } + kdDebug(2100)<<"Finished Groups"<text(6).isEmpty()) + newPos = findItem(current->text(6), 6); + else + newPos = findItem(current->text(0), 0); + delete current; + } + + if (newPos != 0L) { + setCurrentItem(newPos); + setSelected(newPos, true); + ensureItemVisible(newPos); + } else { + setCurrentItem(firstChild()); + setSelected(firstChild(),true); + } + + emit statusMessage(i18n("%1 Keys, %2 Groups").arg(childCount()-groupNb).arg(groupNb),1); + emit statusMessage(i18n("Ready"),0); + kdDebug(2100)<<"Refresh Finished"<setPixmap(0,pixkeyOrphan); + } + } + pclose(fp); + if (!keyFound) { + orphanList.remove(currentID); + setSelected(currentItem(),true); + return; + } + clearSelection(); + setCurrentItem(item); + setSelected(item,true); +} + +void KeyView::insertOrphanedKeys(QStringList orphans) +{ + FILE *fp; + char line[300]; + fp = popen("gpg --no-secmem-warning --no-tty --with-colons --list-secret-keys", "r"); + while ( fgets( line, sizeof(line), fp)) { + QString lineRead=QString::fromUtf8(line); + if ((lineRead.startsWith("sec")) && (orphans.find(lineRead.section(':',4,4).right(8))!=orphans.end())) { + gpgKey orphanedKey=extractKey(lineRead); + + bool isbold=false; + bool isexpired=false; + // if (orphanedKey.gpgkeyid==defaultKey) + // isbold=true; + if (orphanedKey.gpgkeytrust==i18n("Expired")) + isexpired=true; + // if (orphanedKey.gpgkeyname.isEmpty()) + // noID=true; + orphanList+=orphanedKey.gpgkeyid+","; + UpdateViewItem *item=new UpdateViewItem(this,orphanedKey.gpgkeyname,orphanedKey.gpgkeymail,QString::null,orphanedKey.gpgkeyexpiration,orphanedKey.gpgkeysize,orphanedKey.gpgkeycreation,orphanedKey.gpgkeyid,isbold,isexpired); + item->setPixmap(0,pixkeyOrphan); + } + } + pclose(fp); +} + +void KeyView::refreshgroups() +{ + QListViewItem *item=firstChild(); + while (item) { + if (item->text(6).isEmpty()) { + QListViewItem *item2=item->nextSibling(); + delete item; + item=item2; + } else + item=item->nextSibling(); + } + + QStringList groups=KgpgInterface::getGpgGroupNames(KGpgSettings::gpgConfigPath()); + groupNb=groups.count(); + for ( QStringList::Iterator it = groups.begin(); it != groups.end(); ++it ) + if (!QString(*it).isEmpty()) { + item=new UpdateViewItem(this,QString(*it),QString::null,QString::null,QString::null,QString::null,QString::null,QString::null,false,false); + item->setPixmap(0,pixkeyGroup); + item->setExpandable(false); + } + emit statusMessage(i18n("%1 Keys, %2 Groups").arg(childCount()-groupNb).arg(groupNb),1); + emit statusMessage(i18n("Ready"),0); +} + +void KeyView::refreshselfkey() +{ + kdDebug(2100)<<"Refreshing key"<depth()==0) + refreshcurrentkey(currentItem()); + else + refreshcurrentkey(currentItem()->parent()); +} + +void KeyView::slotReloadKeys(QStringList keyIDs) +{ + if (keyIDs.isEmpty()) + return; + if (keyIDs.first()=="ALL") + { + refreshkeylist(); + return; + } + for ( QStringList::Iterator it = keyIDs.begin(); it != keyIDs.end(); ++it ) { + refreshcurrentkey(*it); + } + kdDebug(2100)<<"Refreshing key:--------"<<(keyIDs.last()).right(8).prepend("0x")<findItem((keyIDs.last()).right(8).prepend("0x"),6)); + emit statusMessage(i18n("%1 Keys, %2 Groups").arg(childCount()-groupNb).arg(groupNb),1); + emit statusMessage(i18n("Ready"),0); +} + +void KeyView::slotReloadOrphaned() +{ + QStringList issec; + FILE *fp,*fp2; + char line[300]; + + fp2 = popen("gpg --no-secmem-warning --no-tty --with-colons --list-secret-keys", "r"); + while ( fgets( line, sizeof(line), fp2)) { + QString lineRead=QString::fromUtf8(line); + if (lineRead.startsWith("sec")) + issec<<"0x"+lineRead.section(':',4,4).right(8); + } + pclose(fp2); + + fp = popen("gpg --no-secmem-warning --no-tty --with-colons --list-keys", "r"); + while ( fgets( line, sizeof(line), fp)) { + QString lineRead=QString::fromUtf8(line); + if (lineRead.startsWith("pub")) + issec.remove("0x"+lineRead.section(':',4,4).right(8)); + } + pclose(fp); + + QStringList::Iterator it; + + for ( it = issec.begin(); it != issec.end(); ++it ) { + if (findItem(*it,6)==0) { + insertOrphan(*it); + orphanList+=*it+","; + } + } + setSelected(findItem(*it,6),true); + emit statusMessage(i18n("%1 Keys, %2 Groups").arg(childCount()-groupNb).arg(groupNb),1); + emit statusMessage(i18n("Ready"),0); +} + +void KeyView::refreshcurrentkey(QString currentID) +{ + if (currentID.isNull()) return; + UpdateViewItem *item=NULL; + QString issec=QString::null; + FILE *fp,*fp2; + char line[300]; + + fp2 = popen("gpg --no-secmem-warning --no-tty --with-colons --list-secret-keys", "r"); + while ( fgets( line, sizeof(line), fp2)) { + QString lineRead=QString::fromUtf8(line); + if (lineRead.startsWith("sec")) + issec+=lineRead.section(':',4,4); + } + pclose(fp2); + + QString defaultKey = KGpgSettings::defaultKey(); + + QString tst; + bool keyFound=false; + QString cmd="gpg --no-secmem-warning --no-tty --with-colons --list-keys "+currentID; + fp = popen(QFile::encodeName(cmd), "r"); + while ( fgets( line, sizeof(line), fp)) { + tst=QString::fromUtf8(line); + if (tst.startsWith("pub")) { + gpgKey pubKey=extractKey(tst); + keyFound=true; + bool isbold=false; + bool isexpired=false; + if (pubKey.gpgkeyid==defaultKey) + isbold=true; + if (pubKey.gpgkeytrust==i18n("Expired")) + isexpired=true; + item=new UpdateViewItem(this,pubKey.gpgkeyname,pubKey.gpgkeymail,QString::null,pubKey.gpgkeyexpiration,pubKey.gpgkeysize,pubKey.gpgkeycreation,pubKey.gpgkeyid,isbold,isexpired); + item->setPixmap(2,pubKey.trustpic); + item->setVisible(true); + item->setExpandable(true); + if (issec.find(pubKey.gpgkeyid.right(8),0,FALSE)!=-1) { + item->setPixmap(0,pixkeyPair); + secretList+=pubKey.gpgkeyid; + } else { + item->setPixmap(0,pixkeySingle); + } + } + } + pclose(fp); + + if (!keyFound) { + if (orphanList.find(currentID)==-1) + orphanList+=currentID+","; + insertOrphan(currentID); + return; + } + if (orphanList.find(currentID)!=-1) + orphanList.remove(currentID); + + clearSelection(); + setCurrentItem(item); + +} + +void KeyView::refreshcurrentkey(QListViewItem *current) +{ + if (!current) + return; + bool keyIsOpen=false; + QString keyUpdate=current->text(6); + if (keyUpdate.isEmpty()) + return; + if (current->isOpen()) + keyIsOpen=true; + delete current; + refreshcurrentkey(keyUpdate); + if (currentItem()) + if (currentItem()->text(6)==keyUpdate) + currentItem()->setOpen(keyIsOpen); +} + + +void KeyView::refreshTrust(int color,QColor newColor) +{ +if (!newColor.isValid()) return; +QPixmap blankFrame,newtrust; +int trustFinger=0; +blankFrame.load(locate("appdata", "pics/kgpg_blank.png")); +newtrust.load(locate("appdata", "pics/kgpg_fill.png")); +newtrust.fill(newColor); +bitBlt(&newtrust,0,0,&blankFrame,0,0,50,15); +switch (color) +{ +case GoodColor: +trustFinger=trustgood.serialNumber(); +trustgood=newtrust; +break; +case BadColor: +trustFinger=trustbad.serialNumber(); +trustbad=newtrust; +break; +case UnknownColor: +trustFinger=trustunknown.serialNumber(); +trustunknown=newtrust; +break; +case RevColor: +trustFinger=trustrevoked.serialNumber(); +trustrevoked=newtrust; +break; +} +QListViewItem *item=firstChild(); + while (item) { + if (item->pixmap(2)) + { + if (item->pixmap(2)->serialNumber()==trustFinger) item->setPixmap(2,newtrust); + } + item=item->nextSibling(); + } +} + +gpgKey KeyView::extractKey(QString keyColon) +{ + QStringList keyString=QStringList::split(":",keyColon,true); + gpgKey ret; + + ret.gpgkeysize=keyString[2]; + ret.gpgkeycreation=keyString[5]; + if(!ret.gpgkeycreation.isEmpty()) { + QDate date = QDate::fromString(ret.gpgkeycreation, Qt::ISODate); + ret.gpgkeycreation=KGlobal::locale()->formatDate(date, true); + } + QString tid=keyString[4]; + ret.gpgkeyid=QString("0x"+tid.right(8)); + ret.gpgkeyexpiration=keyString[6]; + if (ret.gpgkeyexpiration.isEmpty()) + ret.gpgkeyexpiration=i18n("Unlimited"); + else { + QDate date = QDate::fromString(ret.gpgkeyexpiration, Qt::ISODate); + ret.gpgkeyexpiration=KGlobal::locale()->formatDate(date, true); + } + QString fullname=keyString[9]; + if (fullname.find("<")!=-1) { + ret.gpgkeymail=fullname.section('<',-1,-1); + ret.gpgkeymail.truncate(ret.gpgkeymail.length()-1); + ret.gpgkeyname=fullname.section('<',0,0); + //ret.gpgkeyname=ret.gpgkeyname.section('(',0,0); + } else { + ret.gpgkeymail=QString::null; + ret.gpgkeyname=fullname; + //ret.gpgkeyname=fullname.section('(',0,0); + } + + //ret.gpgkeyname=KgpgInterface::checkForUtf8(ret.gpgkeyname); // FIXME lukas + + QString algo=keyString[3]; + if (!algo.isEmpty()) + switch( algo.toInt() ) { + case 1: + algo=i18n("RSA"); + break; + case 16: + case 20: + algo=i18n("ElGamal"); + break; + case 17: + algo=i18n("DSA"); + break; + default: + algo=QString("#" + algo); + break; + } + ret.gpgkeyalgo=algo; + + const QString trust=keyString[1]; + switch( trust[0] ) { + case 'o': + ret.gpgkeytrust=i18n("Unknown"); + ret.trustpic=trustunknown; + break; + case 'i': + ret.gpgkeytrust=i18n("Invalid"); + ret.trustpic=trustbad; + break; + case 'd': + ret.gpgkeytrust=i18n("Disabled"); + ret.trustpic=trustbad; + break; + case 'r': + ret.gpgkeytrust=i18n("Revoked"); + ret.trustpic=trustrevoked; + break; + case 'e': + ret.gpgkeytrust=i18n("Expired"); + ret.trustpic=trustbad; + break; + case 'q': + ret.gpgkeytrust=i18n("Undefined"); + ret.trustpic=trustunknown; + break; + case 'n': + ret.gpgkeytrust=i18n("None"); + ret.trustpic=trustunknown; + break; + case 'm': + ret.gpgkeytrust=i18n("Marginal"); + ret.trustpic=trustbad; + break; + case 'f': + ret.gpgkeytrust=i18n("Full"); + ret.trustpic=trustgood; + break; + case 'u': + ret.gpgkeytrust=i18n("Ultimate"); + ret.trustpic=trustgood; + break; + default: + ret.gpgkeytrust=i18n("?"); + ret.trustpic=trustunknown; + break; + } + if (keyString[11].find('D')!=-1) { + ret.gpgkeytrust=i18n("Disabled"); + ret.trustpic=trustbad; + } + + return ret; +} + +#include "listkeys.moc" diff --git a/kgpg/listkeys.h b/kgpg/listkeys.h new file mode 100644 index 0000000..b2610db --- /dev/null +++ b/kgpg/listkeys.h @@ -0,0 +1,302 @@ +/*************************************************************************** + listkeys.h - description + ------------------- + begin : Thu Jul 4 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef LISTKEYS_H +#define LISTKEYS_H + +#include +#include +#include +#include + +#include +#include + +#include "dcopiface.h" + +#include +#include +#include + +#include +#include + +class QPushButton; +class QPopupMenu; +class QLabel; +class QCheckbox; +class KStatusBar; +class KPassivePopup; +class KProcess; +class KProcIO; +class QEvent; +class KTempFile; +class KgpgApp; +class keyServer; +class groupEdit; +class KgpgInterface; +class KSelectAction; + +struct gpgKey +{ + QString gpgkeymail; + QString gpgkeyname; + QString gpgkeyid; + QString gpgkeytrust; + QString gpgkeyvalidity; + QString gpgkeysize; + QString gpgkeycreation; + QString gpgkeyexpiration; + QString gpgkeyalgo; + QPixmap trustpic; +}; + +class KgpgSelKey : public KDialogBase +{ + Q_OBJECT + +public: + KgpgSelKey( QWidget *parent = 0, const char *name = 0,bool allowMultipleSelection=false, QString preselected=QString::null); + KListView *keysListpr; + QPixmap keyPair; + QCheckBox *local; + QVBoxLayout *vbox; + QWidget *page; +private slots: + void slotOk(); + void slotpreOk(); + void slotSelect(QListViewItem *item); + +public slots: + QString getkeyID(); + QString getkeyMail(); +}; + + + +class KeyView : public KListView +{ + Q_OBJECT + friend class listKeys; +public: + KeyView( QWidget *parent = 0, const char *name = 0); + bool displayPhoto,displayOnlySecret,displayDisabled; + int previewSize; + QString secretList; + QPixmap trustbad; + +private: + + QString orphanList; + QString photoKeysList; + QPixmap pixkeyPair, pixkeySingle, pixkeyGroup, pixsignature, pixuserid, pixuserphoto; + QPixmap trustunknown, trustrevoked, trustgood, pixRevoke, pixkeyOrphan; + QListViewItem *itemToOpen; + KTempFile *kgpgphototmp; + int groupNb; + +public slots: + void slotRemoveColumn(int d); + void slotAddColumn(int c); + +private slots: + void refreshTrust(int color,QColor newColor); + void droppedfile (KURL); + void refreshkeylist(); + gpgKey extractKey(QString keyColon); + void expandKey(QListViewItem *item); + void expandGroup(QListViewItem *item); + void refreshcurrentkey(QListViewItem *current); + void refreshcurrentkey(QString currentID); + void refreshselfkey(); + void refreshgroups(); + void insertOrphanedKeys(QStringList orpans); + void insertOrphan(QString currentID); + QPixmap slotGetPhoto(QString photoId,bool mini=false); + void slotReloadKeys(QStringList keyIDs); + void slotReloadOrphaned(); + +signals: + void statusMessage(QString,int,bool keep=false); + +protected: + virtual void startDrag(); + virtual void contentsDragMoveEvent(QDragMoveEvent *e); + virtual void contentsDropEvent (QDropEvent*); +}; + +class mySearchLine: public KListViewSearchLine +{ + Q_OBJECT +public: + mySearchLine(QWidget *parent = 0, KeyView *listView = 0, const char *name = 0); + virtual ~mySearchLine(); +private: + KeyView *searchListView; + +public slots: +virtual void updateSearch(const QString &s = QString::null); +protected: +virtual bool itemMatches(const QListViewItem *item, const QString & s) const; +}; + + +class listKeys : public KMainWindow, virtual public KeyInterface +{ + friend class KeyView; + Q_OBJECT + +public: + listKeys(QWidget *parent=0, const char *name=0); + ~listKeys(); + QLabel *keyPhoto; + KeyView *keysList2; + QPopupMenu *popup,*popupsec,*popupout,*popupsig,*popupgroup,*popupphoto,*popupuid,*popuporphan; + QString message; + QStringList keynames; + KPassivePopup *pop; + KToggleAction *sTrust,*sCreat,*sExpi,*sSize; + KSelectAction *photoProps; + KStatusBar *keyStatusBar; + KgpgApp *s_kgpgEditor; + +private: + QPushButton *bouton1,*bouton2,*bouton0; + QString tempKeyFile,newKeyMail,newKeyName,newkeyFinger,newkeyID; + KListViewSearchLine* listViewSearch; + bool continueSearch; + bool showPhoto; + keyServer *kServer; + KTempFile *kgpgtmp; + KAction *importSignatureKey,*importAllSignKeys,*signKey,*refreshKey; + QPtrList signList,keysList; + uint globalCount,keyCount; + int globalChecked; + bool globalisLocal,showTipOfDay; + QString globalkeyMail,globalkeyID,searchString; + long searchOptions; + groupEdit *gEdit; + KgpgInterface *revKeyProcess; + KDialogBase *addUidWidget; + QClipboard::Mode clipboardMode; + QTimer *statusbarTimer; + + +protected: + void closeEvent( QCloseEvent * e ); + bool eventFilter( QObject *, QEvent *e ); + +public slots: + void slotgenkey(); + void refreshkey(); + void readAllOptions(); + void showKeyInfo(QString keyID); + void findKey(); + void findFirstKey(); + void findNextKey(); + void slotSetDefaultKey(QString newID); + +private slots: + void quitApp(); + void slotOpenEditor(); + void changeMessage(QString,int, bool keep=false); + void statusBarTimeout(); + void slotShowTrust(); + void slotShowSize(); + void slotShowCreat(); + void slotShowExpi(); + void slotToggleSecret(); + void slotToggleDisabled(); + void slotGotoDefaultKey(); + void slotDelUid(); + void slotAddUid(); + void slotAddUidEnable(const QString & name); + void slotGpgError(QString errortxt); + void slotUpdatePhoto(); + void slotDeletePhoto(); + void slotAddPhoto(); + void slotSetPhotoSize(int size); + void slotShowPhoto(); + void readgenprocess(KProcIO *p); + void newKeyDone(KProcess *); + void slotrevoke(QString keyID,QString revokeUrl,int reason,QString description); + void revokeWidget(); + void doFilePrint(QString url); + void doPrint(QString txt); + void checkList(); + void signLoop(); + void slotManpage(); + void slotTip(); + void showKeyServer(); + void showKeyManager(); + void slotReadFingerProcess(KProcIO *p); + void slotProcessExportMail(QString keys); + void slotProcessExportClip(QString keys); + void readOptions(); + void genover(KProcess *p); + void showOptions(); + void slotSetDefKey(); + void slotSetDefaultKey(QListViewItem *newdef); + void annule(); + void confirmdeletekey(); + void deletekey(); + void deleteseckey(); + void signkey(); + void delsignkey(); + void preimportsignkey(); + bool importRemoteKey(QString keyID); + void importsignkey(QString importKeyId); + void importallsignkey(); + void importfinished(); + void signatureResult(int success); + void delsignatureResult(bool); + void listsigns(); + void slotexport(); + void slotexportsec(); + void slotmenu(QListViewItem *,const QPoint &,int); + void slotPreImportKey(); + void slotedit(); + void addToKAB(); + // void allToKAB(); + void editGroup(); + void groupAdd(); + void groupRemove(); + void groupInit(QStringList keysGroup); + void groupChange(); + void createNewGroup(); + void deleteGroup(); + void slotImportRevoke(QString url); + void slotImportRevokeTxt(QString revokeText); + void refreshKeyFromServer(); + void refreshFinished(); + void slotregenerate(); + void reloadSecretKeys(); + void dcopImportFinished(); + +signals: + void readAgainOptions(); + void certificate(QString); + void closeAsked(); + void fontChanged(QFont); + void encryptFiles(KURL::List); + void installShredder(); + +}; + + +#endif // LISTKEYS_H + diff --git a/kgpg/listkeys.rc b/kgpg/listkeys.rc new file mode 100644 index 0000000..a2dff30 --- /dev/null +++ b/kgpg/listkeys.rc @@ -0,0 +1,137 @@ + + + + + &Keys + + + + + + + + + + + + + + + + &View + + + &Show Details + + + + + + + + + + &Groups + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kgpg/main.cpp b/kgpg/main.cpp new file mode 100644 index 0000000..622739f --- /dev/null +++ b/kgpg/main.cpp @@ -0,0 +1,79 @@ +/*************************************************************************** + main.cpp - description + ------------------- + begin : Mon Jul 8 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include + + +#include +#include +#include +#include +#include +#include "kgpg.h" + +static const char description[] = + I18N_NOOP("Kgpg - simple gui for gpg\n\nKgpg was designed to make gpg very easy to use.\nI tried to make it as secure as possible.\nHope you enjoy it."); + +static const char version[] = "1.2.2"; + +static KCmdLineOptions options[] = + { + { "e", I18N_NOOP("Encrypt file"), 0 }, + { "k", I18N_NOOP("Open key manager"), 0 }, + { "s", I18N_NOOP("Show encrypted file"), 0 }, + { "S", I18N_NOOP("Sign file"), 0 }, + { "V", I18N_NOOP("Verify signature"), 0 }, + { "X", I18N_NOOP("Shred file"), 0 }, + { "+[File]", I18N_NOOP("File to open"), 0 }, + KCmdLineLastOption + // INSERT YOUR COMMANDLINE OPTIONS HERE + }; + +int main(int argc, char *argv[]) +{ + + KAboutData about("kgpg", I18N_NOOP("KGpg"), version, description, + KAboutData::License_GPL, "(C) 2003 Jean-Baptiste Mardelle"); + about.addAuthor( "Jean-Baptiste Mardelle", 0, "bj@altern.org" ); + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions(options); + KUniqueApplication::addCmdLineOptions(); + + + //KMessageBox::sorry(0,"nombre: "+QString::number(i)); + + if (!KUniqueApplication::start()) + return 0; + + //KgpgAppletApp *app; + KApplication *app; + app=new KgpgAppletApp; + return app->exec(); + + /* + + KUniqueApplication app; + + // register ourselves as a dcop client + //app.dcopClient()->registerAs(app.name(), false); + + + kgpgapplet widget;// = new kgpgapplet("kgpg"); + widget.show(); + return app.exec();*/ +} diff --git a/kgpg/newkey.ui b/kgpg/newkey.ui new file mode 100644 index 0000000..ad6b0aa --- /dev/null +++ b/kgpg/newkey.ui @@ -0,0 +1,196 @@ + +newKey + + + newKey + + + + 0 + 0 + 625 + 328 + + + + New Key Pair Created + + + + unnamed + + + 0 + + + + groupBox2 + + + New Key Created + + + + unnamed + + + + textLabel2 + + + You have successfully created the following key: + + + + + CBdefault + + + Set as your default key + + + <qt><b>Set as your default key:</b><br /> + <p>Checking this option sets the newly created key pair as the default key pair.</p> + </qt> + + + + + LEfinger + + + true + + + true + + + + + textLabel6 + + + Fingerprint: + + + + + textLabel3 + + + Name: + + + + + textLabel4 + + + Email: + + + + + textLabel5 + + + Key ID: + + + + + TLname + + + + 7 + 5 + 0 + 0 + + + + textLabel7 + + + + + TLemail + + + textLabel8 + + + + + TLid + + + textLabel10 + + + + + + + groupBox1 + + + Revocation Certificate + + + + unnamed + + + + textLabel1 + + + It is recommended to save or print a revocation certificate in case your key is compromised. + + + + + CBprint + + + Print + + + + + CBsave + + + Save as: + + + + + kURLRequester1 + + + false + + + + + + + + + CBsave + toggled(bool) + newKey + CBsave_toggled(bool) + + + + newkey.ui.h + + + CBsave_toggled( bool isOn ) + + + diff --git a/kgpg/newkey.ui.h b/kgpg/newkey.ui.h new file mode 100644 index 0000000..e920edd --- /dev/null +++ b/kgpg/newkey.ui.h @@ -0,0 +1,21 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ +//(C) 2002 Jean-Baptiste Mardelle + +void newKey::CBsave_toggled( bool isOn) +{ +kURLRequester1->setEnabled(isOn); +} diff --git a/kgpg/popuppublic.cpp b/kgpg/popuppublic.cpp new file mode 100644 index 0000000..167423c --- /dev/null +++ b/kgpg/popuppublic.cpp @@ -0,0 +1,480 @@ +/*************************************************************************** + popuppublic.cpp - description + ------------------- + begin : Sat Jun 29 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +//////////////////////////////////////////////////////// code for choosing a public key from a list for encryption +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#if KDE_IS_VERSION( 3, 2, 90 ) +#include +#endif +#include +#include +#include +#include +#include + + +#include "popuppublic.h" +#include "kgpgsettings.h" +#include "kgpgview.h" +#include "kgpg.h" + +///////////////// klistviewitem special + +class UpdateViewItem2 : public KListViewItem +{ +public: + UpdateViewItem2(QListView *parent, QString name,QString mail,QString id,bool isDefault); + virtual void paintCell(QPainter *p, const QColorGroup &cg,int col, int width, int align); + virtual QString key(int c,bool ) const; + bool def; +}; + +UpdateViewItem2::UpdateViewItem2(QListView *parent, QString name,QString mail,QString id,bool isDefault) + : KListViewItem(parent) +{ +def=isDefault; + setText(0,name); + setText(1,mail); + setText(2,id); +} + + +void UpdateViewItem2::paintCell(QPainter *p, const QColorGroup &cg,int column, int width, int alignment) +{ + if ((def) && (column<2)) { + QFont font(p->font()); + font.setBold(true); + p->setFont(font); + } + KListViewItem::paintCell(p, cg, column, width, alignment); +} + +QString UpdateViewItem2 :: key(int c,bool ) const +{ + return text(c).lower(); +} + +/////////////// main view + +popupPublic::popupPublic(QWidget *parent, const char *name,QString sfile,bool filemode,KShortcut goDefaultKey): +KDialogBase( Plain, i18n("Select Public Key"), Details | Ok | Cancel, Ok, parent, name,true) +{ + + QWidget *page = plainPage(); + QVBoxLayout *vbox=new QVBoxLayout(page,0,spacingHint()); + vbox->setAutoAdd(true); + + setButtonText(KDialogBase::Details,i18n("Options")); + + if (KGpgSettings::allowCustomEncryptionOptions()) + customOptions=KGpgSettings::customEncryptionOptions(); + + KIconLoader *loader = KGlobal::iconLoader(); + + keyPair=loader->loadIcon("kgpg_key2",KIcon::Small,20); + keySingle=loader->loadIcon("kgpg_key1",KIcon::Small,20); + keyGroup=loader->loadIcon("kgpg_key3",KIcon::Small,20); + + if (filemode) setCaption(i18n("Select Public Key for %1").arg(sfile)); + fmode=filemode; + + QHButtonGroup *hBar=new QHButtonGroup(page); + //hBar->setFrameStyle(QFrame::NoFrame); + hBar->setMargin(0); + +#if KDE_IS_VERSION( 3, 2, 90 ) + QToolButton *clearSearch = new QToolButton(hBar); + clearSearch->setTextLabel(i18n("Clear Search"), true); + clearSearch->setIconSet(SmallIconSet(QApplication::reverseLayout() ? "clear_left" + : "locationbar_erase")); + (void) new QLabel(i18n("Search: "),hBar); + KListViewSearchLine* listViewSearch = new KListViewSearchLine(hBar); + connect(clearSearch, SIGNAL(pressed()), listViewSearch, SLOT(clear())); +#endif + + keysList = new KListView( page ); + keysList->addColumn(i18n("Name")); + keysList->addColumn(i18n("Email")); + keysList->addColumn(i18n("ID")); + +#if KDE_IS_VERSION( 3, 2, 90 ) + listViewSearch->setListView(keysList); +#endif + + keysList->setRootIsDecorated(false); + page->setMinimumSize(540,200); + keysList->setShowSortIndicator(true); + keysList->setFullWidth(true); + keysList->setAllColumnsShowFocus(true); + keysList->setSelectionModeExt(KListView::Extended); + keysList->setColumnWidthMode(0,QListView::Manual); + keysList->setColumnWidthMode(1,QListView::Manual); + keysList->setColumnWidth(0,210); + keysList->setColumnWidth(1,210); + + boutonboxoptions=new QButtonGroup(5,Qt::Vertical ,page,0); + + KActionCollection *actcol=new KActionCollection(this); + (void) new KAction(i18n("&Go to Default Key"),goDefaultKey, this, SLOT(slotGotoDefaultKey()),actcol,"go_default_key"); + + + CBarmor=new QCheckBox(i18n("ASCII armored encryption"),boutonboxoptions); + CBuntrusted=new QCheckBox(i18n("Allow encryption with untrusted keys"),boutonboxoptions); + CBhideid=new QCheckBox(i18n("Hide user id"),boutonboxoptions); + setDetailsWidget(boutonboxoptions); + QWhatsThis::add + (keysList,i18n("Public keys list: select the key that will be used for encryption.")); + QWhatsThis::add + (CBarmor,i18n("ASCII encryption: makes it possible to open the encrypted file/message in a text editor")); + QWhatsThis::add + (CBhideid,i18n("Hide user ID: Do not put the keyid into encrypted packets. This option hides the receiver " + "of the message and is a countermeasure against traffic analysis. It may slow down the decryption process because " + "all available secret keys are tried.")); + QWhatsThis::add + (CBuntrusted,i18n("Allow encryption with untrusted keys: when you import a public key, it is usually " + "marked as untrusted and you cannot use it unless you sign it in order to make it 'trusted'. Checking this " + "box enables you to use any key, even if it has not be signed.")); + + if (filemode) { + QWidget *parentBox=new QWidget(boutonboxoptions); + QHBoxLayout *shredBox=new QHBoxLayout(parentBox,0); + //shredBox->setFrameStyle(QFrame::NoFrame); + //shredBox->setMargin(0); + CBshred=new QCheckBox(i18n("Shred source file"),parentBox); + QWhatsThis::add + (CBshred,i18n("Shred source file: permanently remove source file. No recovery will be possible")); + + QString shredWhatsThis = i18n( "Shred source file:

Checking this option will shred (overwrite several times before erasing) the files you have encrypted. This way, it is almost impossible that the source file is recovered.

But you must be aware that this is not secure on all file systems, and that parts of the file may have been saved in a temporary file or in the spooler of your printer if you previously opened it in an editor or tried to print it. Only works on files (not on folders).

"); + KActiveLabel *warn= new KActiveLabel( i18n("Read this before using shredding").arg(shredWhatsThis),parentBox ); + shredBox->addWidget(CBshred); + shredBox->addWidget(warn); + } + + CBsymmetric=new QCheckBox(i18n("Symmetrical encryption"),boutonboxoptions); + QWhatsThis::add + (CBsymmetric,i18n("Symmetrical encryption: encryption does not use keys. You just need to give a password " + "to encrypt/decrypt the file")); + QObject::connect(CBsymmetric,SIGNAL(toggled(bool)),this,SLOT(isSymetric(bool))); + + CBarmor->setChecked( KGpgSettings::asciiArmor() ); + CBuntrusted->setChecked( KGpgSettings::allowUntrustedKeys() ); + CBhideid->setChecked( KGpgSettings::hideUserID() ); + if (filemode) CBshred->setChecked( KGpgSettings::shredSource() ); + + if (KGpgSettings::allowCustomEncryptionOptions()) { + QHButtonGroup *bGroup = new QHButtonGroup(page); + //bGroup->setFrameStyle(QFrame::NoFrame); + (void) new QLabel(i18n("Custom option:"),bGroup); + KLineEdit *optiontxt=new KLineEdit(bGroup); + optiontxt->setText(customOptions); + QWhatsThis::add + (optiontxt,i18n("Custom option: for experienced users only, allows you to enter a gpg command line option, like: '--armor'")); + QObject::connect(optiontxt,SIGNAL(textChanged ( const QString & )),this,SLOT(customOpts(const QString & ))); + } + QObject::connect(keysList,SIGNAL(doubleClicked(QListViewItem *,const QPoint &,int)),this,SLOT(slotOk())); +// QObject::connect(this,SIGNAL(okClicked()),this,SLOT(crypte())); + QObject::connect(CBuntrusted,SIGNAL(toggled(bool)),this,SLOT(refresh(bool))); + + char line[200]="\0"; + FILE *fp2; + seclist=QString::null; + + fp2 = popen("gpg --no-secmem-warning --no-tty --with-colon --list-secret-keys ", "r"); + while ( fgets( line, sizeof(line), fp2)) + { + QString readLine=QString::fromUtf8(line); + if (readLine.startsWith("sec")) seclist+=", 0x"+readLine.section(":",4,4).right(8); + } + pclose(fp2); + + trusted=CBuntrusted->isChecked(); + + refreshkeys(); + setMinimumSize(550,200); + updateGeometry(); + keysList->setFocus(); + show(); +} + +popupPublic::~popupPublic() +{} + + +void popupPublic::slotAccept() +{ +accept(); +} + +void popupPublic::enable() +{ + QListViewItem *current = keysList->firstChild(); + if (current==NULL) + return; + current->setVisible(true); + while ( current->nextSibling() ) { + current = current->nextSibling(); + current->setVisible(true); + } + keysList->ensureItemVisible(keysList->currentItem()); +} + +void popupPublic::sort() +{ + bool reselect=false; + QListViewItem *current = keysList->firstChild(); + if (current==NULL) + return; + + if ((untrustedList.find(current->text(2))!=untrustedList.end()) && (!current->text(2).isEmpty())){ + if (current->isSelected()) { + current->setSelected(false); + reselect=true; + } + current->setVisible(false); + } + + while ( current->nextSibling() ) { + current = current->nextSibling(); + if ((untrustedList.find(current->text(2))!=untrustedList.end()) && (!current->text(2).isEmpty())) { + if (current->isSelected()) { + current->setSelected(false); + reselect=true; + } + current->setVisible(false); + } + } + + if (reselect || !keysList->currentItem()->isVisible()) { + QListViewItem *firstvisible; + firstvisible=keysList->firstChild(); + while (firstvisible->isVisible()!=true) { + firstvisible=firstvisible->nextSibling(); + if (firstvisible==NULL) + return; + } + keysList->setSelected(firstvisible,true); + keysList->setCurrentItem(firstvisible); + keysList->ensureItemVisible(firstvisible); + } +} + +void popupPublic::isSymetric(bool state) +{ + keysList->setEnabled(!state); + CBuntrusted->setEnabled(!state); + CBhideid->setEnabled(!state); +} + + +void popupPublic::customOpts(const QString &str) +{ + customOptions=str; +} + +void popupPublic::slotGotoDefaultKey() +{ + QListViewItem *myDefaulKey = keysList->findItem(KGpgSettings::defaultKey(),2); + keysList->clearSelection(); + keysList->setCurrentItem(myDefaulKey); + keysList->setSelected(myDefaulKey,true); + keysList->ensureItemVisible(myDefaulKey); +} + +void popupPublic::refresh(bool state) +{ + if (state) + enable(); + else + sort(); +} + +void popupPublic::refreshkeys() +{ + keysList->clear(); + QStringList groups= QStringList::split(",", KGpgSettings::groups()); + if (!groups.isEmpty()) + { + for ( QStringList::Iterator it = groups.begin(); it != groups.end(); ++it ) + { + if (!QString(*it).isEmpty()) + { + UpdateViewItem2 *item=new UpdateViewItem2(keysList,QString(*it),QString::null,QString::null,false); + item->setPixmap(0,keyGroup); + } + } + } + KProcIO *encid=new KProcIO(QTextCodec::codecForLocale()); + *encid << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-keys"; + ///////// when process ends, update dialog infos + QObject::connect(encid, SIGNAL(processExited(KProcess *)),this, SLOT(slotpreselect())); + QObject::connect(encid, SIGNAL(readReady(KProcIO *)),this, SLOT(slotprocread(KProcIO *))); + encid->start(KProcess::NotifyOnExit,true); +} + +void popupPublic::slotpreselect() +{ +QListViewItem *it=NULL; +if (!keysList->firstChild()) return; + if (fmode) it=keysList->findItem(KGpgSettings::defaultKey(),2); +if (!trusted) + sort(); +if (fmode) +{ + keysList->clearSelection(); + keysList->setSelected(it,true); + keysList->setCurrentItem(it); + keysList->ensureItemVisible(it); +} +emit keyListFilled(); +} + +void popupPublic::slotSetVisible() +{ + keysList->ensureItemVisible(keysList->currentItem()); +} + +void popupPublic::slotprocread(KProcIO *p) +{ + ///////////////////////////////////////////////////////////////// extract encryption keys + bool dead; + QString tst,keyname,keymail; + + QString defaultKey = KGpgSettings::defaultKey().right(8); + + while (p->readln(tst)!=-1) { + if (tst.startsWith("pub")) { + QStringList keyString=QStringList::split(":",tst,true); + dead=false; + const QString trust=keyString[1]; + QString val=keyString[6]; + QString id=QString("0x"+keyString[4].right(8)); + if (val.isEmpty()) + val=i18n("Unlimited"); + QString tr; + switch( trust[0] ) { + case 'o': + untrustedList<setSelectable(false); + if (seclist.find(tst,0,FALSE)!=-1) + item->setPixmap(0,keyPair); + else + item->setPixmap(0,keySingle); + } + } + } +} + + +void popupPublic::slotOk() +{ + ////// emit selected data +kdDebug(2100)<<"Ok pressed"< list=keysList->selectedItems(); + + for ( uint i = 0; i < list.count(); ++i ) + if ( list.at(i) && list.at(i)->isVisible()) { + if (!list.at(i)->text(2).isEmpty()) selectedKeys<text(2); + else selectedKeys<text(0); + } + if (selectedKeys.isEmpty() && !CBsymmetric->isChecked()) + return; + if (CBsymmetric->isChecked()) selectedKeys=NULL; +kdDebug(2100)<<"Selected Key:"<isChecked()) + returnOptions<<"--always-trust"; + if (CBarmor->isChecked()) + returnOptions<<"--armor"; + if (CBhideid->isChecked()) + returnOptions<<"--throw-keyid"; + if ((KGpgSettings::allowCustomEncryptionOptions()) && (!customOptions.stripWhiteSpace().isEmpty())) + returnOptions.operator+ (QStringList::split(QString(" "),customOptions.simplifyWhiteSpace())); + //hide(); + if (fmode) + emit selectedKey(selectedKeys,returnOptions,CBshred->isChecked(),CBsymmetric->isChecked()); + else + emit selectedKey(selectedKeys,returnOptions,false,CBsymmetric->isChecked()); + accept(); +} + +#include "popuppublic.moc" diff --git a/kgpg/popuppublic.h b/kgpg/popuppublic.h new file mode 100644 index 0000000..e0d2bb5 --- /dev/null +++ b/kgpg/popuppublic.h @@ -0,0 +1,76 @@ +/*************************************************************************** + popuppublic.h - description + ------------------- + begin : Sat Jun 29 2002 + copyright : (C) 2002 by Jean-Baptiste Mardelle + email : bj@altern.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef POPUPPUBLIC_H +#define POPUPPUBLIC_H + +#include + +//#include +#include + + +class QPushButton; +class QCheckBox; +class KListView; +class QButtonGroup; +class KProcIO; + +class popupPublic : public KDialogBase //QDialog +{ + Q_OBJECT +public: + + popupPublic(QWidget *parent=0, const char *name=0,QString sfile="",bool filemode=false,KShortcut goDefaultKey=QKeySequence(CTRL+Qt::Key_Home)); + ~popupPublic(); + KListView *keysList; + QCheckBox *CBarmor,*CBuntrusted,*CBshred,*CBsymmetric,*CBhideid; + bool fmode,trusted; + QPixmap keyPair,keySingle,keyGroup; + QString seclist; + QStringList untrustedList; + +private: + KConfig *config; + QButtonGroup *boutonboxoptions; + QString customOptions; + +private slots: + void customOpts(const QString &); + void slotprocread(KProcIO *); + void slotpreselect(); + void refreshkeys(); + void refresh(bool state); + void isSymetric(bool state); + void sort(); + void enable(); + void slotGotoDefaultKey(); + +public slots: +void slotAccept(); +void slotSetVisible(); + +protected slots: +virtual void slotOk(); + +signals: + void selectedKey(QStringList ,QStringList,bool,bool); + void keyListFilled(); + +}; + +#endif // POPUPPUBLIC_H + diff --git a/kgpg/searchres.ui b/kgpg/searchres.ui new file mode 100644 index 0000000..0c81fcd --- /dev/null +++ b/kgpg/searchres.ui @@ -0,0 +1,124 @@ + +searchRes + + + searchRes + + + + 0 + 0 + 415 + 305 + + + + + unnamed + + + 0 + + + + statusText + + + + + + + + textLabel1 + + + Key to import: + + + + + kLEID + + + + + + Name + + + true + + + true + + + + + Email + + + true + + + true + + + + + Creation + + + true + + + true + + + + + ID + + + true + + + true + + + + kLVsearch + + + Extended + + + true + + + true + + + true + + + LastColumn + + + true + + + false + + + + + + kLVsearch + kLEID + + + + klineedit.h + klistview.h + + diff --git a/kgpg/sourceselect.ui b/kgpg/sourceselect.ui new file mode 100644 index 0000000..faf0dee --- /dev/null +++ b/kgpg/sourceselect.ui @@ -0,0 +1,112 @@ + +SrcSelect + + + SrcSelect + + + + 0 + 0 + 350 + 93 + + + + + 5 + 5 + 0 + 0 + + + + + 350 + 0 + + + + + unnamed + + + 0 + + + + buttonGroup2 + + + + + + + unnamed + + + + checkFile + + + File: + + + true + + + + + newFilename + + + true + + + + + checkClipboard + + + Clipboard + + + + + + + spacer2 + + + Vertical + + + Expanding + + + + 20 + 31 + + + + + + + + checkFile + toggled(bool) + SrcSelect + checkFile_toggled(bool) + + + + checkFile_toggled( bool isOn ) + + + + kurlrequester.h + klineedit.h + kpushbutton.h + + diff --git a/kgpg/tips b/kgpg/tips new file mode 100644 index 0000000..cc3f0bf --- /dev/null +++ b/kgpg/tips @@ -0,0 +1,44 @@ + + +

If you want to decrypt a text file, simply drag and drop it into the editor window. Kgpg will do the rest. Even remote files can be dropped.

+

Drag a public key into the editor window and kgpg will automatically import it if you want.

+ + + +

The easiest way to encrypt a file: simply right click on the file, and you have an encrypt option in the contextual menu. +This works in konqueror or on your Desktop!

+ +
+ + +

If you want to encrypt a message for several persons, just select several encryption keys by pressing the "Ctrl" key.

+ +
+ + +

You don't know anything about encryption?
+No problem, simply create yourself a key pair in the key management window. Then, export your public key & mail it to your friends.
+Ask them to do the same & import their public keys. Finally, to send an encrypted message, type it in the Kgpg editor, then click "encrypt". Choose +your friend key and click "encrypt" again. The message will be encrypted, ready to be sent by email.

+ +
+ + +

To perform an operation on a key, open the key management window & right click on the key. A popup menu with all available options will appear.

+ +
+ + +

Decrypt a file with a single mouse click on it. You will then be prompted for password & that's all!

+ +
+ + +

If you only want to open the key manager, type "kgpg -k" in the command line prompt.

+ +
+ + +

Typing "kgpg -s filename" will decrypt the file filename and open it in Kgpg's editor.

+ +
diff --git a/khexedit/Makefile.am b/khexedit/Makefile.am new file mode 100644 index 0000000..bacaa75 --- /dev/null +++ b/khexedit/Makefile.am @@ -0,0 +1,35 @@ +INCLUDES = $(all_includes) + +SUBDIRS = pics lib parts + +bin_PROGRAMS = khexedit + +khexedit_SOURCES = main.cc toplevel.cc hexmanagerwidget.cc \ +hexeditorwidget.cc hextoolwidget.cc hexviewwidget.cc hexbuffer.cc \ +conversion.cc dialog.cc hexvalidator.cc hexclipboard.cc \ +optiondialog.cc printdialogpage.cc statusbarprogress.cc \ +hexprinter.cc hexerror.cc draglabel.cc stringdialog.cc \ +bitswapwidget.cc chartabledialog.cc hexdrag.cc exportdialog.cc \ +fileinfodialog.cc converterdialog.cc listview.cc searchbar.cc + +noinst_HEADERS = toplevel.h hexmanagerwidget.h hexeditorwidget.h \ +hextoolwidget.h hexviewwidget.h hexbuffer.h conversion.h dialog.h \ +hexvalidator.h hexclipboard.h optiondialog.h \ +printdialogpage.h statusbarprogress.h hexprinter.h hexerror.h \ +draglabel.h progress.h hexeditstate.h chartabledialog.h hexdrag.h \ +exportdialog.h fileinfodialog.h converterdialog.h listview.h searchbar.h + +khexedit_METASOURCES = AUTO +khexedit_LDFLAGS = $(all_libraries) $(KDE_RPATH) +khexedit_LDADD = $(LIB_KIO) $(LIB_KDEPRINT) + +xdg_apps_DATA = khexedit.desktop + +KDE_ICON = khexedit + +rcdir = $(kde_datadir)/khexedit +rc_DATA = khexeditui.rc + +messages: rc.cpp + $(EXTRACTRC) parts/kpart/*rc >> rc.cpp + $(XGETTEXT) rc.cpp `find . -name \*.cc -o -name \*.cpp` -o $(podir)/khexedit.pot diff --git a/khexedit/README b/khexedit/README new file mode 100644 index 0000000..ef686b7 --- /dev/null +++ b/khexedit/README @@ -0,0 +1,34 @@ +Overview +-------- +To confuse you these directories mix two binary editor projects. +The first project is the current khexedit app from Espen Sand, +(here called KHE1). The second project is the coming khexedit app +from Friedrich W. H. Kossebau (called KHE2) which has been already +partly moved from kdenonbeta/khexedit2. + + +What to find in which directory: +-------------------------------- +khexedit: + sources of KHE1 + +khexedit/pics: + pictures used by KHE1 + +khexedit/lib: + sources of the basic library of KHE2 + +khexedit/parts: + collection of all parts based on KHE2 + +khexedit/parts/kbytesedit: + sources of the implementation for the service type KHexEdit/KBytesEdit + + +Future plans: +------------- +* inclusion of the KReadWritePart based HexEdit2Part which can handle + GB sized files. (-> KDE 3.3) +* a binary diff editor widget in the KHE2 lib +* binary diff editor widget based parts +* a standalone KHE2 app, replacing KHE1 diff --git a/khexedit/bitswapwidget.cc b/khexedit/bitswapwidget.cc new file mode 100644 index 0000000..212d126 --- /dev/null +++ b/khexedit/bitswapwidget.cc @@ -0,0 +1,323 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include + +#include "bitswapwidget.h" + +CDigitLabel::CDigitLabel( QWidget *parent, uint digit, const char *name ) + :QLabel(parent, name), mDigit( digit ), mDotPosition( 0 ) +{ + setFocusPolicy( StrongFocus ); + initialize(); +} + +CDigitLabel::~CDigitLabel( void ) +{ + +} + +void CDigitLabel::initialize( void ) +{ + QFont font( KGlobalSettings::generalFont() ); + font.setBold( true ); + setFont( font ); +} + + +void CDigitLabel::paletteChange( const QPalette & ) +{ + update(); +} + + +void CDigitLabel::setValue( uint digit, bool notify ) +{ + if( mDigit != digit ) + { + if( notify == true ) + { + emit valueChanged( this, digit, false ); + } + + mDigit = digit; + update(); + + if( notify == true ) + { + emit valueChanged( this, mDigit, true ); + } + } +} + + +void CDigitLabel::setDotPosition( uint dotPosition ) +{ + if( mDotPosition != dotPosition ) + { + mDotPosition = dotPosition; + update(); + } +} + + + +QSize CDigitLabel::sizeHint( void ) const +{ + int h = fontMetrics().height(); + QSize s( h, h ); // Retangular + return( s ); +} + + +#include + + +void CDigitLabel::drawContents( QPainter *p ) +{ + QRect cr = contentsRect(); + + if( hasFocus() == true ) + { + p->fillRect( cr, palette().active().highlight() ); + p->setPen( palette().active().highlightedText() ); + } + else + { + p->fillRect( cr, palette().active().base() ); + p->setPen( palette().active().text() ); + } + + if( mDotPosition != 0 ) + { + p->fillRect( cr.x()+2, cr.y()+2, 5, 5, Qt::red ); // UL + /* + if( mDotPosition == 1 ) + { + p->fillRect( cr.x()+2, cr.y()+2, 5, 5, red ); // UL + } + else if( mDotPosition == 2 ) + { + p->fillRect( cr.width()-7, cr.y()+2, 5, 5, red ); // UR + } + else if( mDotPosition == 3 ) + { + p->fillRect( cr.x()+2, cr.height()-7, 5, 5, red ); // LL + } + else if( mDotPosition == 4 ) + { + p->fillRect( cr.width()-7, cr.height()-7, 5, 5, red ); // LR + } + */ + } + + QString text; + text.setNum( mDigit ); + p->drawText( 0, 0, cr.width(), cr.height(), alignment(), text ); + + + +} + + +void CDigitLabel::keyPressEvent( QKeyEvent *e ) +{ + switch ( e->key() ) + { + case Key_Left: + case Key_Up: + emit stepCell( this, false ); + break; + + case Key_Right: + case Key_Down: + emit stepCell( this, true ); + break; + + case Key_Escape: + e->ignore(); // Allow dialog or whatever use this one + return; + break; + + default: + { + int val = e->text()[0].digitValue(); + if( val >= 0 && val <= 7 ) + { + setValue( val, true ); + } + } + break; + } + + e->accept(); +} + + + +CByteWidget::CByteWidget( QWidget *parent, const char *name ) + :QWidget(parent, name) +{ + mHBox = new QHBoxLayout( this, 0 ); + + for( uint i=0; i<8; i++ ) + { + mDigit[i] = new CDigitLabel( this, 7-i ); + mDigit[i]->setLineWidth( 1 ); + mDigit[i]->setFixedSize( mDigit[i]->sizeHint()*2 ); + mDigit[i]->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + mDigit[i]->setAlignment( AlignCenter ); + connect( mDigit[i], SIGNAL(stepCell(const QObject *, bool )), + this, SLOT(stepCell(const QObject *, bool ))); + connect( mDigit[i], SIGNAL(valueChanged(const QObject *, uint, bool )), + this, SLOT(valueChanged(const QObject *, uint, bool ))); + mHBox->addWidget( mDigit[i] ); + } + + mHBox->addStretch(); +} + +CByteWidget::~CByteWidget( void ) +{ + for( uint i=0; i<8; i++ ) { delete mDigit[i]; } + delete mHBox; +} + +void CByteWidget::stepCell( const QObject *obj, bool next ) +{ + for( uint i=0; i<8; i++ ) + { + if( obj == mDigit[i] ) + { + if( next == true ) + { + mDigit[(i+1)%8]->setFocus(); + } + else + { + mDigit[(i+7)%8]->setFocus(); + } + } + } +} + + + +void CByteWidget::valueChanged( const QObject *obj, uint val, bool after ) +{ + if( after == false ) + { + for( uint i=0; i<8; i++ ) + { + if( obj == mDigit[i] ) + { + uint tmp = 7-mDigit[i]->value(); + mDigit[tmp]->setValue( mDigit[i]->value(), false ); + break; + } + } + + + if( mDigit[7-val]->value() != val ) + { + uint tmp = mDigit[7-val]->value(); + mDigit[7-tmp]->setValue( tmp, false ); + mDigit[7-val]->setValue( val, false ); + } + + } + else + { + setBuddy( obj ); + + uint pos = 1; + for( uint i=0; i<8; i++ ) + { + if( mDigit[i]->value() < (7-i) ) + { + mDigit[i]->setDotPosition( pos ); + mDigit[7-mDigit[i]->value()]->setDotPosition( pos ); + pos++; + } + else if( mDigit[i]->value() == (7-i) ) + { + mDigit[i]->setDotPosition( 0 ); + } + } + + } +} + + +void CByteWidget::reset( void ) +{ + for( uint i=0; i<8; i++ ) + { + mDigit[i]->setValue( 7-i, false ); + mDigit[i]->setDotPosition( 0 ); + } +} + + +void CByteWidget::setBuddy( const QObject *obj ) +{ + for( uint i=0; i<8; i++ ) + { + if( obj == mDigit[i] ) + { + uint val = mDigit[i]->value(); + if( val < 8 ) + { + mDigit[7-val]->setValue( 7-i, false ); + } + break; + } + } +} + + + + + +bool CByteWidget::flag( QByteArray &buf ) +{ + bool swapPresent = false; + uint i, j; + + buf.resize( 8 ); + for( i=0; i<8; buf[i++] = 0 ); + + for( i=j=0; i<8; i++ ) + { + if( mDigit[i]->value() < (7-i) ) + { + buf[j] = 7 - i; j++; + buf[j] = mDigit[i]->value(); j++; + swapPresent = true; + } + } + + return( swapPresent ); +} + + +#include "bitswapwidget.moc" diff --git a/khexedit/bitswapwidget.h b/khexedit/bitswapwidget.h new file mode 100644 index 0000000..f1d3582 --- /dev/null +++ b/khexedit/bitswapwidget.h @@ -0,0 +1,101 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _BITSWAP_WIDGET_H_ +#define _BITSWAP_WIDGET_H_ + +#include +#include +#include + + +class CDigitLabel : public QLabel +{ + Q_OBJECT + + public: + CDigitLabel( QWidget *parent, uint digit = 0, const char *name=0 ); + ~CDigitLabel( void ); + + virtual QSize sizeHint() const; + inline uint value( void ); + + signals: + void stepCell( const QObject *obj, bool next ); + void valueChanged( const QObject *obj, uint newVal, bool after ); + + public slots: + void setValue( uint digit, bool notify ); + void setDotPosition( uint dotPosition ); + + protected: + void paletteChange( const QPalette & ); + void drawContents( QPainter * ); + virtual void keyPressEvent( QKeyEvent *e ); + + private: + void initialize( void ); + + private: + uint mDigit; + uint mDotPosition; +}; + + +inline uint CDigitLabel::value( void ) +{ + return( mDigit ); +} + + + + +class CByteWidget : public QWidget +{ + Q_OBJECT + + public: + CByteWidget( QWidget *parent, const char *name=0 ); + ~CByteWidget( void ); + + bool flag( QByteArray &buf ); + + public slots: + void reset( void ); + + private slots: + void stepCell( const QObject *obj, bool next ); + void valueChanged( const QObject *obj, uint newVal, bool after ); + + private: + void setBuddy( const QObject *obj ); + + private: + QHBoxLayout *mHBox; + CDigitLabel *mDigit[8]; +}; + + + + + + + +#endif diff --git a/khexedit/chartabledialog.cc b/khexedit/chartabledialog.cc new file mode 100644 index 0000000..1914750 --- /dev/null +++ b/khexedit/chartabledialog.cc @@ -0,0 +1,212 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "chartabledialog.h" + + +CCharTableDialog::CCharTableDialog( QWidget *parent, const char *name, + bool modal ) + :KDialogBase( Plain, i18n("Character Table"), Help|User1|Cancel, User1, + parent, name, modal, true, KStdGuiItem::insert()) +{ + updateGeometry(); + setHelp( "khexedit/khexedit.html", QString::null ); + + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + mCharacterList = new CListView( plainPage(), "characterList" ); + mCharacterList->setFont( KGlobalSettings::fixedFont() ); + mCharacterList->addColumn( i18n("Decimal") ); + mCharacterList->addColumn( i18n("Hexadecimal") ); + mCharacterList->addColumn( i18n("Octal") ); + mCharacterList->addColumn( i18n("Binary") ); + mCharacterList->addColumn( i18n("Text") ); + mCharacterList->setAllColumnsShowFocus( true ); + mCharacterList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken ); + mCharacterList->setSorting( -1 ); + + // + // I am setting the min. size below + // + //connect( mCharacterList, SIGNAL(doubleClicked(QListViewItem *) ), + //SLOT(startAssign(QListViewItem *))); + + topLayout->addWidget( mCharacterList, 10 ); + + QHBoxLayout *hbox = new QHBoxLayout(); + if( hbox == 0 ) { return; } + topLayout->addLayout( hbox ); + + text = i18n("Insert this number of characters:"); + QLabel *label = new QLabel( text, plainPage() ); + label->setFixedWidth( label->sizeHint().width() ); + hbox->addWidget( label ); + + mInputCountSpin = new QSpinBox( plainPage(), "spin" ); + mInputCountSpin->setMinimumWidth( fontMetrics().maxWidth()*7 ); + mInputCountSpin->setRange( 1, INT_MAX ); + mInputCountSpin->setValue( 1 ); + hbox->addWidget( mInputCountSpin ); + + hbox->addStretch ( 10 ); + + createListData(); + setColumnWidth(); + mCharacterList->setVisibleItem( 15 ); +} + + + +CCharTableDialog::~CCharTableDialog( void ) +{ +} + + +const char *printBinary( uint val ) +{ + static char buf[9]; + for( int i = 0; i < 8; i++ ) + { + buf[7-i] = (val&(1<setSelected( item, true ); + } + + } +} + + +void CCharTableDialog::slotUser1( void ) // Insert +{ + QListViewItem *item = mCharacterList->selectedItem(); + if( item != 0 ) + { + startAssign( item ); + } + +} + +void CCharTableDialog::startAssign( QListViewItem *item ) +{ + QByteArray buf; + if( buf.fill( item->text(0).toInt(), mInputCountSpin->value() ) == false ) + { + return; + } + emit assign( buf ); +} + + +void CCharTableDialog::setColumnWidth( void ) +{ + const QFontMetrics &fm = mCharacterList->fontMetrics(); + int w0, w1, w2, w3, w4; + + w0 = -fm.minLeftBearing() - fm.minRightBearing() + 8 + fm.maxWidth(); + w3 = 0; + + w1 = fm.width( mCharacterList->header()->label(0) ) + w0; + w2 = fm.width('0')*5; + w3 += w1 > w2 ? w1 : w2; + mCharacterList->setColumnWidth( 0, w1 > w2 ? w1 : w2 ); + + w1 = fm.boundingRect( mCharacterList->header()->label(1) ).width() + w0; + w2 = fm.width('0')*6; + w3 += w1 > w2 ? w1 : w2; + mCharacterList->setColumnWidth( 1, w1 > w2 ? w1 : w2 ); + + w1 = fm.boundingRect( mCharacterList->header()->label(2) ).width() + w0; + w2 = fm.width('0')*5; + w3 += w1 > w2 ? w1 : w2; + mCharacterList->setColumnWidth( 2, w1 > w2 ? w1 : w2 ); + + w1 = fm.boundingRect( mCharacterList->header()->label(3) ).width() + w0; + w2 = fm.width('0')*10; + w3 += w1 > w2 ? w1 : w2; + mCharacterList->setColumnWidth( 3, w1 > w2 ? w1 : w2 ); + + w4 = mCharacterList->viewport()->width() - w3; + w1 = fm.boundingRect( mCharacterList->header()->label(4) ).width() + w0; + w2 = fm.width('0')*3; + w1 = w1 > w2 ? w1 : w2; + mCharacterList->setColumnWidth( 4, w1 > w4 ? w1 : w4 ); +} + + +void CCharTableDialog::resizeEvent( QResizeEvent * ) +{ + setColumnWidth(); +} + + +void CCharTableDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + setColumnWidth(); + mCharacterList->setFocus(); +} + + +#include "chartabledialog.moc" diff --git a/khexedit/chartabledialog.h b/khexedit/chartabledialog.h new file mode 100644 index 0000000..a35246b --- /dev/null +++ b/khexedit/chartabledialog.h @@ -0,0 +1,72 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _CHAR_TABLE_DIALOG_H_ +#define _CHAR_TABLE_DIALOG_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +class QLabel; +class QSpinBox; + +#include +#include "listview.h" + + +class CCharTableDialog : public KDialogBase +{ + Q_OBJECT + + public: + CCharTableDialog( QWidget *parent=0, const char *name=0,bool modal=false ); + ~CCharTableDialog( void ); + + signals: + void assign( const QByteArray &buf ); + + protected slots: + virtual void slotUser1( void ); + virtual void startAssign( QListViewItem * ); + + protected: + virtual void resizeEvent( QResizeEvent *e ); + virtual void showEvent( QShowEvent *e ); + + private: + void createListData( void ); + void setColumnWidth( void ); + + private: + QSpinBox *mInputCountSpin; + CListView *mCharacterList; +}; + +#endif + + + + + + + + + diff --git a/khexedit/configure.in.in b/khexedit/configure.in.in new file mode 100644 index 0000000..8f094fa --- /dev/null +++ b/khexedit/configure.in.in @@ -0,0 +1,8 @@ +# kossebau: copied from kdelibs/configure.in.in for khexedit +AC_LANG_SAVE +AC_LANG_C +dnl AC_C_BIGENDIAN has a bug (one of its tests uses "main()" instead of +dnl "int main()") so C++ compilers would break. Thats why we switch languages +AC_C_BIGENDIAN +AC_LANG_RESTORE +# kossebau end diff --git a/khexedit/conversion.cc b/khexedit/conversion.cc new file mode 100644 index 0000000..7a5c25c --- /dev/null +++ b/khexedit/conversion.cc @@ -0,0 +1,395 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include + +#include "conversion.h" + + +CConversion::CConversion( void ) +{ + setMode( cnvDefault ); +} + + +CConversion::EMode CConversion::mode( void ) +{ + return( (EMode)mState.mode ); +} + +const SEncodeState &CConversion::state( void ) +{ + return( mState ); +} + +QString CConversion::names( unsigned int index ) +{ + static const QString strings[4] = + { + i18n("Default encoding", "Default"), + i18n("EBCDIC"), + i18n("US-ASCII (7 bit)"), + i18n("Unknown"), + }; + + return( strings[ index > cnvUsAscii ? 3 : index ] ); +} + + +const unsigned char *CConversion::tables( EMode cnvMode ) +{ + /* + static unsigned char ebcdicToLatin1[256] = + { + 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, + 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, + 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, + 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, + 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, + 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, + 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, + 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, + 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, + 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, + 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, + 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, + 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, + 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, + 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE, + 0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, + 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7, + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, + 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F + }; + */ + + static unsigned char ebcdicToLatin1[256] = + { + 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, + 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, + 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, + 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, + 0x20, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21, + 0x26, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E, + 0x2D, 0x2F, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, + 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, + 0xC2, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, + 0xC3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, + 0xCA, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + 0x71, 0x72, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, + 0xD1, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7A, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, + 0x5C, 0x9F, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5A, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, + }; + + static unsigned char buf[256]; + + + if( cnvMode == cnvEbcdic ) + { + return( ebcdicToLatin1 ); + } + else if( cnvMode == cnvUsAscii ) + { + memset( buf, 0, 256 ); + for( unsigned int i=0; i<127; i++ ) { buf[i] = i; } + return( buf ); + } + else if( cnvMode == cnvDefault ) + { + for( unsigned int i=0; i<256; i++ ) { buf[i] = i; } + return( buf ); + } + else + { + return( 0 ); + } +} + + +void CConversion::setMode( EMode cnvMode ) +{ + const unsigned char *table = tables( cnvMode ); + if( table == 0 ) + { + cnvMode = cnvDefault; + table = tables( cnvMode ); + } + + mState.mode = cnvMode; + mState.name = names( mState.mode ); + memcpy( mData, table, 256 ); +} + + +bool CConversion::lossless( EMode cnvMode ) +{ + const unsigned char *table = tables( cnvMode ); + if( table == 0 ) + { + return( false ); + } + + unsigned char flag[256]; + memset( flag, 0, sizeof( flag ) ); + + for( uint i=0; i<256; i++ ) + { + int index = table[i]; + if( flag[index] != 0 ) + { + return( false ); + } + flag[index] += 1; + } + + return( true ); +} + + + +#if 0 +void CConversion::setMode( EMode cnvMode ) +{ + /* + static unsigned char ebcdicToLatin1[256] = + { + 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, + 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, + 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, + 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, + 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, + 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, + 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, + 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, + 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, + 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, + 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, + 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, + 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, + 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, + 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE, + 0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, + 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7, + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, + 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F + }; + */ + + static unsigned char ebcdicToLatin1[256] = + { + 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, + 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, + 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, + 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, + 0x20, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21, + 0x26, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E, + 0x2D, 0x2F, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, + 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, + 0xC2, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, + 0xC3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, + 0xCA, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + 0x71, 0x72, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, + 0xD1, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7A, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, + 0x5C, 0x9F, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5A, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, + }; + + + if( cnvMode == cnvEbcdic ) + { + memcpy( mData, ebcdicToLatin1, 256 ); + } + else if( cnvMode == cnvUsAscii ) + { + memset( mData, 0, 256 ); + for( unsigned int i=0; i<127; i++ ) { mData[i] = i; } + } + else + { + for( unsigned int i=0; i<256; i++ ) { mData[i] = i; } + cnvMode = cnvDefault; + } + + mState.mode = cnvMode; + mState.name = names( mState.mode ); +} +#endif + + + + +int CConversion::convert( QByteArray &buf, EMode newMode, CProgress &p ) +{ + if( newMode == mode() ) + { + p.finish(); + return( Err_Success ); + } + + if( buf.isEmpty() ) + { + p.finish(); + setMode( newMode ); + return( Err_Success ); + } + + // + // Make backup + // + const QByteArray tmp( buf.copy() ); + if( tmp.isEmpty() ) + { + p.finish(); + return( Err_NoMemory ); + } + + unsigned char rev[256]; + uint i, sum; + + sum = 0; + + const float total = buf.size() * 2.0; + + // + // Prepare reverse buffer. + // + for( i=0; i < 256; i++ ) + { + rev[(unsigned char)mData[i]] = i; + } + + // + // Normalize + // + for( i=0; i + +#include "progress.h" + + +struct SEncodeState +{ + unsigned int mode; + QString name; +}; + + +class CConversion +{ + public: + enum EMode + { + cnvDefault = 0, + cnvEbcdic, + cnvUsAscii + }; + + public: + CConversion( void ); + + int convert( QByteArray &buf, EMode mode, CProgress &p ); + bool lossless( EMode cnvMode ); + + EMode mode( void ); + const SEncodeState &state( void ); + + unsigned char operator[]( unsigned int i ) const + { + return( mData[i] ); + } + + private: + QString names( unsigned int index ); + const unsigned char *tables( EMode cnvMode ); + void setMode( EMode cnvMode ); + + private: + SEncodeState mState; + unsigned char mData[256]; +}; + + +#endif diff --git a/khexedit/converterdialog.cc b/khexedit/converterdialog.cc new file mode 100644 index 0000000..f8dd9be --- /dev/null +++ b/khexedit/converterdialog.cc @@ -0,0 +1,163 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include +#include + +#include + +#include "converterdialog.h" +#include "hexvalidator.h" + + +CValidateLineEdit::CValidateLineEdit( QWidget *parent, int validateType, + const char *name ) + :QLineEdit( parent, name ), mBusy(false) +{ + mValidator = new CHexValidator( this, (CHexValidator::EState)validateType ); + setValidator( mValidator ); + connect( this, SIGNAL(textChanged(const QString &)), + this, SLOT(convertText(const QString &)) ); +} + + +CValidateLineEdit::~CValidateLineEdit( void ) +{ +} + + +void CValidateLineEdit::setData( const QByteArray &buf ) +{ + if( mBusy == false ) + { + QString text; + mValidator->format( text, buf ); + setText( text ); + } +} + + +void CValidateLineEdit::convertText( const QString &text ) +{ + QByteArray buf; + mValidator->convert( buf, text ); + mBusy = true; // Don't update while editing + emit dataChanged( buf ); + mBusy = false; +} + + + +CConverterDialog::CConverterDialog( QWidget *parent, const char *name, + bool modal ) + :KDialogBase( parent, name, modal, i18n("Converter"), Cancel|User2|User1, + Cancel, true, KStdGuiItem::clear(), i18n("&On Cursor") ) +{ + QWidget *page = new QWidget( this ); + setMainWidget( page ); + + QGridLayout *topLayout = new QGridLayout( page, 6, 2, 0, spacingHint() ); + topLayout->setRowStretch( 5, 10 ); + topLayout->setColStretch( 1, 10 ); + + QLabel *label = new QLabel( i18n("Hexadecimal:"), page ); + topLayout->addWidget( label, 0, 0 ); + label = new QLabel( i18n("Decimal:"), page ); + topLayout->addWidget( label, 1, 0 ); + label = new QLabel( i18n("Octal:"), page ); + topLayout->addWidget( label, 2, 0 ); + label = new QLabel( i18n("Binary:"), page ); + topLayout->addWidget( label, 3, 0 ); + label = new QLabel( i18n("Text:"), page ); + topLayout->addWidget( label, 4, 0 ); + + mHexInput = new CValidateLineEdit( page, CHexValidator::hexadecimal ); + mHexInput->setMinimumWidth( fontMetrics().maxWidth()*17 ); + topLayout->addWidget( mHexInput, 0, 1 ); + mDecInput = new CValidateLineEdit( page, CHexValidator::decimal ); + topLayout->addWidget( mDecInput, 1, 1 ); + mOctInput = new CValidateLineEdit( page, CHexValidator::octal ); + topLayout->addWidget( mOctInput, 2, 1 ); + mBinInput = new CValidateLineEdit( page, CHexValidator::binary ); + topLayout->addWidget( mBinInput, 3, 1 ); + mTxtInput = new CValidateLineEdit( page, CHexValidator::regularText ); + topLayout->addWidget( mTxtInput, 4, 1 ); + + connect( mHexInput, SIGNAL(dataChanged(const QByteArray &)), + this, SLOT(setData(const QByteArray &)) ); + connect( mDecInput, SIGNAL(dataChanged(const QByteArray &)), + this, SLOT(setData(const QByteArray &)) ); + connect( mOctInput, SIGNAL(dataChanged(const QByteArray &)), + this, SLOT(setData(const QByteArray &)) ); + connect( mBinInput, SIGNAL(dataChanged(const QByteArray &)), + this, SLOT(setData(const QByteArray &)) ); + connect( mTxtInput, SIGNAL(dataChanged(const QByteArray &)), + this, SLOT(setData(const QByteArray &)) ); + +} + + +CConverterDialog::~CConverterDialog( void ) +{ +} + + +void CConverterDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + mHexInput->setFocus(); +} + + +void CConverterDialog::setData( const QByteArray &data ) +{ + mHexInput->blockSignals(true); + mDecInput->blockSignals(true); + mOctInput->blockSignals(true); + mBinInput->blockSignals(true); + mTxtInput->blockSignals(true); + mHexInput->setData(data); + mDecInput->setData(data); + mOctInput->setData(data); + mBinInput->setData(data); + mTxtInput->setData(data); + mHexInput->blockSignals(false); + mDecInput->blockSignals(false); + mOctInput->blockSignals(false); + mBinInput->blockSignals(false); + mTxtInput->blockSignals(false); +} + +void CConverterDialog::slotUser1( void ) // Clear +{ + QByteArray buf; + setData( buf ); +} + +void CConverterDialog::slotUser2( void ) // On Cursor +{ + QByteArray buf; + emit probeCursorValue( buf, 1 ); + setData( buf ); +} + + +#include "converterdialog.moc" diff --git a/khexedit/converterdialog.h b/khexedit/converterdialog.h new file mode 100644 index 0000000..f84fe66 --- /dev/null +++ b/khexedit/converterdialog.h @@ -0,0 +1,83 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _CONVERTER_DIALOG_H_ +#define _CONVERTER_DIALOG_H_ + +#include +#include + +class CHexValidator; + + +class CValidateLineEdit : public QLineEdit +{ + Q_OBJECT + + public: + CValidateLineEdit( QWidget *parent, int validateType, const char *name=0 ); + ~CValidateLineEdit( void ); + + public slots: + void setData( const QByteArray &buf ); + + private slots: + void convertText( const QString &text ); + + signals: + void dataChanged( const QByteArray &buf ); + + private: + bool mBusy; + CHexValidator *mValidator; +}; + + +class CConverterDialog : public KDialogBase +{ + Q_OBJECT + + public: + CConverterDialog( QWidget *parent, const char *name=0, bool modal=true ); + ~CConverterDialog( void ); + + protected: + void showEvent( QShowEvent *e ); + + protected slots: + virtual void slotUser1( void ); + virtual void slotUser2( void ); + + private slots: + void setData( const QByteArray &data ); + + signals: + void probeCursorValue( QByteArray &buf, uint size ); + + private: + CValidateLineEdit *mHexInput; + CValidateLineEdit *mDecInput; + CValidateLineEdit *mOctInput; + CValidateLineEdit *mBinInput; + CValidateLineEdit *mTxtInput; +}; + +#endif + diff --git a/khexedit/dialog.cc b/khexedit/dialog.cc new file mode 100644 index 0000000..6ef1273 --- /dev/null +++ b/khexedit/dialog.cc @@ -0,0 +1,1433 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "dialog.h" +#include + +static const QStringList &formatStrings( void ); +static const QStringList &operationStrings( void ); + + +CGotoDialog::CGotoDialog( QWidget *parent, const char *name, bool modal ) + :KDialogBase( Plain, i18n("Goto Offset"), Ok|Cancel, Ok, parent, name, + modal ) +{ + QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + QVBoxLayout *vbox = new QVBoxLayout(); + if( vbox == 0 ) { return; } + topLayout->addLayout( vbox ); + + mComboBox = new QComboBox( true, plainPage() ); + if( mComboBox == 0 ) { return; } + mComboBox->setMaxCount( 10 ); + mComboBox->setInsertionPolicy( QComboBox::AtTop ); + mComboBox->setMinimumWidth( fontMetrics().maxWidth()*17 ); + + QLabel *label = new QLabel( mComboBox, i18n("O&ffset:"), plainPage() ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mComboBox ); + + QButtonGroup *group = new QButtonGroup( i18n("Options"), plainPage() ); + if( group == 0 ) { return; } + topLayout->addWidget( group, 10 ); + + QGridLayout *gbox = new QGridLayout( group, 4, 2, spacingHint() ); + if( gbox == 0 ) { return; } + gbox->addRowSpacing( 0, fontMetrics().lineSpacing() ); + mCheckFromCursor = new QCheckBox( i18n("&From cursor"), group ); + gbox->addWidget( mCheckFromCursor, 1, 0 ); + mCheckBackward = new QCheckBox( i18n("&Backwards"), group ); + gbox->addWidget( mCheckBackward, 1, 1 ); + mCheckVisible = new QCheckBox( i18n("&Stay visible"), group ); + gbox->addWidget( mCheckVisible, 2, 0 ); + gbox->setRowStretch( 3, 10 ); + + KConfig &config = *kapp->config(); + config.setGroup("Goto Dialog"); + mCheckFromCursor->setChecked( config.readBoolEntry( "FromCursor", false ) ); + mCheckVisible->setChecked( config.readBoolEntry( "StayVisible", true ) ); + mCheckBackward->setChecked( config.readBoolEntry( "Backwards", false ) ); +} + + + +CGotoDialog::~CGotoDialog( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup("Goto Dialog"); + config.writeEntry( "FromCursor", mCheckFromCursor->isChecked() ); + config.writeEntry( "StayVisible", mCheckVisible->isChecked() ); + config.writeEntry( "Backwards", mCheckBackward->isChecked() ); + config.sync(); +} + + + +void CGotoDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + mComboBox->setFocus(); +} + + + +// +// Format of input string: +// 0x|s +// s = :,. or space +// +void CGotoDialog::slotOk( void ) +{ + uint offset; + bool success = stringToOffset( mComboBox->currentText(), offset ); + if( success == false ) + { + showEntryFailure( this, QString("") ); + return; + } + + if( mCheckVisible->isChecked() == false ) + { + hide(); + } + emit gotoOffset( offset, 7, mCheckFromCursor->isChecked(), + mCheckBackward->isChecked() == true ? false : true ); + + #if 0 + const char *p = mComboBox->currentText(); + if( strlen( p ) == 0 ) + { + return; + } + + // + // Skip any whitespaces in front of string + // + for( ; *p != 0 && isspace( *p ) ; p++ ); + + uint offset, bit; + int match; + if( strncmp( p, "0x", 2 ) == 0 || strncmp( p, "0X", 2 ) == 0 ) + { + match = sscanf( p+2, "%x", &offset ); + } + else + { + match = sscanf( p, "%u", &offset ); + } + + if( match == 0 ) + { + return; + } + + bit = 7; + + p = strpbrk( p, ":,. " ); + if( p != 0 ) + { + match = sscanf( p+1, "%u", &bit ); + if( match == 0 ) + { + return; + } + if( bit > 7 ) { bit = 7; } + } + #endif +} + + + +CFindDialog::CFindDialog( QWidget *parent, const char *name, bool modal ) + :KDialogBase( Plain, i18n("Find"), Ok|Cancel, Ok, parent, name, modal ) +{ + + QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + QVBoxLayout *vbox = new QVBoxLayout(); + if( vbox == 0 ) { return; } + topLayout->addLayout( vbox ); + + mSelector = new QComboBox( false, plainPage() ); + if( mSelector == 0 ) { return; } + mSelector->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mSelector->insertStringList( formatStrings() ); + connect( mSelector, SIGNAL(activated(int)), SLOT(selectorChanged(int)) ); + + QLabel *label = new QLabel( mSelector, i18n("Fo&rmat:"), plainPage() ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mSelector ); + + mInput = new QLineEdit( plainPage() ); + if( mInput == 0 ) { return; } + mInput->setMinimumWidth( fontMetrics().maxWidth()*17 ); + connect( mInput, SIGNAL(textChanged(const QString&)), + SLOT(inputChanged(const QString&)) ); + mFindValidator = new CHexValidator( this, CHexValidator::regularText ); + if( mFindValidator == 0 ) { return; } + mInput->setValidator( mFindValidator ); + + label = new QLabel( mInput, i18n("F&ind:"), plainPage() ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mInput ); + + QButtonGroup *group = new QButtonGroup( i18n("Options"), plainPage() ); + if( group == 0 ) { return; } + topLayout->addWidget( group, 10 ); + + QGridLayout *gbox = new QGridLayout( group, 5, 2, spacingHint() ); + if( gbox == 0 ) { return; } + gbox->addRowSpacing( 0, fontMetrics().lineSpacing() ); + + mCheckFromCursor = new QCheckBox( i18n("&From cursor"), group ); + gbox->addWidget( mCheckFromCursor, 1, 0 ); + mCheckBackward = new QCheckBox( i18n("&Backwards"), group ); + gbox->addWidget( mCheckBackward, 1, 1 ); + mCheckInSelection = new QCheckBox( i18n("&In selection"), group ); + gbox->addWidget( mCheckInSelection, 2, 0 ); + mCheckUseNavigator = new QCheckBox( i18n("&Use navigator"),group); + gbox->addWidget( mCheckUseNavigator, 2, 1 ); + mCheckIgnoreCase = new QCheckBox( i18n("Ignore c&ase"),group); + gbox->addWidget( mCheckIgnoreCase, 3, 0 ); + gbox->setRowStretch( 4, 10 ); + + KConfig &config = *kapp->config(); + config.setGroup("Find Dialog"); + mCheckFromCursor->setChecked( config.readBoolEntry( "FromCursor", true ) ); + mCheckInSelection->setChecked( config.readBoolEntry( "InSelection", false) ); + mCheckIgnoreCase->setChecked( config.readBoolEntry( "IgnoreCase", false ) ); + mCheckBackward->setChecked( config.readBoolEntry( "Backwards", false ) ); + mCheckUseNavigator->setChecked( config.readBoolEntry( "UseNavigator", true)); + uint val = config.readUnsignedNumEntry( "Format", 0 ); + mSelector->setCurrentItem(QMIN(4,val) ); + selectorChanged( mSelector->currentItem() ); + enableButtonOK(!mInput->text().isEmpty()); +} + + +CFindDialog::~CFindDialog( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup("Find Dialog"); + config.writeEntry( "FromCursor", mCheckFromCursor->isChecked() ); + config.writeEntry( "InSelection", mCheckInSelection->isChecked() ); + config.writeEntry( "IgnoreCase", mCheckIgnoreCase->isChecked() ); + config.writeEntry( "Backwards", mCheckBackward->isChecked() ); + config.writeEntry( "UseNavigator", mCheckUseNavigator->isChecked() ); + config.writeEntry( "Format", mSelector->currentItem() ); + config.sync(); +} + + +void CFindDialog::selectorChanged( int index ) +{ + mFindValidator->setState( (CHexValidator::EState)index ); + mInput->setText( mFindString[ index ] ); + mCheckIgnoreCase->setEnabled( index == 4 ); +} + + +void CFindDialog::inputChanged( const QString &text ) +{ + mFindString[ mSelector->currentItem() ] = text; + mFindValidator->convert( mFindData, + mFindString[ mSelector->currentItem() ] ); + enableButtonOK(!text.isEmpty()); +} + + +void CFindDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + mInput->setFocus(); +} + + +bool CFindDialog::isEmpty( void ) +{ + return( mFindData.isEmpty() ); +} + + +void CFindDialog::slotOk( void ) +{ + if( isEmpty() == true ) + { + showEntryFailure( this, QString("") ); + return; + } + + SSearchControl sc; + sc.key = mFindData; + sc.keyType = mSelector->currentItem(); + sc.fromCursor = mCheckFromCursor->isChecked(); + sc.inSelection = mCheckInSelection->isChecked(); + sc.forward = mCheckBackward->isChecked() == true ? false : true; + sc.ignoreCase = mCheckIgnoreCase->isEnabled() && mCheckIgnoreCase->isChecked(); + + hide(); + emit findData( sc, Find_First, mCheckUseNavigator->isChecked() ); +} + + +void CFindDialog::findAgain( EOperation operation ) +{ + if( isEmpty() == true ) + { + showEntryFailure( this, QString("") ); + return; + } + + SSearchControl sc; + sc.key = mFindData; + sc.fromCursor = true; + sc.inSelection = mCheckInSelection->isChecked(); + sc.ignoreCase = mCheckIgnoreCase->isEnabled() && mCheckIgnoreCase->isChecked(); + if( operation == find_Next ) + { + sc.forward = true; + } + else if( operation == find_Previous ) + { + sc.forward = false; + } + else + { + sc.forward = mCheckBackward->isChecked() == true ? false : true; + } + + hide(); + emit findData( sc, Find_Next, false ); +} + + + +CFindNavigatorDialog::CFindNavigatorDialog( QWidget *parent, const char *name, + bool modal ) + :KDialogBase( Plain, i18n("Find (Navigator)"), User3|User2|User1|Close, + User2, parent, name, modal, true, i18n("New &Key"), + i18n("&Next"), i18n("&Previous") ) +{ + QString text; + QBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + topLayout->addSpacing( spacingHint() ); // A little bit extra space + + QHBoxLayout *hbox = new QHBoxLayout(); + if( hbox == 0 ) { return; } + topLayout->addLayout( hbox ); + + text = i18n("Searching for:"); + QLabel *label = new QLabel( text, plainPage() ); + hbox->addWidget( label ); + + mKey = new QLineEdit( plainPage() ); + mKey->setMinimumWidth( fontMetrics().width("M") * 20 ); + mKey->setFocusPolicy( QWidget::NoFocus ); + hbox->addWidget( mKey ); + + topLayout->addSpacing( spacingHint() ); // A little bit extra space + topLayout->addStretch(10); +} + + +CFindNavigatorDialog::~CFindNavigatorDialog( void ) +{ +} + + +void CFindNavigatorDialog::defineData( SSearchControl &sc ) +{ + mSearchControl = sc; + mSearchControl.key.duplicate( sc.key ); + + if( mSearchControl.key.isEmpty() == true ) + { + mKey->setText(""); + return; + } + + if( mSearchControl.keyType == 0 ) + { + QString str; + for( uint i=0; isetText( str ); + + } + else if( mSearchControl.keyType == 1 ) + { + QString str("0x "); + for( uint i=0; isetText( str ); + } + else if( mSearchControl.keyType == 2 ) + { + QString str; + for( uint i=0; isetText( str ); + } + else + { + char buf[10]; + memset( buf, 0, sizeof( buf ) ); buf[8] = ' '; + + QString str; + for( uint i=0; isetText( str ); + } +} + + +void CFindNavigatorDialog::slotUser3( void ) // Previous +{ + done( repPrevious ); +} + + +void CFindNavigatorDialog::slotUser2( void ) // Next +{ + done( repNext ); +} + + +void CFindNavigatorDialog::slotUser1( void ) // New key +{ + done( repNewKey ); +} + + +void CFindNavigatorDialog::slotClose( void ) +{ + done( repClose ); +} + + +void CFindNavigatorDialog::done( int resultCode ) +{ + setResult( resultCode ); + if( resultCode == repClose || resultCode == repNewKey ) + { + if( resultCode == repNewKey ) + { + emit makeKey(); + } + hide(); + return; + } + + mSearchControl.forward = resultCode == repNext ? true : false; + emit findData( mSearchControl, Find_Next, true ); +} + + + + +CReplaceDialog::CReplaceDialog( QWidget *parent, const char *name, bool modal ) + :KDialogBase( Plain, i18n("Find & Replace"), Ok|Cancel, Ok, + parent, name, modal ) +{ + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + QVBoxLayout *vbox = new QVBoxLayout(); + if( vbox == 0 ) { return; } + topLayout->addLayout( vbox ); + + + mFindSelector = new QComboBox( false, plainPage() ); + if( mFindSelector == 0 ) { return; } + mFindSelector->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mFindSelector->insertStringList( formatStrings() ); + connect( mFindSelector, SIGNAL(activated(int)), + SLOT(findSelectorChanged(int)) ); + + text = i18n("Fo&rmat (find):"); + QLabel *label = new QLabel( mFindSelector, text, plainPage() ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mFindSelector ); + + mFindInput = new QLineEdit( plainPage() ); + if( mFindInput == 0 ) { return; } + mFindInput->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mFindValidator = new CHexValidator( this, CHexValidator::regularText ); + if( mFindValidator == 0 ) { return; } + mFindInput->setValidator( mFindValidator ); + connect( mFindInput, SIGNAL(textChanged(const QString&)), + SLOT(findInputChanged(const QString&)) ); + + label = new QLabel( mFindInput, i18n("F&ind:"), plainPage() ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mFindInput ); + + mReplaceSelector = new QComboBox( false, plainPage() ); + if( mReplaceSelector == 0 ) { return; } + mReplaceSelector->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mReplaceSelector->insertStringList( formatStrings() ); + connect( mReplaceSelector, SIGNAL(activated(int)), + SLOT(replaceSelectorChanged(int)) ); + + text = i18n("For&mat (replace):"); + label = new QLabel( mReplaceSelector, text, plainPage() ); + if( label == 0 ) { return; } + label->setFixedHeight( label->sizeHint().height() ); + + vbox->addWidget( label ); + vbox->addWidget( mReplaceSelector ); + + mReplaceInput = new QLineEdit( plainPage() ); + if( mReplaceInput == 0 ) { return; } + mReplaceInput->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mReplaceValidator = new CHexValidator( this, CHexValidator::regularText ); + if( mReplaceValidator == 0 ) { return; } + mReplaceInput->setValidator( mReplaceValidator ); + connect( mReplaceInput, SIGNAL(textChanged(const QString&)), + SLOT(replaceInputChanged(const QString&)) ); + + label = new QLabel( mReplaceInput, i18n("Rep&lace:"), plainPage() ); + if( label == 0 ) { return; } + label->setFixedHeight( label->sizeHint().height() ); + + vbox->addWidget( label ); + vbox->addWidget( mReplaceInput ); + + QButtonGroup *group = new QButtonGroup( i18n("Options"), plainPage() ); + if( group == 0 ) { return; } + topLayout->addWidget( group, 10 ); + + QGridLayout *gbox = new QGridLayout( group, 5, 2, spacingHint() ); + if( gbox == 0 ) { return; } + gbox->addRowSpacing( 0, fontMetrics().lineSpacing() ); + mCheckFromCursor = new QCheckBox( i18n("&From cursor"), group ); + gbox->addWidget( mCheckFromCursor, 1, 0 ); + mCheckBackward = new QCheckBox( i18n("&Backwards"), group ); + gbox->addWidget( mCheckBackward, 1, 1 ); + mCheckInSelection = new QCheckBox( i18n("&In selection"), group ); + gbox->addWidget( mCheckInSelection, 2, 0 ); + mCheckPrompt = new QCheckBox( i18n("&Prompt"), group ); + gbox->addWidget( mCheckPrompt, 2, 1 ); + mCheckIgnoreCase = new QCheckBox( i18n("Ignore c&ase"), group ); + gbox->addWidget( mCheckIgnoreCase, 3, 0 ); + gbox->setRowStretch( 4, 10 ); + + KConfig &config = *kapp->config(); + config.setGroup("Replace Dialog"); + mCheckFromCursor->setChecked( config.readBoolEntry( "FromCursor", true ) ); + mCheckInSelection->setChecked( config.readBoolEntry( "InSelection", false) ); + mCheckIgnoreCase->setChecked( config.readBoolEntry( "IgnoreCase", false ) ); + mCheckBackward->setChecked( config.readBoolEntry( "Backwards", false ) ); + mCheckPrompt->setChecked( config.readBoolEntry( "Prompt", true)); + uint val = config.readUnsignedNumEntry( "FindFormat", 0 ); + mFindSelector->setCurrentItem(QMIN(4,val) ); + findSelectorChanged( mFindSelector->currentItem() ); + val = config.readUnsignedNumEntry( "ReplaceFormat", 0 ); + mReplaceSelector->setCurrentItem(QMIN(4,val) ); + replaceSelectorChanged( mReplaceSelector->currentItem() ); + enableButtonOK(!mFindInput->text().isEmpty()); +} + + +CReplaceDialog::~CReplaceDialog( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup("Replace Dialog"); + config.writeEntry( "FromCursor", mCheckFromCursor->isChecked() ); + config.writeEntry( "InSelection", mCheckInSelection->isChecked() ); + config.writeEntry( "IgnoreCase", mCheckIgnoreCase->isChecked() ); + config.writeEntry( "Backwards", mCheckBackward->isChecked() ); + config.writeEntry( "Prompt", mCheckPrompt->isChecked() ); + config.writeEntry( "FindFormat", mFindSelector->currentItem() ); + config.writeEntry( "ReplaceFormat", mReplaceSelector->currentItem() ); + config.sync(); +} + + +void CReplaceDialog::findSelectorChanged( int index ) +{ + mFindValidator->setState( (CHexValidator::EState)index ); + mFindInput->setText( mFindString[ index ] ); + mCheckIgnoreCase->setEnabled( index == 4 ); +} + + +void CReplaceDialog::findInputChanged( const QString &text ) +{ + mFindString[ mFindSelector->currentItem() ] = text; + mFindValidator->convert( mFindData, + mFindString[ mFindSelector->currentItem() ] ); + enableButtonOK(!text.isEmpty()); +} + + +void CReplaceDialog::replaceSelectorChanged( int index ) +{ + mReplaceValidator->setState( (CHexValidator::EState)index ); + mReplaceInput->setText( mReplaceString[ index ] ); +} + + +void CReplaceDialog::replaceInputChanged( const QString &text ) +{ + mReplaceString[ mReplaceSelector->currentItem() ] = text; + mReplaceValidator->convert( mReplaceData, + mReplaceString[ mReplaceSelector->currentItem() ] ); +} + + +void CReplaceDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + mFindInput->setFocus(); +} + + +void CReplaceDialog::slotOk( void ) +{ + if( mFindData.isEmpty() == true ) + { + showEntryFailure( this, QString("") ); + return; + } + + if( mFindData == mReplaceData ) + { + showEntryFailure( this,i18n("Source and target values can not be equal.")); + return; + } + + hide(); + + SSearchControl sc; + sc.key = mFindData; + sc.val = mReplaceData; + sc.fromCursor = mCheckFromCursor->isChecked(); + sc.inSelection = mCheckInSelection->isChecked(); + sc.forward = mCheckBackward->isChecked() == true ? false : true; + + sc.ignoreCase = mCheckIgnoreCase->isEnabled() && mCheckIgnoreCase->isChecked(); + + emit replaceData( sc, mCheckPrompt->isChecked() ? Replace_First: Replace_AllInit ); +} + + + + + +CReplacePromptDialog::CReplacePromptDialog( QWidget *parent, const char *name, + bool modal ) + :KDialogBase( Plain, i18n("Find & Replace"), User3|User2|User1|Close, + User2, parent, name, modal, true, i18n("Replace &All"), + i18n("Do Not Replace"), i18n("Replace")) +{ + QString text; + QBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + topLayout->addSpacing( spacingHint() ); // A little bit extra space + + text = i18n("Replace marked data at cursor position?"); + QLabel* label = new QLabel( text, plainPage() ); + topLayout->addWidget( label ); + + topLayout->addSpacing( spacingHint() ); // A little bit extra space + topLayout->addStretch(10); +} + + +CReplacePromptDialog::~CReplacePromptDialog( void ) +{ +} + + +void CReplacePromptDialog::defineData( SSearchControl &sc ) +{ + mSearchControl = sc; + mSearchControl.key.duplicate( sc.key ); + mSearchControl.val.duplicate( sc.val ); +} + + +void CReplacePromptDialog::slotUser3( void ) +{ + done( repYes ); +} + + +void CReplacePromptDialog::slotUser2( void ) +{ + done( repNo ); +} + + +void CReplacePromptDialog::slotUser1( void ) +{ + done( repAll ); +} + + +void CReplacePromptDialog::slotClose( void ) +{ + done( repClose ); +} + + +void CReplacePromptDialog::done( int returnCode ) +{ + if( returnCode == repClose ) + { + hide(); + } + else if( returnCode == repYes ) + { + emit replaceData( mSearchControl, Replace_Next ); + } + else if( returnCode == repNo ) + { + emit replaceData( mSearchControl, Replace_Ignore ); + } + else + { + emit replaceData( mSearchControl, Replace_All ); + } +} + + + + +CFilterDialog::CFilterDialog( QWidget *parent, const char *name, bool modal ) + :KDialogBase( Plain, i18n("Binary Filter"), Ok|Cancel, Ok, + parent, name, modal ) +{ + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + QVBoxLayout *vbox = new QVBoxLayout(); + if( vbox == 0 ) { return; } + topLayout->addLayout( vbox ); + + + mOperationSelector = new QComboBox( false, plainPage() ); + if( mOperationSelector == 0 ) { return; } + mOperationSelector->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mOperationSelector->insertStringList( operationStrings() ); + connect( mOperationSelector, SIGNAL(activated(int)), + SLOT(operationSelectorChanged(int)) ); + + text = i18n("O&peration:"); + QLabel *label = new QLabel( mOperationSelector, text, plainPage() ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mOperationSelector ); + + KSeparator *separator = new KSeparator( plainPage() ); + separator->setOrientation( QFrame::HLine ); + vbox->addWidget( separator ); + + + mWidgetStack = new QWidgetStack( plainPage(), "pagestack" ); + if( mWidgetStack == 0 ) { return; } + vbox->addWidget( mWidgetStack ); + + makeEmptyLayout(); + makeOperandLayout(); + makeBitSwapLayout(); + makeRotateLayout(); + mWidgetStack->raiseWidget( (int)OperandPage ); + + + QButtonGroup *group = new QButtonGroup( i18n("Options"), plainPage() ); + if( group == 0 ) { return; } + topLayout->addWidget( group, 10 ); + + QGridLayout *gbox = new QGridLayout( group, 4, 2, spacingHint() ); + if( gbox == 0 ) { return; } + gbox->addRowSpacing( 0, fontMetrics().lineSpacing() ); + mCheckFromCursor = new QCheckBox( i18n("&From cursor"), group ); + gbox->addWidget( mCheckFromCursor, 1, 0 ); + mCheckBackward = new QCheckBox( i18n("&Backwards"), group ); + gbox->addWidget( mCheckBackward, 1, 1 ); + mCheckInSelection = new QCheckBox( i18n("&In selection"), group ); + gbox->addWidget( mCheckInSelection, 2, 0 ); + mCheckVisible = new QCheckBox( i18n("&Stay visible"), group ); + gbox->addWidget( mCheckVisible, 2, 1 ); + gbox->setRowStretch( 3, 10 ); +} + + +CFilterDialog::~CFilterDialog( void ) +{ + delete mOperandValidator; +} + + +void CFilterDialog::makeEmptyLayout( void ) +{ + QFrame *page = new QFrame( plainPage() ); + if( page == 0 ) { return; } + mWidgetStack->addWidget( page, EmptyPage ); +} + + +void CFilterDialog::makeOperandLayout( void ) +{ + QString text; + + QFrame *page = new QFrame( plainPage() ); + if( page == 0 ) { return; } + mWidgetStack->addWidget( page, OperandPage ); + + QVBoxLayout *vbox = new QVBoxLayout( page, 0, spacingHint() ); + if( vbox == 0 ) { return; } + + mOperandSelector = new QComboBox( false, page ); + if( mOperandSelector == 0 ) { return; } + mOperandSelector->setFixedHeight( mOperandSelector->sizeHint().height()); + mOperandSelector->setMinimumWidth( fontMetrics().width("M")*20 ); + mOperandSelector->insertStringList( formatStrings() ); + connect( mOperandSelector, SIGNAL(activated(int)), + SLOT(operandSelectorChanged(int)) ); + + text = i18n("Fo&rmat (operand):"); + mOperandFormatLabel = new QLabel( mOperandSelector, text, page ); + if( mOperandFormatLabel == 0 ) { return; } + + vbox->addWidget( mOperandFormatLabel ); + vbox->addWidget( mOperandSelector ); + + mOperandInput = new QLineEdit( page ); + if( mOperandInput == 0 ) { return; } + mOperandInput->setMinimumWidth( fontMetrics().width("M") * 20 ); + mOperandValidator = new CHexValidator( this, CHexValidator::regularText ); + if( mOperandValidator == 0 ) { return; } + mOperandInput->setValidator( mOperandValidator ); + connect( mOperandInput, SIGNAL(textChanged(const QString&)), + SLOT(operandInputChanged(const QString&)) ); + + mOperandInputLabel = new QLabel( mOperandInput, i18n("O&perand:"), page ); + if( mOperandInputLabel == 0 ) { return; } + + vbox->addWidget( mOperandInputLabel ); + vbox->addWidget( mOperandInput ); + vbox->addSpacing( 1 ); +} + + +void CFilterDialog::makeBitSwapLayout( void ) +{ + QString text; + + QFrame *page = new QFrame( plainPage() ); + if( page == 0 ) { return; } + mWidgetStack->addWidget( page, BitSwapPage ); + + QVBoxLayout *vbox = new QVBoxLayout( page, 0, spacingHint() ); + if( vbox == 0 ) { return; } + + text = i18n("Swap rule"); + QLabel *label = new QLabel( text, page ); + if( label == 0 ) { return; } + label->setFixedHeight( label->sizeHint().height() ); + vbox->addWidget( label ); + + mByteWidget = new CByteWidget( page ); + vbox->addWidget( mByteWidget ); + + QHBoxLayout *hbox = new QHBoxLayout( 0 ); + vbox->addLayout( hbox ); + + text = i18n("&Reset"); + QPushButton *resetButton = new QPushButton( text, page ); + resetButton->setFixedHeight( resetButton->sizeHint().height() ); + connect( resetButton, SIGNAL(clicked()), mByteWidget, SLOT(reset()) ); + + hbox->addWidget( resetButton ); + hbox->addStretch( 10 ); +} + + +void CFilterDialog::makeRotateLayout( void ) +{ + QString text; + + QFrame *page = new QFrame( plainPage() ); + if( page == 0 ) { return; } + mWidgetStack->addWidget( page, RotatePage ); + + QVBoxLayout *vbox = new QVBoxLayout( page, 0, spacingHint() ); + if( vbox == 0 ) { return; } + + mGroupSpin = new QSpinBox( page ); + if( mGroupSpin == 0 ) { return; } + mGroupSpin->setMinimumWidth( fontMetrics().width("M")*20 ); + mGroupSpin->setRange(1, INT_MAX ); + + text = i18n("&Group size [bytes]"); + QLabel *label = new QLabel( mGroupSpin, text, page ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mGroupSpin ); + + mBitSpin = new QSpinBox( page ); + if( mBitSpin == 0 ) { return; } + mBitSpin->setMinimumWidth( fontMetrics().width("M")*20 ); + mBitSpin->setRange(INT_MIN, INT_MAX); + + text = i18n("S&hift size [bits]"); + label = new QLabel( mBitSpin, text, page ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mBitSpin ); +} + + + +void CFilterDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + mOperandInput->setFocus(); +} + + + +void CFilterDialog::slotOk( void ) +{ + SFilterControl fc; + switch( mOperationSelector->currentItem() ) + { + case SFilterControl::OperandAndData: + case SFilterControl::OperandOrData: + case SFilterControl::OperandXorData: + if( mOperandData.isEmpty() == true ) + { + showEntryFailure( this, QString("") ); + return; + } + fc.operand = mOperandData; + break; + + case SFilterControl::InvertData: + case SFilterControl::ReverseData: + break; + + case SFilterControl::RotateData: + case SFilterControl::ShiftData: + fc.rotate[0] = mGroupSpin->value(); + fc.rotate[1] = mBitSpin->value(); + if( fc.rotate[1] == 0 ) + { + QString msg = i18n("Shift size is zero."); + showEntryFailure( this, msg ); + return; + } + break; + + case SFilterControl::SwapBits: + if( mByteWidget->flag( fc.operand ) == false ) + { + QString msg = i18n("Swap rule does not define any swapping."); + showEntryFailure( this, msg ); + return; + } + break; + + default: + return; + break; + + } + + if( mCheckVisible->isChecked() == false ) + { + hide(); + } + + fc.operation = (SFilterControl::Operation)mOperationSelector->currentItem(); + fc.fromCursor = mCheckFromCursor->isChecked(); + fc.inSelection = mCheckInSelection->isChecked(); + if( mCheckBackward->isEnabled() == true ) + { + fc.forward = mCheckBackward->isChecked() == true ? false : true; + } + else + { + fc.forward = true; + } + + emit filterData( fc ); +} + + +void CFilterDialog::operandSelectorChanged( int index ) +{ + mOperandValidator->setState( (CHexValidator::EState)index ); + mOperandInput->setText( mOperandString[ index ] ); +} + + +void CFilterDialog::operandInputChanged( const QString &text ) +{ + mOperandString[ mOperandSelector->currentItem() ] = text; + mOperandValidator->convert( mOperandData, + mOperandString[ mOperandSelector->currentItem() ] ); +} + + +void CFilterDialog::operationSelectorChanged( int index ) +{ + if( index <= 2 ) + { + mWidgetStack->raiseWidget( OperandPage ); + mCheckBackward->setEnabled( true ); + } + else if( index <= 4 ) + { + mWidgetStack->raiseWidget( EmptyPage ); + mCheckBackward->setEnabled( true ); + } + else if( index <= 6 ) + { + mWidgetStack->raiseWidget( RotatePage ); + mCheckBackward->setEnabled( false ); + } + else + { + mWidgetStack->raiseWidget( BitSwapPage ); + mCheckBackward->setEnabled( true ); + } +} + + + + +CInsertDialog::CInsertDialog( QWidget *parent, const char *name, bool modal ) + :KDialogBase( Plain, i18n("Insert Pattern"), Ok|Cancel, Ok, + parent, name, modal ) +{ + setButtonOKText(i18n("&Insert")); + + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + QVBoxLayout *vbox = new QVBoxLayout(); + if( vbox == 0 ) { return; } + topLayout->addLayout( vbox ); + + mSizeBox = new QSpinBox( plainPage() ); + if( mSizeBox == 0 ) { return; } + mSizeBox->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mSizeBox->setRange( 1, INT_MAX ); + mSizeBox->setValue( 1 ); + + QLabel *label = new QLabel( mSizeBox, i18n("&Size:"), plainPage() ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mSizeBox ); + + mPatternSelector = new QComboBox( false, plainPage() ); + if( mPatternSelector == 0 ) { return; } + mPatternSelector->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mPatternSelector->insertStringList( formatStrings() ); + connect( mPatternSelector, SIGNAL(activated(int)), + SLOT(patternSelectorChanged(int)) ); + + text = i18n("Fo&rmat (pattern):"); + label = new QLabel( mPatternSelector, text, plainPage() ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mPatternSelector ); + + mPatternInput = new QLineEdit( plainPage() ); + if( mPatternInput == 0 ) { return; } + mPatternInput->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mPatternValidator = new CHexValidator( this, CHexValidator::regularText ); + if( mPatternValidator == 0 ) { return; } + mPatternInput->setValidator( mPatternValidator ); + connect( mPatternInput, SIGNAL(textChanged(const QString&)), + SLOT(patternInputChanged(const QString&)) ); + + label = new QLabel( mPatternInput, i18n("&Pattern:"), plainPage() ); + if( label == 0 ) { return; } + + vbox->addWidget( label ); + vbox->addWidget( mPatternInput ); + + mOffsetInput = new QLineEdit( plainPage() ); + mOffsetInput->setMinimumWidth( fontMetrics().maxWidth()*17 ); + + mOffsetLabel = new QLabel( mOffsetInput, i18n("&Offset:"), plainPage() ); + if( mOffsetLabel == 0 ) { return; } + + vbox->addWidget( mOffsetLabel ); + vbox->addWidget( mOffsetInput ); + + QButtonGroup *group = new QButtonGroup( i18n("Options"), plainPage() ); + if( group == 0 ) { return; } + topLayout->addWidget( group, 10 ); + + + QGridLayout *gbox = new QGridLayout( group, 4, 2, spacingHint() ); + if( gbox == 0 ) { return; } + gbox->addRowSpacing( 0, fontMetrics().lineSpacing() ); + + mCheckPattern = new QCheckBox( i18n("R&epeat pattern"), group ); + gbox->addWidget( mCheckPattern, 1, 0 ); + mCheckOnCursor = new QCheckBox( i18n("&Insert on cursor position"), group ); + gbox->addWidget( mCheckOnCursor, 2, 0 ); + connect( mCheckOnCursor, SIGNAL(clicked()), SLOT(cursorCheck()) ); + gbox->setRowStretch( 3, 10 ); + + KConfig &config = *kapp->config(); + config.setGroup("Insert Pattern Dialog"); + mCheckPattern->setChecked( config.readBoolEntry( "RepeatPattern", false ) ); + mCheckOnCursor->setChecked( config.readBoolEntry( "InsertOnCursor", false) ); + cursorCheck(); + uint val = config.readUnsignedNumEntry( "Format", 0 ); + mPatternSelector->setCurrentItem( QMIN(4,val) ); + patternSelectorChanged( mPatternSelector->currentItem() ); +} + + +CInsertDialog::~CInsertDialog( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup("Insert Pattern Dialog"); + config.writeEntry( "RepeatPattern", mCheckPattern->isChecked() ); + config.writeEntry( "InsertOnCursor", mCheckOnCursor->isChecked() ); + config.writeEntry( "Format", mPatternSelector->currentItem() ); + config.sync(); +} + + +void CInsertDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + mPatternInput->setFocus(); +} + + +void CInsertDialog::patternSelectorChanged( int index ) +{ + mPatternValidator->setState( (CHexValidator::EState)index ); + mPatternInput->setText( mPatternString[ index ] ); +} + + +void CInsertDialog::patternInputChanged( const QString &text ) +{ + mPatternString[ mPatternSelector->currentItem() ] = text; + mPatternValidator->convert( mPatternData, + mPatternString[ mPatternSelector->currentItem() ] ); +} + + +void CInsertDialog::slotOk( void ) +{ + if( mPatternData.isEmpty() == true ) + { + showEntryFailure( this, QString("") ); + return; + } + + SInsertData id; + id.size = mSizeBox->value(); + id.repeatPattern = mCheckPattern->isChecked(); + id.onCursor = mCheckOnCursor->isChecked(); + id.pattern = mPatternData; + + if( id.onCursor == false ) + { + bool success = stringToOffset( mOffsetInput->text(), id.offset ); + if( success == false ) + { + showEntryFailure( this, QString("") ); + return; + } + } + + hide(); + execute( id ); +} + + +void CInsertDialog::cursorCheck( void ) +{ + bool state = mCheckOnCursor->isChecked() == true ? false : true; + mOffsetLabel->setEnabled( state ); + mOffsetInput->setEnabled( state ); +} + + + + +void centerDialog( QWidget *widget, QWidget *centerParent ) +{ + if( centerParent == 0 || widget == 0 ) + { + return; + } + + QPoint point = centerParent->mapToGlobal( QPoint(0,0) ); + QRect pos = centerParent->geometry(); + + widget->setGeometry( point.x() + pos.width()/2 - widget->width()/2, + point.y() + pos.height()/2 - widget->height()/2, + widget->width(), widget->height() ); +} + + +void centerDialogBottom( QWidget *widget, QWidget *centerParent ) +{ + if( centerParent == 0 || widget == 0 ) + { + return; + } + + QPoint point = centerParent->mapToGlobal( QPoint(0,0) ); + QRect pos = centerParent->geometry(); + + widget->setGeometry( point.x() + pos.width()/2 - widget->width()/2, + point.y() + pos.height() - widget->height(), + widget->width(), widget->height() ); +} + + +void comboMatchText( QComboBox *combo, const QString &text ) +{ + for( int i=0; i < combo->count(); i++ ) + { + if( combo->text(i) == text ) + { + combo->setCurrentItem(i); + return; + } + } + combo->setCurrentItem(0); +} + + + + + +void showEntryFailure( QWidget *parent, const QString &msg ) +{ + QString message; + message += i18n("Your request can not be processed."); + message += "\n"; + if( msg.isNull() == true || msg.isEmpty() == true ) + { + message += i18n("Examine argument(s) and try again."); + } + else + { + message += msg; + } + KMessageBox::sorry( parent, message, i18n("Invalid argument(s)") ); +} + + +bool verifyFileDestnation( QWidget *parent, const QString &title, + const QString &path ) +{ + if( path.isEmpty() == true ) + { + QString msg = i18n("You must specify a destination file."); + KMessageBox::sorry( parent, msg, title ); + return( false ); + } + + QFileInfo info( path ); + if( info.exists() == true ) + { + if( info.isDir() == true ) + { + QString msg = i18n("You have specified an existing folder."); + KMessageBox::sorry( parent, msg, title ); + return( false ); + } + + if( info.isWritable() == false ) + { + QString msg = i18n("You do not have write permission to this file."); + KMessageBox::sorry( parent, msg, title ); + return( false ); + } + + QString msg = i18n( "" + "You have specified an existing file.\n" + "Overwrite current file?" ); + int reply = KMessageBox::warningContinueCancel( parent, msg, title, i18n("Overwrite") ); + if( reply != KMessageBox::Continue ) + { + return( false ); + } + } + + return( true ); +} + + + +bool stringToOffset( const QString & text, uint &offset ) +{ + if( text.isEmpty() ) + { + return( false ); + } + + const char * p = text.ascii(); // ####: Is this correct? + + // + // Skip any whitespaces in front of string + // + for( ; *p != 0 && isspace( *p ) ; p++ ); + + int match = 0; + bool space = false; + if( strncmp( p, "0x", 2 ) == 0 || strncmp( p, "0X", 2 ) == 0 ) + { + for( const char *q = p+2; *q != 0; q++ ) + { + if( isxdigit( *q ) == 0 || space == true ) + { + if( isspace( *q ) == 0 ) + { + return( false ); + } + space = true; + } + } + match = sscanf( p+2, "%x", &offset ); + } + else + { + for( const char *q = p; *q != 0; q++ ) + { + if( isdigit( *q ) == 0 || space == true ) + { + if( isspace( *q ) == 0 ) + { + return( false ); + } + space = true; + } + } + match = sscanf( p, "%u", &offset ); + } + + if( match == 0 ) + { + return( false ); + } + + return( true ); +} + + +static const QStringList &formatStrings( void ) +{ + static QStringList list; + if( list.isEmpty() == true ) + { + list.append( i18n( "Hexadecimal" ) ); + list.append( i18n( "Decimal" ) ); + list.append( i18n( "Octal" ) ); + list.append( i18n( "Binary" ) ); + list.append( i18n( "Regular Text" ) ); + } + return( list ); +} + + +static const QStringList &operationStrings( void ) +{ + static QStringList list; + if( list.isEmpty() == true ) + { + list.append( i18n( "operand AND data" ) ); + list.append( i18n( "operand OR data" ) ); + list.append( i18n( "operand XOR data" ) ); + list.append( i18n( "INVERT data" ) ); + list.append( i18n( "REVERSE data" ) ); + list.append( i18n( "ROTATE data" ) ); + list.append( i18n( "SHIFT data" ) ); + list.append( i18n( "Swap Individual Bits" ) ); + } + + return( list ); +} + + + + + +#include "dialog.moc" diff --git a/khexedit/dialog.h b/khexedit/dialog.h new file mode 100644 index 0000000..6a6aae1 --- /dev/null +++ b/khexedit/dialog.h @@ -0,0 +1,350 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _DIALOG_H_ +#define _DIALOG_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "bitswapwidget.h" +#include "hexbuffer.h" +#include "hexvalidator.h" + +const int repYes = QDialog::Accepted; +const int repNo = 11; +const int repAll = 12; +const int repClose = QDialog::Rejected; +const int repNext = 13; +const int repPrevious = 14; +const int repNewKey = 15; + +const uint Replace_All = 1; +const uint Replace_AllInit = 2; +const uint Replace_First = 3; +const uint Replace_Next = 4; +const uint Replace_Ignore = 5; +const uint Find_First = 6; +const uint Find_Next = 7; + + + + +class CGotoDialog : public KDialogBase +{ + Q_OBJECT + + public: + CGotoDialog( QWidget *parent, const char *name = 0, bool modal = false ); + ~CGotoDialog( void ); + + protected: + virtual void showEvent( QShowEvent *e ); + + private slots: + void slotOk( void ); + + signals: + void gotoOffset( uint offset, uint bit, bool fromCursor, bool forward ); + + private: + QComboBox *mComboBox; + QCheckBox *mCheckBackward; + QCheckBox *mCheckFromCursor; + QCheckBox *mCheckVisible; +}; + + + +class CFindDialog : public KDialogBase +{ + Q_OBJECT + + public: + enum EOperation + { + find_Again = 0, + find_Next, + find_Previous + }; + + public: + CFindDialog( QWidget *parent=0, const char *name=0, bool modal=false ); + ~CFindDialog( void ); + bool isEmpty( void ); + + public slots: + void findAgain( EOperation operation ); + + protected: + virtual void showEvent( QShowEvent *e ); + + private slots: + void slotOk( void ); + void selectorChanged( int index ); + void inputChanged( const QString &text ); + + signals: + void findData( SSearchControl &sc, uint mode, bool navigator ); + + private: + QComboBox *mSelector; + QLineEdit *mInput; + QCheckBox *mCheckBackward; + QCheckBox *mCheckFromCursor; + QCheckBox *mCheckInSelection; + QCheckBox *mCheckUseNavigator; + QCheckBox *mCheckIgnoreCase; + + QString mFindString[5]; + QByteArray mFindData; + CHexValidator *mFindValidator; +}; + + + +class CFindNavigatorDialog : public KDialogBase +{ + Q_OBJECT + + public: + CFindNavigatorDialog( QWidget *parent=0, const char *name=0, + bool modal=false ); + ~CFindNavigatorDialog( void ); + void defineData( SSearchControl &sc ); + + private slots: + void slotUser1( void ); + void slotUser2( void ); + void slotUser3( void ); + void slotClose( void ); + + private: + void done( int returnCode ); + + signals: + void findData( SSearchControl &sc, uint mode, bool navigator ); + void makeKey( void ); + + private: + QLineEdit *mKey; + SSearchControl mSearchControl; +}; + + +class CReplaceDialog : public KDialogBase +{ + Q_OBJECT + + public: + CReplaceDialog( QWidget *parent=0, const char *name=0, bool modal=false ); + ~CReplaceDialog( void ); + + protected: + virtual void showEvent( QShowEvent *e ); + + private slots: + void slotOk( void ); + void findSelectorChanged( int index ); + void findInputChanged( const QString &text ); + void replaceSelectorChanged( int index ); + void replaceInputChanged( const QString &text ); + + signals: + void replaceData( SSearchControl &sc, uint mode ); + + private: + QComboBox *mFindSelector; + QComboBox *mReplaceSelector; + QLineEdit *mFindInput; + QLineEdit *mReplaceInput; + + QCheckBox *mCheckBackward; + QCheckBox *mCheckFromCursor; + QCheckBox *mCheckInSelection; + QCheckBox *mCheckPrompt; + QCheckBox *mCheckIgnoreCase; + + QString mFindString[5]; + QString mReplaceString[5]; + QByteArray mFindData; + QByteArray mReplaceData; + CHexValidator *mFindValidator; + CHexValidator *mReplaceValidator; +}; + + + +class CReplacePromptDialog : public KDialogBase +{ + Q_OBJECT + + public: + CReplacePromptDialog( QWidget *parent=0, const char *name=0, + bool modal=false ); + ~CReplacePromptDialog( void ); + void defineData( SSearchControl &sc ); + + private slots: + void slotUser1( void ); + void slotUser2( void ); + void slotUser3( void ); + void slotClose( void ); + + private: + void done( int returnCode ); + + signals: + void replaceData( SSearchControl &sc, uint mode ); + + private: + SSearchControl mSearchControl; +}; + + + + +class CFilterDialog : public KDialogBase +{ + Q_OBJECT + + public: + enum EStackMode + { + EmptyPage = 0, + OperandPage, + BitSwapPage, + RotatePage + }; + + public: + CFilterDialog( QWidget *parent=0, const char *name=0, bool modal=false ); + ~CFilterDialog( void ); + + protected: + virtual void showEvent( QShowEvent *e ); + + private: + void makeEmptyLayout( void ); + void makeOperandLayout( void ); + void makeBitSwapLayout( void ); + void makeRotateLayout( void ); + + private slots: + void slotOk( void ); + void operandSelectorChanged( int index ); + void operandInputChanged( const QString &text ); + void operationSelectorChanged( int index ); + + signals: + void filterData( SFilterControl &fc ); + + private: + QWidgetStack *mWidgetStack; + QLabel *mOperandFormatLabel; + QLabel *mOperandInputLabel; + QComboBox *mOperandSelector; + QLineEdit *mOperandInput; + QComboBox *mOperationSelector; + QSpinBox *mGroupSpin; + QSpinBox *mBitSpin; + CByteWidget *mByteWidget; + + QCheckBox *mCheckBackward; + QCheckBox *mCheckFromCursor; + QCheckBox *mCheckInSelection; + QCheckBox *mCheckVisible; + + QString mOperandString[5]; + QByteArray mOperandData; + CHexValidator *mOperandValidator; +}; + + + + +class CInsertDialog : public KDialogBase +{ + Q_OBJECT + + public: + CInsertDialog( QWidget *parent=0, const char *name=0, bool modal=false ); + ~CInsertDialog( void ); + + protected: + virtual void showEvent( QShowEvent *e ); + + private slots: + void slotOk( void ); + void cursorCheck( void ); + void patternSelectorChanged( int index ); + void patternInputChanged( const QString &text ); + + signals: + void execute( SInsertData &id ); + + private: + QSpinBox *mSizeBox; + QLabel *mOffsetLabel; + QComboBox *mPatternSelector; + QLineEdit *mPatternInput; + QLineEdit *mOffsetInput; + QCheckBox *mCheckPattern; + QCheckBox *mCheckOnCursor; + + QString mPatternString[5]; + QByteArray mPatternData; + CHexValidator *mPatternValidator; +}; + + + + +void centerDialog( QWidget *widget, QWidget *centerParent ); +void centerDialogBottom( QWidget *widget, QWidget *centerParent ); +void comboMatchText( QComboBox *combo, const QString &text ); +bool stringToOffset( const QString & text, uint &offset ); + +void showEntryFailure( QWidget *parent, const QString &msg ); +bool verifyFileDestnation( QWidget *parent, const QString &title, + const QString &path ); + + + +#endif + + + + + diff --git a/khexedit/draglabel.cc b/khexedit/draglabel.cc new file mode 100644 index 0000000..e20088c --- /dev/null +++ b/khexedit/draglabel.cc @@ -0,0 +1,149 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include +#include + +#include + +#include "draglabel.h" + + +CDragLabel::CDragLabel( QWidget *parent ) + : QLabel( "draglabel", parent, "kde toolbar widget" ) +{ + mValid = true; + mDragPending = false; + setBackgroundMode( Qt::PaletteButton ); +} + + +CDragLabel::~CDragLabel( void ) +{ +} + + +void CDragLabel::mousePressEvent( QMouseEvent *e ) +{ + if( mValid == false || e->button() != LeftButton || mUrl.isEmpty() == true ) + { + return; + } + + mDragOrigin = e->pos(); + mDragPending = true; +} + + +void CDragLabel::mouseMoveEvent( QMouseEvent *e ) +{ + if( mDragPending == true ) + { + if( abs(e->x() - mDragOrigin.x()) + abs(e->y() - mDragOrigin.y()) > 5 ) + { + mDragPending = false; + + // + // Make drag object, assign pixmap and grab keyboard. The grabbing + // will allow ESC to abort the drag + // + KURL::List uris; + uris.append(KURL(mUrl)); + KURLDrag *uriDrag = new KURLDrag( uris, this ); + if( uriDrag == 0 ) { return; } + prepPixmap( *uriDrag ); + grabKeyboard(); + uriDrag->drag(); + releaseKeyboard(); + } + } +} + +void CDragLabel::mouseReleaseEvent( QMouseEvent * ) +{ + mDragPending = false; +} + + +void CDragLabel::setUrl( const QString &url ) +{ + mUrl = url; +} + + +void CDragLabel::setDragMask( const QPixmap pix ) +{ + mDragMask = pix; +} + + +void CDragLabel::prepPixmap( KURLDrag &uriDrag ) +{ + if( pixmap() == 0 ) + { + return; + } + + QString text; + int index = mUrl.findRev( '/', mUrl.length() ); + if( index < 0 ) + { + text = mUrl; + } + else + { + text = mUrl.right( mUrl.length() - index - 1 ); + } + + int sep = 2; + QRect rect = fontMetrics().boundingRect(text); + int w = pixmap()->width() + rect.width() + sep + 2; + int h = fontMetrics().lineSpacing(); + if( pixmap()->height() > h ) { h = pixmap()->height(); } + + QBitmap mask( w, h, TRUE ); + QPixmap dragPixmap( w, h ); + dragPixmap.fill( black ); + + QPainter p; + p.begin( &mask ); + p.setPen( white ); + p.drawPixmap( 0, 0, mDragMask ); + p.drawText( pixmap()->width()+sep, 0, w-pixmap()->width()+sep, + h, AlignVCenter|AlignLeft, text ); + p.end(); + + p.begin( &dragPixmap ); + p.drawPixmap( 0, 0, *pixmap() ); + p.end(); + + dragPixmap.setMask( mask ); + + QPoint hotspot( pixmap()->width(), pixmap()->height()/2 ); + uriDrag.setPixmap( dragPixmap, hotspot ); +} + + + + + +#include "draglabel.moc" diff --git a/khexedit/draglabel.h b/khexedit/draglabel.h new file mode 100644 index 0000000..d90b5ed --- /dev/null +++ b/khexedit/draglabel.h @@ -0,0 +1,60 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _DRAG_SOURCE_H_ +#define _DRAG_SOURCE_H_ + +#include +#include +#include +#include +#include + +class KURLDrag; + +class CDragLabel: public QLabel +{ + Q_OBJECT + + public: + CDragLabel( QWidget *parent ); + ~CDragLabel( void ); + + void setUrl( const QString &url ); + void setDragMask( const QPixmap pix ); + + protected: + void mousePressEvent( QMouseEvent * ); + void mouseMoveEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + + private: + void prepPixmap( KURLDrag &uriDrag ); + + private: + bool mValid; + QString mUrl; + QBitmap mDragMask; + bool mDragPending; + QPoint mDragOrigin; + +}; + +#endif diff --git a/khexedit/exportdialog.cc b/khexedit/exportdialog.cc new file mode 100644 index 0000000..a178319 --- /dev/null +++ b/khexedit/exportdialog.cc @@ -0,0 +1,696 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include + +#include +#include +#include + +#include "dialog.h" +#include "exportdialog.h" +#include + + +CExportDialog::CExportDialog( QWidget *parent, char *name, bool modal ) + :KDialogBase( Tabbed, i18n("Export Document"), Help|Ok|Cancel, Ok, + parent, name, modal ) +{ + setHelp( "khexedit/khexedit.html", QString::null ); + + mFrame[ page_destination ] = addPage( i18n("Destination") ); + mFrame[ page_option ] = addPage( i18n("Options") ); + + setupDestinationPage(); + setupOptionPage(); + + mConfig = 0; + readConfiguration(); + + QString path = mDestination.fileInput->text(); + int index = path.findRev( '/' ); + if( index != -1 ) { mWorkDir = path.left( index+1 ); } +} + + +CExportDialog::~CExportDialog( void ) +{ + writeConfiguration(); + delete mConfig; mConfig = 0; +} + + +void CExportDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + showPage(0); + mDestination.fileInput->setFocus(); +} + + +void CExportDialog::readConfiguration( void ) +{ + if( mConfig != 0 ) { return; } + + mConfig = new KSimpleConfig( QString("hexexport") ); + if( mConfig == 0 ) { return; } + + mConfig->setGroup( "Destination" ); + + int val = mConfig->readNumEntry( "Format", 0 ); + mDestination.formatCombo->setCurrentItem( val ); + formatChanged( val < 0 || val > option_html ? 0 : val ); + + mConfig->setGroup( "Option" ); + val = mConfig->readNumEntry( "HtmlLine", 80 ); + mHtml.lineSpin->setValue( val ); + QString text = mConfig->readEntry( "HtmlPrefix", "table" ); + mHtml.prefixInput->setText( text ); + val = mConfig->readNumEntry( "HtmlHeader", 1 ); + mHtml.topCombo->setCurrentItem( val < 0 || val >= 4 ? 0 : val ); + val = mConfig->readNumEntry( "HtmlFooter", 3 ); + mHtml.bottomCombo->setCurrentItem( val < 0 || val >= 4 ? 0 : val ); + + bool state = mConfig->readBoolEntry( "HtmlSymlink", true ); + mHtml.symlinkCheck->setChecked( state ); + state = mConfig->readBoolEntry( "HtmlNavigatorBar", true ); + mHtml.navigatorCheck->setChecked( state ); + state = mConfig->readBoolEntry( "HtmlBlackWhite", false ); + mHtml.bwCheck->setChecked( state ); + + text = mConfig->readEntry( "ArrayName", "buffer" ); + mArray.nameInput->setText( text ); + text = mConfig->readEntry( "ArrayElementType", "char" ); + for( int i=0; i < mArray.typeCombo->count(); i++ ) + { + if( mArray.typeCombo->text(i) == text ) + { + mArray.typeCombo->setCurrentItem(i); + break; + } + } + val = mConfig->readNumEntry( "ArrayElementPerLine", 20 ); + val = QMAX( val, mArray.lineSizeSpin->minValue() ); + val = QMIN( val, mArray.lineSizeSpin->maxValue() ); + mArray.lineSizeSpin->setValue( val ); + state = mConfig->readBoolEntry( "ArrayUnsignedAsHex", true ); + mArray.hexadecimalCheck->setChecked( state ); +} + + +void CExportDialog::writeConfiguration( void ) +{ + if( mConfig == 0 ) + { + return; + } + + mConfig->setGroup( "Destination" ); + mConfig->writeEntry( "Format", mDestination.formatCombo->currentItem() ); + + mConfig->setGroup( "Option" ); + mConfig->writeEntry( "HtmlLine", mHtml.lineSpin->value() ); + mConfig->writeEntry( "HtmlPrefix", mHtml.prefixInput->text() ); + mConfig->writeEntry( "HtmlHeader", mHtml.topCombo->currentItem() ); + mConfig->writeEntry( "HtmlFooter", mHtml.bottomCombo->currentItem() ); + mConfig->writeEntry( "HtmlSymlink", mHtml.symlinkCheck->isChecked()); + mConfig->writeEntry( "HtmlNavigatorBar",mHtml.navigatorCheck->isChecked()); + mConfig->writeEntry( "HtmlBlackWhite", mHtml.bwCheck->isChecked() ); + + + mConfig->writeEntry( "ArrayName", mArray.nameInput->text() ); + mConfig->writeEntry( "ArrayElementType", mArray.typeCombo->currentText() ); + mConfig->writeEntry( "ArrayElementPerLine", mArray.lineSizeSpin->value() ); + mConfig->writeEntry( "ArrayUnsignedAsHex", + mArray.hexadecimalCheck->isChecked() ); + mConfig->sync(); +} + + +void CExportDialog::setupDestinationPage( void ) +{ + QString text; + QFrame *page = mFrame[ page_destination ]; + + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + QStringList formatList; + formatList.append( i18n("Plain Text") ); + formatList.append( i18n("HTML Tables") ); + formatList.append( i18n("Rich Text (RTF)") ); + formatList.append( i18n("C Array") ); + + mDestination.formatCombo = new QComboBox( false, page ); + mDestination.formatCombo->insertStringList( formatList ); + mDestination.formatCombo->setMinimumWidth( fontMetrics().maxWidth()*10 ); + connect( mDestination.formatCombo, SIGNAL(activated(int)), + SLOT(formatChanged(int)) ); + + text = i18n("&Format:"); + QLabel *label = new QLabel( mDestination.formatCombo, text, page ); + topLayout->addWidget( label ); + topLayout->addWidget( mDestination.formatCombo ); + + QHBoxLayout *hbox = new QHBoxLayout(); + topLayout->addLayout( hbox ); + + text = i18n("&Destination:"); + label = new QLabel( text, page ); + hbox->addWidget( label ); + + text = i18n("(Package folder)"); + mDestination.fileExtraLabel = new QLabel( text, page ); + hbox->addWidget( mDestination.fileExtraLabel, 10, AlignLeft|AlignVCenter ); + + hbox = new QHBoxLayout(); + topLayout->addLayout( hbox ); + + mDestination.fileInput = new QLineEdit( page ); + hbox->addWidget( mDestination.fileInput ); + connect(mDestination.fileInput, SIGNAL(textChanged ( const QString & )),this,SLOT(destinationChanged(const QString &))); + text = i18n("Choose..."); + QPushButton *browseButton = new QPushButton( text, page, "browse" ); + hbox->addWidget( browseButton ); + connect( browseButton, SIGNAL(clicked()), SLOT(browserClicked()) ); + mDestination.fileInput->setMinimumWidth( fontMetrics().maxWidth()*15 ); + + label->setBuddy(mDestination.fileInput); + + hbox = new QHBoxLayout(); + topLayout->addLayout( hbox, 10 ); + + mDestination.rangeBox = new QButtonGroup( i18n("Export Range"), page ); + hbox->addWidget( mDestination.rangeBox ); + + QButtonGroup *group = mDestination.rangeBox; // convenience + + QVBoxLayout *vbox = new QVBoxLayout( group, spacingHint() ); + vbox->addSpacing( fontMetrics().lineSpacing() ); + + QRadioButton *radio1 = new QRadioButton( i18n("&Everything"), group ); + radio1->setFixedSize( radio1->sizeHint() ); + mDestination.rangeBox->insert( radio1, 0 ); + vbox->addWidget( radio1, 0, AlignLeft ); + + QRadioButton *radio2 = new QRadioButton( i18n("&Selection"), group ); + radio2->setFixedSize( radio2->sizeHint() ); + mDestination.rangeBox->insert( radio2, 1 ); + vbox->addWidget( radio2, 0, AlignLeft ); + + QRadioButton *radio3 = new QRadioButton( i18n("&Range"), group ); + radio3->setFixedSize( radio3->sizeHint() ); + mDestination.rangeBox->insert( radio3, 2 ); + vbox->addWidget( radio3, 0, AlignLeft ); + + QGridLayout *gbox = new QGridLayout( 2, 2, spacingHint() ); + vbox->addLayout( gbox ); + + mDestination.fromInput = new QLineEdit( group ); + text = i18n("&From offset:"); + mDestination.fromLabel = new QLabel( mDestination.fromInput, text, group ); + gbox->addWidget( mDestination.fromLabel, 0, 0 ); + gbox->addWidget( mDestination.fromInput, 0, 1 ); + + mDestination.toInput = new QLineEdit( group ); + text = i18n("&To offset:"); + mDestination.toLabel = new QLabel( mDestination.toInput, text, group ); + gbox->addWidget( mDestination.toLabel, 1, 0 ); + gbox->addWidget( mDestination.toInput, 1, 1 ); + + connect( group, SIGNAL(clicked(int)), SLOT(rangeChanged(int)) ); + group->setButton(0); + rangeChanged(0); + enableButtonOK( !mDestination.fileInput->text().isEmpty() ); +} + +void CExportDialog::destinationChanged(const QString &_text) +{ + enableButtonOK( !_text.isEmpty() ); +} + +void CExportDialog::setupOptionPage( void ) +{ + QFrame *page = mFrame[ page_option ]; + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + mOptionStack = new QWidgetStack( page, "stack" ); + if( mOptionStack == 0 ) { return; } + topLayout->addWidget( mOptionStack ); + + makeTextOption(); + makeHtmlOption(); + makeRtfOption(); + makeCArrayOption(); + mOptionStack->raiseWidget( (int)option_text ); + + QSize size = mOptionStack->sizeHint(); + size += QSize(spacingHint()*2, spacingHint()*2); + page->setMinimumSize( size ); +} + + +void CExportDialog::makeTextOption( void ) +{ + QFrame *page = new QFrame( mFrame[ page_option ] ); + if( page == 0 ) { return; } + mOptionStack->addWidget( page, option_text ); + + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + QString text = i18n("No options for this format."); + QLabel *label = new QLabel( text, page ); + topLayout->addWidget( label, 0, AlignCenter ); +} + + +void CExportDialog::makeHtmlOption( void ) +{ + QFrame *page = new QFrame( mFrame[ page_option ] ); + if( page == 0 ) { return; } + mOptionStack->addWidget( page, option_html ); + + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + text = i18n("HTML Options (one table per page)"); + QLabel *label = new QLabel( text, page ); + topLayout->addWidget( label ); + + QFrame *hline = new QFrame( page ); + hline->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + topLayout->addWidget( hline ); + + QFrame *frame = new QFrame( page ); + if( frame == 0 ) { return; } + topLayout->addWidget( frame ); + + QGridLayout *gbox = new QGridLayout( frame, 4, 2, 0, spacingHint() ); + if( gbox == 0 ) { return; } + gbox->setColStretch( 1, 10 ); + + mHtml.lineSpin = new QSpinBox( frame ); + mHtml.lineSpin->setMinimumWidth( fontMetrics().maxWidth()*10 ); + mHtml.lineSpin->setRange( 5, INT_MAX ); + gbox->addWidget( mHtml.lineSpin, 0, 1 ); + + text = i18n("&Lines per table:"); + label = new QLabel( mHtml.lineSpin, text, frame ); + gbox->addWidget( label, 0, 0 ); + + mHtml.prefixInput = new QLineEdit( frame, "prefix" ); + mHtml.prefixInput->setMinimumWidth( fontMetrics().maxWidth()*10 ); + gbox->addWidget( mHtml.prefixInput, 1, 1 ); + + text = i18n("Filename &prefix (in package):"); + label = new QLabel( mHtml.prefixInput, text, frame ); + gbox->addWidget( label, 1, 0 ); + + QStringList headerList; + headerList.append( i18n("None") ); + headerList.append( i18n("Filename with Path") ); + headerList.append( i18n("Filename") ); + headerList.append( i18n("Page Number") ); + + mHtml.topCombo = new QComboBox( false, frame ); + mHtml.topCombo->insertStringList( headerList ); + gbox->addWidget( mHtml.topCombo, 2, 1 ); + + text = i18n("Header &above text:"); + label = new QLabel( mHtml.topCombo, text, frame ); + gbox->addWidget( label, 2, 0 ); + + mHtml.bottomCombo = new QComboBox( false, frame ); + mHtml.bottomCombo->insertStringList( headerList ); + gbox->addWidget( mHtml.bottomCombo, 3, 1 ); + + text = i18n("&Footer below text:"); + label = new QLabel( mHtml.bottomCombo, text, frame ); + gbox->addWidget( label, 3, 0 ); + + text = i18n("Link \"index.html\" to &table of contents file"); + mHtml.symlinkCheck = new QCheckBox( text, page ); + topLayout->addWidget( mHtml.symlinkCheck ); + + text = i18n("&Include navigator bar"); + mHtml.navigatorCheck = new QCheckBox( text, page ); + topLayout->addWidget( mHtml.navigatorCheck ); + + text = i18n("&Use black and white only"); + mHtml.bwCheck = new QCheckBox( text, page ); + topLayout->addWidget( mHtml.bwCheck ); + + topLayout->addStretch(10); +} + + +void CExportDialog::makeRtfOption( void ) +{ + QFrame *page = new QFrame( mFrame[ page_option ] ); + if( page == 0 ) { return; } + mOptionStack->addWidget( page, option_rtf ); + + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + QString text = i18n("No options for this format."); + QLabel *label = new QLabel( text, page ); + topLayout->addWidget( label, 0, AlignCenter ); +} + + +void CExportDialog::makeCArrayOption( void ) +{ + QFrame *page = new QFrame( mFrame[ page_option ] ); + mOptionStack->addWidget( page, option_carray ); + + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + + text = i18n("C Array Options"); + QLabel *label = new QLabel( text, page ); + topLayout->addWidget( label, 0, AlignLeft ); + + QFrame *hline = new QFrame( page ); + hline->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + topLayout->addWidget( hline ); + + QGridLayout *gbox = new QGridLayout( 3, 2, spacingHint() ); + topLayout->addLayout( gbox ); + gbox->setColStretch( 1, 10 ); + + mArray.nameInput = new QLineEdit( page ); + gbox->addWidget( mArray.nameInput, 0, 1 ); + text = i18n("Array name:"); + label = new QLabel( mArray.nameInput, text, page ); + gbox->addWidget( label, 0, 0 ); + + QStringList typeList; + typeList.append( i18n("char") ); + typeList.append( i18n("unsigned char") ); + typeList.append( i18n("short") ); + typeList.append( i18n("unsigned short") ); + typeList.append( i18n("int") ); + typeList.append( i18n("unsigned int") ); + typeList.append( i18n("float") ); + typeList.append( i18n("double") ); + mArray.typeCombo = new QComboBox( false, page ); + mArray.typeCombo->insertStringList( typeList ); + mArray.typeCombo->setMinimumWidth( fontMetrics().maxWidth()*10 ); + gbox->addWidget( mArray.typeCombo, 1, 1 ); + text = i18n("Element type:"); + label = new QLabel( mArray.typeCombo, text, page ); + gbox->addWidget( label, 1, 0 ); + + mArray.lineSizeSpin = new QSpinBox( page ); + mArray.lineSizeSpin->setMinimumWidth( fontMetrics().maxWidth()*10 ); + mArray.lineSizeSpin->setRange( 1, INT_MAX ); + gbox->addWidget( mArray.lineSizeSpin, 2, 1 ); + text = i18n("Elements per line:"); + label = new QLabel( mArray.lineSizeSpin, text, page ); + gbox->addWidget( label, 2, 0 ); + + text = i18n("Print unsigned values as hexadecimal"); + mArray.hexadecimalCheck = new QCheckBox( text, page ); + topLayout->addWidget( mArray.hexadecimalCheck ); + + topLayout->addStretch(10); +} + + + + + +void CExportDialog::formatChanged( int index ) +{ + mDestination.formatCombo->setCurrentItem(index); + mDestination.fileExtraLabel->setEnabled( index == option_html ); + mOptionStack->raiseWidget( index ); +} + + +void CExportDialog::rangeChanged( int id ) +{ + bool state = id == 2 ? true : false; + mDestination.toLabel->setEnabled( state ); + mDestination.fromLabel->setEnabled( state ); + mDestination.toInput->setEnabled( state ); + mDestination.fromInput->setEnabled( state ); +} + + +void CExportDialog::browserClicked( void ) +{ + QString url; + if( mDestination.formatCombo->currentItem() == option_html ) + { + url = KFileDialog::getExistingDirectory( mWorkDir, topLevelWidget() ); + } + else + { + url = KFileDialog::getSaveFileName( mWorkDir, "*", topLevelWidget() ); + } + + if( url.isEmpty() ) + { + return; + } + + int index = url.findRev( '/' ); + if( index != -1 ) + { + mWorkDir = url.left( index+1 ); + } + mDestination.fileInput->setText( url ); +} + + +void CExportDialog::slotOk( void ) +{ + QString path( mDestination.fileInput->text() ); + + int format = mDestination.formatCombo->currentItem(); + if( format == option_text ) + { + if( verifyFileDestnation( this, i18n("Export Document"), path ) == false ) + { + return; + } + + SExportText e; + uint mode; + if( collectRange( mode, e.range.start, e.range.stop ) == false ) + { + showEntryFailure( this, QString("") ); + return; + } + e.range.mode = (SExportRange::EMode)mode; // FIXME + e.destFile = path; + + hide(); + emit exportText(e); + } + else if( format == option_html ) + { + SExportHtml e; + uint mode; + if( collectRange( mode, e.range.start, e.range.stop ) == false ) + { + showEntryFailure( this, QString("") ); + return; + } + e.range.mode = (SExportRange::EMode)mode; // FIXME + + const QString str = mHtml.prefixInput->text().stripWhiteSpace(); + mHtml.prefixInput->setText( str ); + if( mHtml.prefixInput->text().isEmpty() == true ) + { + mHtml.prefixInput->setText( "table" ); + } + + const QString prefix = mHtml.prefixInput->text(); + for( uint i=0; ivalue(); + e.topCaption = mHtml.topCombo->currentItem(); + e.bottomCaption = mHtml.bottomCombo->currentItem(); + e.symLink = mHtml.symlinkCheck->isChecked(); + e.navigator = mHtml.navigatorCheck->isChecked(); + e.blackWhite = mHtml.bwCheck->isChecked(); + + hide(); + emit exportHtml(e); + } + else if( format == option_rtf ) + { + QString msg = i18n("This format is not yet supported."); + KMessageBox::sorry( this, msg ); + } + else if( format == option_carray ) + { + if( verifyFileDestnation( this, i18n("Export Document"), path ) == false ) + { + return; + } + + SExportCArray e; + uint mode; + if( collectRange( mode, e.range.start, e.range.stop ) == false ) + { + showEntryFailure( this, QString("") ); + return; + } + e.range.mode = (SExportRange::EMode)mode; // FIXME + e.destFile = path; + e.arrayName = mArray.nameInput->text(); + e.elementType = mArray.typeCombo->currentItem(); + e.elementPerLine = mArray.lineSizeSpin->value(); + e.unsignedAsHexadecimal = mArray.hexadecimalCheck->isChecked(); + + emit exportCArray( e ); + } +} + + + + +bool CExportDialog::collectRange( uint &mode, uint &start, uint &stop ) +{ + QButton *b = mDestination.rangeBox->selected(); + if( b == 0 ) + { + return( false ); + } + + int id = mDestination.rangeBox->id( b ); + if( id == 0 ) + { + mode = SExportRange::All; + } + else if( id == 1 ) + { + mode = SExportRange::Selection; + } + else if( id == 2 ) + { + mode = SExportRange::Range; + bool ok1 = stringToOffset( mDestination.fromInput->text(), start ); + bool ok2 = stringToOffset( mDestination.toInput->text(), stop ); + if( ok1 == false || ok2 == false || start >= stop ) + { + return( false ); + } + } + else + { + return( false ); + } + + return( true ); +} + + +// +// This one will attempt to create a directory if 'path' +// specifies a nonexistent name. +// +bool CExportDialog::verifyPackage( const QString &path ) +{ + const QString title = i18n("Export Document"); + + if( path.isEmpty() == true ) + { + QString msg = i18n("You must specify a destination."); + KMessageBox::sorry( this, msg, title ); + return( false ); + } + + QFileInfo info( path ); + if( info.exists() == false ) + { + QDir directory; + if( directory.mkdir( path ) == false ) + { + QString msg; + msg += i18n("Unable to create a new folder"); + msg += "\n"; + msg += path; + KMessageBox::sorry( this, msg, title ); + return( false ); + } + } + else + { + if( info.isDir() == false ) + { + QString msg = i18n("You have specified an existing file"); + KMessageBox::sorry( this, msg, title ); + return( false ); + } + else + { + if( info.isWritable() == false ) + { + QString msg = i18n( "" + "You do not have write permission to this folder."); + KMessageBox::sorry( this, msg, title ); + return( false ); + } + + const QString prefix = mHtml.prefixInput->text(); + QString f1 = QString("%1%2.html").arg(prefix).arg("00000000"); + QString f2 = QString("%1%2.html").arg(prefix).arg("99999999"); + + QString msg = i18n( "" + "You have specified an existing folder.\n" + "If you continue, any existing file in the range " + "\"%1\" to \"%2\" can be lost.\n" + "Continue?").arg(f1).arg(f2); + int reply = KMessageBox::warningContinueCancel( this, msg, title ); + if( reply != KMessageBox::Continue ) + { + return( false ); + } + + } + } + + return( true ); +} + +#include "exportdialog.moc" diff --git a/khexedit/exportdialog.h b/khexedit/exportdialog.h new file mode 100644 index 0000000..6d89ac3 --- /dev/null +++ b/khexedit/exportdialog.h @@ -0,0 +1,138 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _EXPORT_DIALOG_H_ +#define _EXPORT_DIALOG_H_ + + +class QButtonGroup; +class QComboBox; +class QCheckBox; +class QFrame; +class QLabel; +class QLineEdit; +class QSpinBox; +class QWidgetStack; +class KSimpleConfig; + +#include +#include "hexbuffer.h" + + +class CExportDialog : public KDialogBase +{ + Q_OBJECT + + public: + enum EPage + { + page_destination = 0, + page_option, + page_max + }; + + enum OptionPage + { + option_text = 0, + option_html, + option_rtf, + option_carray, + option_max + }; + + CExportDialog( QWidget *parent = 0, char *name = 0, bool modal = false ); + ~CExportDialog( void ); + void writeConfiguration( void ); + + protected: + void showEvent( QShowEvent *e ); + + protected slots: + virtual void slotOk( void ); + void destinationChanged(const QString &); + private: + struct SDestinationWidgets + { + QComboBox *formatCombo; + QLabel *fileExtraLabel; + QLineEdit *fileInput; + QLabel *fromLabel; + QLabel *toLabel; + QButtonGroup *rangeBox; + QLineEdit *fromInput; + QLineEdit *toInput; + }; + + struct SHtmlWidgets + { + QSpinBox *lineSpin; + QLineEdit *prefixInput; + QComboBox *topCombo; + QComboBox *bottomCombo; + QCheckBox *navigatorCheck; + QCheckBox *symlinkCheck; + QCheckBox *bwCheck; + }; + + struct SArrayWidgets + { + QLineEdit *nameInput; + QComboBox *typeCombo; + QSpinBox *lineSizeSpin; + QCheckBox *hexadecimalCheck; + }; + + private slots: + void rangeChanged( int id ); + void formatChanged( int index ); + void browserClicked( void ); + + private: + void setupDestinationPage( void ); + void setupOptionPage( void ); + void makeTextOption( void ); + void makeHtmlOption( void ); + void makeRtfOption( void ); + void makeCArrayOption( void ); + void readConfiguration( void ); + bool collectRange( uint &mode, uint &start, uint &stop ); + bool verifyPackage( const QString &path ); + + signals: + void exportText( const SExportText &e ); + void exportHtml( const SExportHtml &e ); + void exportCArray( const SExportCArray &e ); + + private: + QFrame *mFrame[ page_max ]; + QWidgetStack *mOptionStack; + SDestinationWidgets mDestination; + SHtmlWidgets mHtml; + SArrayWidgets mArray; + KSimpleConfig *mConfig; + + QString mWorkDir; +}; + + + + + +#endif diff --git a/khexedit/fileinfodialog.cc b/khexedit/fileinfodialog.cc new file mode 100644 index 0000000..b9dff60 --- /dev/null +++ b/khexedit/fileinfodialog.cc @@ -0,0 +1,330 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include + +#include +#include +#include + +#include "fileinfodialog.h" +#include "listview.h" + +// quick'n'dirty hack to have the occurrence column sorted correctly +class CStatisticListViewItem : public QListViewItem +{ + public: + CStatisticListViewItem( QListView * parent, QListViewItem * after, + QString label1, QString label2, QString label3, QString label4, + QString label5, QString label6, QString label7, int i, int o) + : QListViewItem( parent, after, label1, label2, label3, label4, label5, label6, label7), + item( i ), + occurrence( o ) + {} + + virtual int compare( QListViewItem *i, int col, bool ascending/*Qt doc says: ignore this one*/ ) const + { + // occurrence column (or the percent one)? + if( col == 5 || col == 6 ) + { + const int otherOccurrence = ((CStatisticListViewItem*)i)->occurrence; + return occurrence < otherOccurrence ? -1 : occurrence == otherOccurrence ? 0 : 1; + } + // char column? + else if( col == 4 ) + { + const int otherItem = ((CStatisticListViewItem*)i)->item; + return item < otherItem ? -1 : item == otherItem ? 0 : 1; + } + // default + else + return QListViewItem::compare(i,col,ascending); + } + + protected: + // no of byte + int item; + // number of the byte's occurrence + int occurrence; +}; + + + +CFileInfoDialog::CFileInfoDialog( QWidget *parent,const char *name,bool modal) + :KDialogBase( Plain, i18n("Statistics"), Help|User1|Cancel, User1, + parent, name, modal, true, i18n("&Update") ), + mBusy(false), mDirty(false) +{ + setHelp( "khexedit/khexedit.html", QString::null ); + + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() ); + if( topLayout == 0 ) { return; } + + + QGridLayout *gbox = new QGridLayout( 2, 2, spacingHint() ); + if( gbox == 0 ) { return; } + topLayout->addLayout( gbox ); + gbox->setColStretch( 1, 10 ); + + text = i18n("File name: "); + QLabel *label = new QLabel( text, plainPage() ); + gbox->addWidget( label, 0, 0 ); + + text = i18n("Size [bytes]: "); + label = new QLabel( text, plainPage() ); + gbox->addWidget( label, 1, 0 ); + + mFileNameLabel = new QLabel( plainPage() ); + mFileSizeLabel = new QLabel( plainPage() ); + gbox->addWidget( mFileNameLabel, 0, 1 ); + gbox->addWidget( mFileSizeLabel, 1, 1 ); + + mFrequencyList = new CListView( plainPage(), "stringList" ); + mFrequencyList->setFont( KGlobalSettings::fixedFont() ); + + mFrequencyList->addColumn( i18n("Hexadecimal") ); + mFrequencyList->addColumn( i18n("Decimal") ); + mFrequencyList->addColumn( i18n("Octal") ); + mFrequencyList->addColumn( i18n("Binary") ); + mFrequencyList->addColumn( i18n("Text") ); + mFrequencyList->addColumn( i18n("Occurrence") ); + mFrequencyList->addColumn( i18n("Percent") ); + mFrequencyList->setAllColumnsShowFocus( true ); + mFrequencyList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken ); + topLayout->addWidget( mFrequencyList, 10 ); + + mDirtyLabel = new QLabel( plainPage() ); + mDirtyLabel->setFixedHeight( fontMetrics().height() ); + topLayout->addWidget( mDirtyLabel ); + + setStatistics(); + setColumnWidth(); + mFrequencyList->setVisibleItem( 15 ); + + // + // Load the first set of data when this timer expires. I do it this + // way so that the dialog will be visible when the load operation starts. + // + startTimer( 0 ); +} + + +CFileInfoDialog::~CFileInfoDialog( void ) +{ +} + + +void CFileInfoDialog::slotUser1( void ) // Update +{ + if( mBusy ) + return; + + SStatisticControl *sc = new SStatisticControl; + if( sc == 0 ) { return; } + + mBusy = true; + emit collectStatistic( *sc ); + mBusy = false; + + delete sc; + +} + + +void CFileInfoDialog::setDirty( void ) +{ + if( mDirty ) + return; + + mDirtyLabel->setText( + i18n("Warning: Document has been modified since last update")); + mDirty = true; +} + + +void CFileInfoDialog::setClean( void ) +{ + if( !mDirty ) + return; + + mDirtyLabel->setText(""); + mDirty = false; +} + + +const char *printBin( uint val ) +{ + static char buf[9]; + for( int i = 0; i < 8; i++ ) + buf[7-i] = (val&(1<clear(); + mFileNameLabel->clear(); + mFileSizeLabel->clear(); + + static const QString u("?"); + QString d, h, o, b, c; + QListViewItem *item = 0; + + char buf[10]; + memset( buf, 0, sizeof( buf ) ); + + for( uint i=0; i<256; i++ ) + { + h.sprintf("0x%02x", i ); + d.sprintf("%03d", i ); + o.sprintf("%03o", i ); + b.sprintf("%s", printBin(i) ); + + const QChar _i((char)i); + c = _i.isPrint() ? _i : QChar('.'); + + item = new CStatisticListViewItem( mFrequencyList, item, h, d, o, b, c, u, u, i, -1 ); + if( i == 0 ) + mFrequencyList->setSelected( item, true ); + } +} + + + +void CFileInfoDialog::setStatistics( SStatisticControl &sc ) +{ + setClean(); + mFrequencyList->clear(); + mFileNameLabel->setText( sc.documentName ); + mFileSizeLabel->setText( KGlobal::locale()->formatNumber(sc.documentSize, 0) ); + + QString d, h, o, b, c, n, p; + QListViewItem *item = 0; + + uint size, pre, i; + // find width of occurrence + for( i=size=0; i<256; i++ ) + if( sc.occurrence[i] > size ) + size = sc.occurrence[i]; + for( pre = 1; size > 0 ; pre++ ) + size /= 10; + + for( i=0; i<256; i++ ) + { + h.sprintf("0x%02x", i ); + d.sprintf("%03d", i ); + o.sprintf("%03o", i ); + b.sprintf("%s", printBin(i) ); + + n = QString("%1").arg( sc.occurrence[i], pre ); + if( sc.documentSize == 0 ) + p = "0.00"; + else + { + double val = 100.0*((double)sc.occurrence[i]/(double)sc.documentSize); + p = QString("%1").arg( val, 6, 'f', 2 ); + } + + const QChar _i((char)i); + c = _i.isPrint() ? _i : QChar('.'); + + item = new CStatisticListViewItem( mFrequencyList, item, h, d, o, b, c, n, p, i, sc.occurrence[i] ); + if( i == 0 ) + mFrequencyList->setSelected( item, true ); + } +} + + + +void CFileInfoDialog::setColumnWidth( void ) +{ + const QFontMetrics &fm = mFrequencyList->fontMetrics(); + int w0, w1, w2, w3, w4; + + w0 = -fm.minLeftBearing() - fm.minRightBearing() + 8 + fm.maxWidth(); + w3 = 0; + + w1 = fm.width( mFrequencyList->header()->label(0) ) + w0; + w2 = fm.width('0')*6; + w3 += w1 > w2 ? w1 : w2; + mFrequencyList->setColumnWidth( 0, w1 > w2 ? w1 : w2 ); + + w1 = fm.boundingRect( mFrequencyList->header()->label(1) ).width() + w0; + w2 = fm.width('0')*5; + w3 += w1 > w2 ? w1 : w2; + mFrequencyList->setColumnWidth( 1, w1 > w2 ? w1 : w2 ); + + w1 = fm.boundingRect( mFrequencyList->header()->label(2) ).width() + w0; + w2 = fm.width('0')*5; + w3 += w1 > w2 ? w1 : w2; + mFrequencyList->setColumnWidth( 2, w1 > w2 ? w1 : w2 ); + + w1 = fm.boundingRect( mFrequencyList->header()->label(3) ).width() + w0; + w2 = fm.width('0')*10; + w3 += w1 > w2 ? w1 : w2; + mFrequencyList->setColumnWidth( 3, w1 > w2 ? w1 : w2 ); + + w1 = fm.boundingRect( mFrequencyList->header()->label(4) ).width() + w0; + w2 = fm.width('0')*3; + w3 += w1 > w2 ? w1 : w2; + mFrequencyList->setColumnWidth( 4, w1 > w2 ? w1 : w2 ); + + w1 = fm.boundingRect( mFrequencyList->header()->label(5) ).width() + w0; + w2 = fm.width('0')*10; + w3 += w1 > w2 ? w1 : w2; + mFrequencyList->setColumnWidth( 5, w1 > w2 ? w1 : w2 ); + + w4 = mFrequencyList->viewport()->width() - w3; + w1 = fm.boundingRect( mFrequencyList->header()->label(6) ).width() + w0; + w2 = fm.width('0')*3; + w1 = w1 > w2 ? w1 : w2; + mFrequencyList->setColumnWidth( 6, w1 > w4 ? w1 : w4 ); +} + + +void CFileInfoDialog::resizeEvent( QResizeEvent * ) +{ + setColumnWidth(); +} + + +void CFileInfoDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + setColumnWidth(); + mFrequencyList->setFocus(); +} + + +void CFileInfoDialog::timerEvent( QTimerEvent * ) +{ + killTimers(); + slotUser1(); +} + + + +#include "fileinfodialog.moc" diff --git a/khexedit/fileinfodialog.h b/khexedit/fileinfodialog.h new file mode 100644 index 0000000..c994d48 --- /dev/null +++ b/khexedit/fileinfodialog.h @@ -0,0 +1,74 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _FILE_INFO_DIALOG_H_ +#define _FILE_INFO_DIALOG_H_ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +class QLabel; + +#include + +class CListView; +#include "hexbuffer.h" + +class CFileInfoDialog : public KDialogBase +{ + Q_OBJECT + + public: + CFileInfoDialog( QWidget *parent=0, const char *name=0,bool modal=false ); + ~CFileInfoDialog( void ); + + void setStatistics( void ); + void setStatistics( SStatisticControl &sc ); + + public slots: + void setDirty( void ); + void setClean( void ); + + protected slots: + virtual void slotUser1( void ); + + protected: + virtual void resizeEvent( QResizeEvent * ); + virtual void showEvent( QShowEvent * ); + virtual void timerEvent( QTimerEvent * ); + + private: + void setColumnWidth( void ); + + signals: + void collectStatistic( SStatisticControl &sc ); + + private: + bool mBusy; + bool mDirty; + CListView *mFrequencyList; + QLabel *mFileNameLabel; + QLabel *mFileSizeLabel; + QLabel *mDirtyLabel; +}; + +#endif diff --git a/khexedit/hexbuffer.cc b/khexedit/hexbuffer.cc new file mode 100644 index 0000000..0c1d598 --- /dev/null +++ b/khexedit/hexbuffer.cc @@ -0,0 +1,5099 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "hexbuffer.h" +#include "hexerror.h" + +// +// There are some comments marked with a "// ##" at various places. +// These indicate a patch from Sergey A. Sukiyazov which I have applied +// "as is" for now. The number of QString::fromLocal8Bit in this modification +// indicates that I should perhaps modify code elsewhere as well +// (espen 2000-11-26) +// + +// #define DEBUG_FIXED_SIZE 1024 +// #define PRINTER_TEST + + +CHexAction::CHexAction( HexAction action, uint offset ) +{ + mAction = action; + mOffset = offset; + mSize = 0; + mData = 0; + mDataSize = 0; + mNext = 0; +} + +CHexAction::~CHexAction( void ) +{ + delete [] mData; +} + +void CHexAction::setData( uint size, char *data, uint dataSize ) +{ + + if( data != 0 && dataSize > 0 ) + { + mData = new char[ dataSize ]; + if( mData == 0 ) + { + return; + } + memcpy( mData, data, dataSize ); + mDataSize = dataSize; + } + else + { + mDataSize = 0; + mData = 0; + } + mSize = size; +} + + +CHexActionGroup::CHexActionGroup( uint startOffset, uint startBit ) +{ + mStartOffset = startOffset; + mStartBit = startBit; + mHexAction = 0; +} + +CHexActionGroup::~CHexActionGroup( void ) +{ + CHexAction *ptr = mHexAction; + while( ptr != 0 ) + { + CHexAction *next = ptr->mNext; + delete ptr; + ptr = next; + } +} + +void CHexActionGroup::insertAction( CHexAction *hexAction ) +{ + hexAction->mNext = mHexAction; + mHexAction = hexAction; +} + + + +int SFilterControl::execute( uchar *dest, uchar *src, uint size ) +{ + if( size == 0 ) + { + return( Err_IllegalArgument ); + } + + uint numElement = operand.size(); + if( operation == OperandAndData ) + { + if( numElement == 0 ) { return( Err_IllegalArgument ); } + if( forward == true ) + { + for( uint i = 0; i < size; ) + { + for( uint j = 0; i < size && j < numElement; j++, i++ ) + { + dest[i] = src[i] & operand[j]; + } + } + } + else + { + for( uint i = size; i > 0; ) + { + for( uint j = numElement; i > 0 && j > 0; j--, i-- ) + { + dest[i-1] = src[i-1] & operand[j-1]; + } + } + } + } + else if( operation == OperandOrData ) + { + if( numElement == 0 ) { return( Err_IllegalArgument ); } + if( forward == true ) + { + for( uint i = 0; i < size; ) + { + for( uint j = 0; i < size && j < numElement; j++, i++ ) + { + dest[i] = src[i] | operand[j]; + } + } + } + else + { + for( uint i = size; i > 0; ) + { + for( uint j = numElement; i > 0 && j > 0; j--, i-- ) + { + dest[i-1] = src[i-1] | operand[j-1]; + } + } + } + } + else if( operation == OperandXorData ) + { + if( numElement == 0 ) { return( Err_IllegalArgument ); } + if( forward == true ) + { + for( uint i = 0; i < size; ) + { + for( uint j = 0; i < size && j < numElement; j++, i++ ) + { + dest[i] = src[i] ^ operand[j]; + } + } + } + else + { + for( uint i = size; i > 0; ) + { + for( uint j = numElement; i > 0 && j > 0; j--, i-- ) + { + dest[i-1] = src[i-1] ^ operand[j-1]; + } + } + } + } + else if( operation == InvertData ) + { + for( uint i = 0; i < size; i++ ) + { + dest[i] = ~src[i]; + } + } + else if( operation == ReverseData ) + { + for( uint i = 0; i < size; i++ ) + { + uchar flag = src[i]; + uchar rev = 0; + for( uint j = 0; j < 8; j++ ) + { + rev |= (((flag & 0x80) >> (7-j))); + flag <<= 1; + } + dest[i] = rev; + } + } + else if( operation == RotateData || operation == ShiftData ) + { + // + // Only forward here + // + bool up = rotate[1] > 0 ? true : false; + int range = rotate[0]; + int shift = abs(rotate[1]); + if( range == 0 || shift == 0 ) { return( Err_IllegalArgument ); } + shift = shift % (range*8); + + int b = shift / 8; + int s = shift - b * 8; + + for( uint i = 0; i < size; ) + { + if( up == true ) + { + int j; + if( operation == RotateData ) + { + for( j=0; j < b && i+range < size ; i++, j++ ) + { + dest[i] = src[i+range-b]; + } + } + else + { + for( j=0; j < b && i < size ; dest[i] = 0, i++, j++ ); + } + for( ; j < range && i < size ; i++, j++ ) + { + dest[i] = src[i-b]; + } + + uchar last = dest[i-1]; + for( int k=1; k <= j; k++ ) + { + dest[i-k] >>= s; + if( k < j ) + { + dest[i-k] |= dest[i-k-1]<<(8-s); + } + else if( j == range && operation == RotateData ) + { + dest[i-k] |= last<<(8-s); + } + } + } + else + { + int j; + for( j=0; j+b < range && i+b < size ; i++, j++ ) + { + dest[i] = src[i+b]; + } + for( ; j < range && i < size ; i++, j++ ) + { + dest[i] = operation == RotateData ? src[i+b-range] : 0; + } + + uchar first = dest[i-j]; + for( int k=j; k>0; k-- ) + { + dest[i-k] <<= s; + if( k>1 ) + { + dest[i-k] |= dest[i-k+1]>>(8-s); + } + else if( j == range && operation == RotateData ) + { + dest[i-k] |= first>>(8-s); + } + } + } + } + } + else if( operation == SwapBits ) + { + // + // Swap bits. Based on Leon Lessing's work. + // + + // + // Make non swapped version first. + // + for( uint i = 0; i < size; i++ ) + { + dest[i] = src[i]; + } + + // + // Swap the pairs the have been defined + // Format of operand (example): + // 7 2 5 0 0 0 0 0 + // Swap bit 7 with bit 2 and swap bit 5 with bit 0 + // + for( uint j=0; j<4; j++ ) + { + uchar b1 = 1 << (uchar)operand[j*2]; + uchar b2 = 1 << (uchar)operand[j*2+1]; + if( b1 == b2 ) { continue; } // Equal, no need to swap. + + for( uint i = 0; i < size; i++ ) + { + uchar b = 0; + if( dest[i] & b1 ) { b |= b2; } + if( dest[i] & b2 ) { b |= b1; } + + // + // A short description so that I will understand what the + // h... is going on five minutes from now. + // + // Destination byte is masked (AND'ed) with the inverse bitmap + // (the noninversed bitmap contains position of the + // two swap bits, eg 7-2 gives 10000100). Then the destination + // is OR'ed with the swapped bitmap. + // + dest[i] = (dest[i] & ~(b1 | b2)) | b; + } + } + } + else + { + return( Err_IllegalArgument ); + } + + return( Err_Success ); +} + + +const char *SExportCArray::printFormatted( const char *b, uint maxSize ) const +{ + static char buf[12]; + if( elementType == Char ) + { + char e = 0; + memcpy( &e, b, QMIN(sizeof(e),maxSize) ); + sprintf( buf, "%d", e ); + return( buf ); + } + else if( elementType == Uchar ) + { + unsigned char e = 0; + memcpy( &e, b, QMIN(sizeof(e),maxSize) ); + if( unsignedAsHexadecimal == true ) + { + sprintf( buf, "0x%02x", e ); + } + else + { + sprintf( buf, "%u", e ); + } + return( buf ); + } + else if( elementType == Short ) + { + short e = 0; + memcpy( &e, b, QMIN(sizeof(e),maxSize) ); + sprintf( buf, "%d", e ); + return( buf ); + + } + else if( elementType == Ushort ) + { + unsigned short e = 0; + memcpy( &e, b, QMIN(sizeof(e),maxSize) ); + if( unsignedAsHexadecimal == true ) + { + sprintf( buf, "0x%04x", e ); + } + else + { + sprintf( buf, "%u", e ); + } + return( buf ); + } + else if( elementType == Int ) + { + int e = 0; + memcpy( &e, b, QMIN(sizeof(e),maxSize) ); + sprintf( buf, "%u", e ); + return( buf ); + } + else if( elementType == Uint ) + { + unsigned int e = 0; + memcpy( &e, b, QMIN(sizeof(e),maxSize) ); + if( unsignedAsHexadecimal == true ) + { + sprintf( buf, "0x%08x", e ); + } + else + { + sprintf( buf, "%u", e ); + } + return( buf ); + } + else if( elementType == Float ) + { + float e = 0; + memcpy( &e, b, QMIN(sizeof(e),maxSize) ); + sprintf( buf, "%f", e ); + return( buf ); + } + else if( elementType == Double ) + { + double e = 0; + memcpy( &e, b, QMIN(sizeof(e),maxSize) ); + sprintf( buf, "%f", e ); + return( buf ); + } + + else + { + return(""); + } +} + + +QString SExportCArray::variableName( uint range ) const +{ + const char *typeString[] = + { + "char", + "unsigned char", + "short", + "unsigned short", + "int", + "unsigned int", + "float", + "double" + }; + + uint es = elementSize(); + uint numElement = range / es + ((range % es) ? 1 : 0); + + return( QString("%1 %2[%2]").arg(typeString[elementType]). + arg(arrayName).arg(numElement) ); +} + + + +int SExportCArray::elementSize( void ) const +{ + if( elementType == Char || elementType == Uchar ) + { + return( sizeof(char) ); + } + else if( elementType == Short || elementType == Ushort ) + { + return( sizeof(short) ); + } + else if( elementType == Int || elementType == Uint ) + { + return( sizeof(int) ); + } + else if( elementType == Float ) + { + return( sizeof(float) ); + } + else if( elementType == Double ) + { + return( sizeof(double) ); + } + else + { + return(1); + } +} + + +char CHexBuffer::mHexBigBuffer[16]= +{ + '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' +}; + +char CHexBuffer::mHexSmallBuffer[16]= +{ + '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' +}; + +char CHexBuffer::mDecBuffer[10]= +{ + '0','1','2','3','4','5','6','7','8','9' +}; + +char CHexBuffer::mOctBuffer[8]= +{ + '0','1','2','3','4','5','6','7' +}; + + +SCursorState CHexBuffer::mCursorState; +SFileState CHexBuffer::mFileState; + + + + +CHexBuffer::CHexBuffer( void ) + :QByteArray() +{ + mColorIndex = 0; + mPrintBuf = 0; + mLoadingData = false; + mEditMode = EditReplace; + mActiveEditor = edit_primary; + + mDocumentModified = false; + + #ifdef DEBUG_FIXED_SIZE + setMaximumSize( DEBUG_FIXED_SIZE ); + #else + setMaximumSize( ~0 ); + #endif + + setDocumentSize(0); + + #ifdef PRINTER_TEST + puts(" Printer test is activated"); + #endif + + + setInputMode( mInputMode ); + + int errCode = setLayout( mLayout ); + if( errCode != 0 ) + { + return; + } + setColor( mColor ); + setFont( mFontInfo.init() ); + setShowCursor( true ); + setDisableCursor( false ); + setEditMode( EditReplace, false, false ); + setSoundState( false, false ); + + mUndoLimit = 10; + mUndoIndex = 0; + mUndoList.setAutoDelete( TRUE ); + mBookmarkList.setAutoDelete( TRUE ); +} + + +CHexBuffer::~CHexBuffer( void ) +{ + //debug("CHexBuffer::~CHexBuffer"); + delete [] mColorIndex; + delete [] mPrintBuf; +} + + + +bool CHexBuffer::hasFileName( void ) +{ + // + // FIXME: Files can be called "Untitled" so this must be corrected. + // + if( mUrl.isEmpty() || mUrl.contains( i18n( "Untitled" ), false ) ) + { + return( false ); + } + else + { + return( true ); + } +} + + + +int CHexBuffer::setLayout( SDisplayLayout &layout ) +{ + mLayout = layout; + mLayout.verify(); + + if( mLayout.primaryMode == SDisplayLayout::textOnly ) + { + mActiveEditor = edit_primary; + setEditMode( mEditMode ); + } + + mCursor.setLineSize( mLayout.lineSize ); + mCursor.addOffset( 0 ); // This will only reset the cell position + + computeLineWidth(); + cursorCompute(); + + delete [] mColorIndex; mColorIndex = 0; + delete [] mPrintBuf; mPrintBuf = 0; + + mColorIndex = new unsigned char[ mLayout.lineSize ]; + if( mColorIndex == 0 ) + { + return( Err_NoMemory ); + } + setColor( mColor ); + + // + // The 'mPrintBuf' is used to store formatted text. It is used for all + // print operations and must have the size of the 'mDpyState.lineSize' which + // is the number of bytes in one single display line. + // + mPrintBuf = new char[ mLayout.lineSize < 12 ? 12 : mLayout.lineSize ]; + if( mPrintBuf == 0 ) + { + delete [] mColorIndex; mColorIndex = 0; + return( Err_NoMemory ); + } + + return( Err_Success ); +} + + +void CHexBuffer::setColor( SDisplayColor &color ) +{ + mColor = color; + + // + // Test... + // + //mColor.secondTextBg = Qt::yellow; + //mColor.offsetBg = Qt::lightGray; + //mColor.gridFg = Qt::darkCyan; + + /* + mColor.secondTextBg = mColor.textBg; + mColor.offsetBg = mColor.textBg; + mColor.gridFg = mColor.textBg; + */ + + if( mColorIndex != 0 ) + { + uint columnSize = mLayout.columnSize == 0 ? 1 : mLayout.columnSize; + for( uint i = 0, entry = 0; i < mLayout.lineSize; i++ ) + { + if( i > 0 && i % columnSize == 0 ) { entry = entry == 0 ? 1 : 0; } + mColorIndex[i] = entry; + } + } +} + +void CHexBuffer::setInputMode( SDisplayInputMode &mode ) +{ + mInputMode = mode; + if( mInputMode.allowResize == false && mEditMode != EditReplace ) + { + setEditMode( EditReplace ); + } +} + + +bool CHexBuffer::toggleEditor( void ) +{ + bool changed; + if( mLayout.secondaryMode == SDisplayLayout::hide ) + { + changed = mActiveEditor == edit_secondary ? true : false; + mActiveEditor = edit_primary; + } + else + { + changed = true; + mActiveEditor = mActiveEditor == edit_primary ? + edit_secondary : edit_primary; + } + + setEditMode( mEditMode ); // Sets the cursor shapes as well + + if( changed == true ) + { + mCursor.resetCell(); + cursorCompute(); + } + + return( changed ); +} + + + + + + + +bool CHexBuffer::matchWidth( uint width ) +{ + if( documentPresent() == false || (uint)mFixedWidth >= width ) + { + return( false ); + } + + width -= mFixedWidth; + + uint g = mLayout.columnSpacing == 0 ? 1 : mLayout.columnSize; + uint n = g * mNumCell; + uint u = mUnitWidth; + uint s = mLayout.secondaryMode == SDisplayLayout::hide ? 0 : g; + uint o = mLayout.columnSpacing == 0 ? 0 : mSplitWidth; + float x = (float)(width+o)/(float)(u*(n+s)+o); + + uint lineSize = (uint)x * g; + + if( mLayout.lockColumn == false ) + { + // + // Examine if we can add one or more entries from the next column. This + // will make the rightmost column smaller than the rest but we will + // utilize as much of the available space (ie., width) as possible. + // (Note that the entry itself (which represents one byte of filedata) + // can not be splitted, eg., in binary mode the entry is eight byte + // wide and will not be splitted). + // + int w = (int)((float)((int)x)* (float)(u*(n+s)+o) - (float)o); + if( w > 0 && (uint)w < width ) + { + width -= w; + if( width > o ) + { + x = (float)(width-o) / (float)(u*(mNumCell+1)); + lineSize += (uint)x; + } + } + } + + if( lineSize == 0 || lineSize == mLayout.lineSize ) + { + // + // We have to redraw all text if a change occurs so we avoid it if + // possible. + // + return( false ); + } + + mLayout.lineSize = lineSize; + setLayout( mLayout ); + return( true ); +} + + +void CHexBuffer::setNonPrintChar( QChar nonPrintChar ) +{ + mFontInfo.nonPrintChar = nonPrintChar; +} + + +void CHexBuffer::setShowCursor( bool showCursor ) +{ + mShowCursor = showCursor; +} + + +void CHexBuffer::setDisableCursor( bool disableCursor ) +{ + mDisableCursor = disableCursor; +} + + +void CHexBuffer::setCursorShapeModifier( bool alwaysBlock, bool thickInsert ) +{ + mCursor.setShapeModifier( alwaysBlock, thickInsert ); + setEditMode( mEditMode ); +} + +void CHexBuffer::setEditMode( EEditMode editMode, bool alwaysBlock, + bool thickInsert ) +{ + mCursor.setShapeModifier( alwaysBlock, thickInsert ); + setEditMode( editMode ); +} + +void CHexBuffer::setEditMode( EEditMode editMode ) +{ + mEditMode = editMode; + if( mEditMode == EditInsert ) + { + if( mActiveEditor == edit_primary ) + { + mCursor.setShape( SCursorSpec::thin, SCursorSpec::frame, mUnitWidth, + mNumCell ); + } + else + { + mCursor.setShape( SCursorSpec::frame, SCursorSpec::thin, mUnitWidth, + mNumCell ); + } + + } + else + { + if( mActiveEditor == edit_primary ) + { + mCursor.setShape( SCursorSpec::solid, SCursorSpec::frame, mUnitWidth, + mNumCell ); + } + else + { + mCursor.setShape( SCursorSpec::frame, SCursorSpec::solid, mUnitWidth, + mNumCell ); + } + } +} + + + +void CHexBuffer::setMaximumSize( uint maximumSize ) +{ + if( maximumSize == 0 ) { maximumSize = ~0; } + + mMaximumSize = maximumSize; + mFixedSizeMode = maximumSize == (uint)~0 ? false : true; + mCursor.setFixedSizeMode( mFixedSizeMode ); + + if( mLayout.offsetVisible == false ) + { + mOffsetSize = 0; + mOffsetIndex = 0; + printOffset = &CHexBuffer::printDummyOffset; + } + else + { + if( mLayout.offsetMode == SDisplayLayout::decimal ) + { + printOffset = &CHexBuffer::printDecimalOffset; + for( mOffsetSize=0; maximumSize > 0; mOffsetSize += 1 ) + { + maximumSize = maximumSize / 10; + } + mOffsetIndex = 10 - mOffsetSize; + } + else if( mLayout.offsetMode == SDisplayLayout::hexadecimal ) + { + if( mLayout.offsetUpperCase == true ) + { + printOffset = &CHexBuffer::printHexadecimalBigOffset; + } + else + { + printOffset = &CHexBuffer::printHexadecimalSmallOffset; + } + for( mOffsetSize=0; maximumSize > 0; mOffsetSize += 1 ) + { + maximumSize = maximumSize / 16; + } + if( mOffsetSize > 4 ) { mOffsetSize += 1; } // Space for the ':' sign + mOffsetIndex = 9 - mOffsetSize; + } + else + { + mLayout.offsetVisible = false; + mOffsetSize = 0; + mOffsetIndex = 0; + printOffset = &CHexBuffer::printDummyOffset; + } + } +} + + +void CHexBuffer::setDocumentSize( uint size ) +{ + if( size > mMaximumSize ) { size = mMaximumSize; } + mDocumentSize = size; + mCursor.setDocumentSize( size ); + updateBookmarkMap(true); +} + + +void CHexBuffer::setUndoLevel( uint level ) +{ + if( level < 10 ) { level = 10; } + + if( level >= mUndoLimit ) + { + mUndoLimit = level; + return; + } + else + { + // + // The maximum size decreases. If the list is larger than the the new + // limit, then reduce the list size starting with the oldest elements. + // + mUndoLimit = level; + while( mUndoList.count() >= mUndoLimit ) + { + mUndoList.removeFirst(); + mUndoIndex -= (mUndoIndex > 0 ? 1 : 0); + } + } +} + + +void CHexBuffer::setSoundState( bool inputSound, bool fatalSound ) +{ + mInputErrorSound = inputSound; + mFatalErrorSound = fatalSound; +} + + +void CHexBuffer::setBookmarkVisibility( bool showInColumn, bool showInEditor ) +{ + mShowBookmarkInOffsetColumn = showInColumn; + mShowBookmarkInEditor = showInEditor; +} + +int CHexBuffer::writeFile( QFile &file, CProgress &p ) +{ + uint offset = 0; + uint remaining = documentSize(); + + do + { + const uint blockSize = QMIN( 131072 /* == 1024 * 128 */ , remaining ); + const int writeSize = file.writeBlock( data() + offset, blockSize ); + if( writeSize == -1 ) + { + p.finish(); + return( Err_ReadFailed ); + } + offset += blockSize; + remaining -= blockSize; + + if( p.expired() == true ) + { + int errCode = p.step( (float)offset/(float)documentSize() ); + if( errCode == Err_Stop && remaining > 0 ) + { + p.finish(); + return( Err_Success ); + } + } + } + while( remaining > 0 ); + + p.finish(); + mDocumentModified = false; + registerDiskModifyTime( file ); + + return( Err_Success ); +} + + +int CHexBuffer::readFile( QFile &file, const QString &url, CProgress &p ) +{ + if( resize( file.size() + 100 ) == false ) + { + p.finish(); + return( Err_NoMemory ); + } + + if( file.size() > 0 ) + { + mLoadingData = true; + uint offset = 0; + uint remaining = file.size(); + while( remaining > 0 ) + { + const uint blockSize = QMIN( 131072 /* == 1024 * 128 */ , remaining ); + const int readSize = file.readBlock( data() + offset, blockSize ); + if( readSize == -1 ) + { + p.finish(); + mLoadingData = false; + return( Err_ReadFailed ); + } + for( uint i=0; i 0 ) + { + p.finish(); + return( Err_OperationAborted ); + } + } + } + mLoadingData = false; + } + + p.finish(); + + mDocumentModified = false; + setDocumentSize( file.size() ); + registerDiskModifyTime( file ); + setUrl( url ); + computeNumLines(); + mSelect.reset(); + mMark.reset(); + mUndoList.clear(); + mUndoIndex = 0; + + return( Err_Success ); +} + + +int CHexBuffer::insertFile( QFile &file, CProgress &p ) +{ + if( file.size() == 0 ) + { + p.finish(); + return( Err_Success ); + } + + QByteArray array( file.size() ); + if( array.isNull() == true ) + { + p.finish(); + return( Err_NoMemory ); + } + + uint offset = 0; + uint remaining = file.size(); + while( remaining > 0 ) + { + const uint blockSize = QMIN( 131072 /* == 1024 * 128 */ , remaining ); + const int readSize = file.readBlock( array.data() + offset, blockSize ); + if( readSize == -1 ) + { + p.finish(); + return( Err_ReadFailed ); + } + for( uint i=0; i 0 ) + { + p.finish(); + return( Err_OperationAborted ); + } + } + } + + p.finish(); + + int errCode = inputAtCursor( array, 0 ); + return( errCode ); +} + + +int CHexBuffer::newFile( const QString &url ) +{ + if( resize( 100 ) == 0 ) + { + return( Err_NoMemory ); + } + + mDocumentModified = false; + setDocumentSize( 0 ); + setUrl( url ); + computeNumLines(); + mSelect.reset(); + + return( Err_Success ); +} + + +void CHexBuffer::closeFile( void ) +{ + resize(0); + computeNumLines(); + + mUndoList.clear(); + mUndoIndex = 0; + + setDocumentSize(0); + mDocumentModified = false; + + QString emptyUrl; + setUrl( emptyUrl ); + + mSelect.reset(); + mMark.reset(); + + removeBookmark(-1); // Negative index - All bookmarks +} + + +void CHexBuffer::registerDiskModifyTime( const QFile &file ) +{ + QFileInfo fileInfo( file ); + mDiskModifyTime = fileInfo.lastModified(); +} + + + +void CHexBuffer::setFont( const SDisplayFontInfo &fontInfo ) +{ + mFontInfo = fontInfo; + QFontMetrics fm( mFontInfo.font ); + mFontHeight = fm.height(); + mFontAscent = fm.ascent(); + computeLineWidth(); + + for( int i=0; i < 256; i++ ) + { + mCharValid[i] = QChar(i).isPrint(); + } + + /* + QFontInfo info( mFontInfo.font ); + puts("CHexBuffer mCharValid broken"); + + KCharset charset( info.charSet() ); + for( int i=0; i < 256; i++ ) + { + mCharValid[i] = charset.printable(i); + } + */ +} + + +int CHexBuffer::setEncoding( CConversion::EMode mode, CProgress &p ) +{ + int errCode = mEncode.convert( *this, mode, p ); + if( errCode == Err_Success ) + { + // + // The cursor stores the byte it is "covering", so this information + // must be updated. + // + cursorCompute(); + } + + return( errCode ); +} + + + + +void CHexBuffer::computeLineWidth( void ) +{ + QFontMetrics fm( mFontInfo.font ); + mUnitWidth = fm.width( "M" ); + + if( mLayout.primaryMode == SDisplayLayout::textOnly ) + { + mSplitWidth = 0; + } + else if( mLayout.columnCharSpace == true ) + { + mSplitWidth = mUnitWidth; + } + else + { + mSplitWidth = mLayout.columnSpacing; + } + + setMaximumSize( mMaximumSize ); + + if( mLayout.primaryMode == SDisplayLayout::hexadecimal ) + { + mNumCell = 2; + mCursor.setCellWeight( 4 ); + if( mLayout.primaryUpperCase == true ) + { + printCell = &CHexBuffer::printHexadecimalBigCell; + inputCell = &CHexBuffer::inputHexadecimal; + } + else + { + printCell = &CHexBuffer::printHexadecimalSmallCell; + inputCell = &CHexBuffer::inputHexadecimal; + } + } + else if( mLayout.primaryMode == SDisplayLayout::decimal ) + { + mNumCell = 3; + printCell = &CHexBuffer::printDecimalCell; + inputCell = &CHexBuffer::inputDecimal; + mCursor.setCellWeight( 3 ); + } + else if( mLayout.primaryMode == SDisplayLayout::octal ) + { + mNumCell = 3; + printCell = &CHexBuffer::printOctalCell; + inputCell = &CHexBuffer::inputOctal; + mCursor.setCellWeight( 3 ); + } + else if( mLayout.primaryMode == SDisplayLayout::binary ) + { + mNumCell = 8; + printCell = &CHexBuffer::printBinaryCell; + inputCell = &CHexBuffer::inputBinary; + mCursor.setCellWeight( 1 ); + } + else if( mLayout.primaryMode == SDisplayLayout::textOnly ) + { + mNumCell = 1; + printCell = &CHexBuffer::printAsciiCell; + inputCell = &CHexBuffer::inputAscii; + mCursor.setCellWeight( 8 ); + } + else + { + mNumCell = 2; + mLayout.primaryMode = SDisplayLayout::hexadecimal; + mLayout.primaryUpperCase = false; + printCell = &CHexBuffer::printHexadecimalSmallCell; + inputCell = &CHexBuffer::inputHexadecimal; + mCursor.setCellWeight( 4 ); + } + + // + // 'mPrimaryWidth' is the number of pixels that are needed to display a + // line in the primary field. + // + mPrimaryWidth = mLayout.lineSize * mNumCell * mUnitWidth; + + if( mLayout.columnSpacing != 0 ) + { + int numSplit = mLayout.lineSize / mLayout.columnSize; + numSplit -= mLayout.lineSize % mLayout.columnSize == 0 ? 1 : 0; + mPrimaryWidth += numSplit * mSplitWidth; + } + + // + // 'mSecondaryWidth' is the number of pixels that are needed to display a + // line in the secondary field (there are no spaces). + // + if( mLayout.secondaryMode == SDisplayLayout::hide ) + { + mSecondaryWidth = 0; + } + else + { + mSecondaryWidth = mLayout.lineSize * mUnitWidth; + } + + // + // 'mLineWidth' is the total number of pixels required to display + // offset data, separators, primary and secondary data on a line. + // + mLineWidth = mPrimaryWidth + mSecondaryWidth + mOffsetSize * mUnitWidth; + + // + // The 'mFixedWidth' is the number of pixels of the width that stays the + // same regardless of how many characters that are displayed. + // This entity consists of the edge margins, the inner margins and the + // separators. + // + mFixedWidth = mOffsetSize * mUnitWidth; + + // + // The edge margin is always present in both ends. + // + mLineWidth += mLayout.edgeMarginWidth * 2; + mFixedWidth += mLayout.edgeMarginWidth * 2; + + // + // 'mTextStart1' is the number of pixels from the left edge where the + // primary field starts. + // + mTextStart1 = mLayout.edgeMarginWidth; + if( mLayout.offsetVisible == true ) + { + int width; + if( mLayout.leftSeparatorWidth > 0 ) + { + width = mLayout.separatorMarginWidth * 2 + mLayout.leftSeparatorWidth; + } + else + { + width = (mLayout.separatorMarginWidth * 3) / 2; + } + + mLineWidth += width; + mFixedWidth += width; + mTextStart1 += width + mOffsetSize * mUnitWidth; + } + + // + // 'mTextStart2' is the number of pixels from the left edge where the + // secondary fields start. + // + mTextStart2 = mTextStart1; + if( mLayout.secondaryMode != SDisplayLayout::hide ) + { + int width; + if( mLayout.rightSeparatorWidth > 0 ) + { + width = mLayout.separatorMarginWidth * 2 + mLayout.rightSeparatorWidth; + } + else + { + width = (mLayout.separatorMarginWidth * 3) / 2; + } + + mLineWidth += width; + mFixedWidth += width; + mTextStart2 += width + mPrimaryWidth; + } + + setEditMode( mEditMode ); + computeNumLines(); +} + + +void CHexBuffer::computeNumLines( void ) +{ + if( mLayout.lineSize == 0 ) + { + mNumLines = 1; + } + else + { + uint s = mFixedSizeMode == true ? mMaximumSize : documentSize() + 1; + mNumLines = s / mLayout.lineSize + (s % mLayout.lineSize ? 1 : 0); + } +} + + + +void CHexBuffer::drawSelection( QPainter &paint, QColor &color, uint start, + uint stop, int sx ) +{ + if( start >= stop ) { return; } + uint width = stop - start; + + uint addStart, addWidth; + addStart = (start / mLayout.columnSize) * mSplitWidth; + if( width == 0 ) + { + addWidth = 0; + } + else + { + uint g = mLayout.columnSize; + addWidth = (((start % g) + width - 1) / g) * mSplitWidth; + } + + int offset = mTextStart1 - sx; + paint.fillRect( offset + start * mNumCell * mUnitWidth + addStart, + 0, width * mNumCell * mUnitWidth + addWidth, + mFontHeight, color ); + + if( mLayout.secondaryMode != SDisplayLayout::hide ) + { + offset = mTextStart2 - sx; + paint.fillRect( offset + start * mUnitWidth, + 0, width * mUnitWidth, + mFontHeight, color ); + } +} + + + + + +void CHexBuffer::drawText( QPainter &paint, uint line, int sx, int x1, int x2 ) +{ + uint fileOffset = line * mLayout.lineSize; + if( documentPresent() == false || mLoadingData == true ) + { + paint.fillRect( x1, 0, x2-x1, lineHeight(), mColor.inactiveBg ); + return; + } + + bool outsideText; + if( size() == 0 || fileOffset > documentSize() || fileOffset >= mMaximumSize) + { + outsideText = true; + } + else + { + outsideText = false; + } + + if( (line+1) % 2 || outsideText == true ) + { + paint.fillRect( x1, 0, x2-x1, lineHeight(), mColor.textBg ); + } + else + { + paint.fillRect( x1, 0, x2-x1, lineHeight(), mColor.secondTextBg ); + } + if( mLayout.horzGridWidth > 0 && outsideText == false ) + { + paint.setPen( mColor.gridFg ); + paint.drawLine( x1, mFontHeight, x2, mFontHeight ); + } + + if( mSelect.inside( fileOffset, mLayout.lineSize ) == true ) + { + uint start = mSelect.start( fileOffset ); + uint stop = mSelect.stop( fileOffset, mLayout.lineSize ); + drawSelection( paint, mColor.selectBg, start, stop, sx ); + } + + // + // A marked area will be displayed "above" a selcted area (given + // the mark background color is different) + // + if( mMark.inside( fileOffset, mLayout.lineSize ) == true ) + { + uint start = mMark.start( fileOffset ); + uint stop = mMark.stop( fileOffset, mLayout.lineSize ); + drawSelection( paint, mColor.markBg, start, stop, sx ); + } + + uint dataSize; + unsigned char *fileData; + if( outsideText == true ) + { + if( size() == 0 ) + { + return; + } + dataSize = 0; + fileData = 0; + } + else + { + dataSize = documentSize() - fileOffset; + if( dataSize > mLayout.lineSize ) { dataSize = mLayout.lineSize; } + fileData = (unsigned char*)&(data()[ fileOffset ]); + } + + // + // Compute the offset area size. We postpose the actual drawing + // until we have drawn any bookmark indicators in the editor areas. + // because we may want to draw an indicator in the offset area as well. + // + int offset = mLayout.edgeMarginWidth - sx; + if( mLayout.offsetVisible == true ) + { + offset += mOffsetSize * mUnitWidth; + if( mLayout.leftSeparatorWidth > 0 ) + { + offset += mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth*2; + } + else + { + offset += (mLayout.separatorMarginWidth * 3) / 2; + } + } + + + #if 0 + int offset = mLayout.edgeMarginWidth - sx; + if( mLayout.offsetVisible == true ) + { + int s0 = mOffsetSize * mUnitWidth; + int s1 = s0 + mLayout.separatorMarginWidth + mLayout.edgeMarginWidth - sx; + if( x1 < s1 && x2 > 0 ) + { + if( outsideText == true ) + { + paint.fillRect( 0, 0, s1, lineHeight(), mColor.offsetBg ); + } + else + { + // + // I want to display the grid here so I cant use lineHeight() + // + paint.fillRect( 0, 0, s1, mFontHeight, mColor.offsetBg ); + } + } + + if( x1 < offset + s0 && x2 >= offset && fileData != 0 ) + { + paint.setPen( mColor.offsetFg ); + THIS_FPTR(printOffset)( mPrintBuf, fileOffset ); + // ## paint.drawText(offset,mFontAscent,&mPrintBuf[mOffsetIndex], + // mOffsetSize); + paint.drawText( offset, mFontAscent, + QString::fromLocal8Bit(&mPrintBuf[mOffsetIndex]), + mOffsetSize ); + } + offset += s0; + + if( mLayout.leftSeparatorWidth > 0 ) + { + offset += mLayout.separatorMarginWidth; + + int s2 = mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth; + if( x1 < offset + s2 && x2 >= offset ) + { + QPen pen( mColor.leftSeparatorFg, mLayout.leftSeparatorWidth ); + paint.setPen( pen ); + int center = offset + mLayout.leftSeparatorWidth/2; + paint.drawLine( center, 0, center, lineHeight() ); + } + offset += s2; + } + else + { + offset += (mLayout.separatorMarginWidth * 3) / 2; + } + } + #endif + + + // + // Draw the primary area + // + int localOffset = offset; + for( uint i = 0; i < dataSize; i++ ) + { + int s = mNumCell * mUnitWidth + + ((i+1) % mLayout.columnSize == 0) * mSplitWidth; + if( x1 < localOffset + s && x2 >= localOffset ) + { + int flag = THIS_FPTR(printCell)( mPrintBuf, fileData[i] ); + if( mSelect.inside( fileOffset+i ) ) + { + paint.setPen( mColor.selectFg ); + } + else if( mMark.inside( fileOffset+i ) ) + { + paint.setPen( mColor.markFg ); + } + else + { + paint.setPen( flag == 0 ? foregroundColor( i ) : mColor.nonPrintFg ); + } + + // ## paint.drawText( localOffset, mFontAscent, mPrintBuf, mNumCell ); + paint.drawText( localOffset, mFontAscent, + QString::fromLocal8Bit(mPrintBuf), mNumCell ); + } + localOffset += s; + + if( mLayout.vertGridWidth > 0 && i+1 < dataSize ) + { + if( (i+1) % mLayout.columnSize == 0 ) + { + paint.setPen( mColor.gridFg ); + int x = localOffset - (mSplitWidth+1) / 2; + paint.drawLine( x, 0, x, mFontHeight ); + } + } + } + + // + // Draw the secondary area + // + offset += mPrimaryWidth; + if( mLayout.secondaryMode != SDisplayLayout::hide ) + { + if( mLayout.rightSeparatorWidth > 0 ) + { + offset += mLayout.separatorMarginWidth; + int s = mLayout.separatorMarginWidth + mLayout.rightSeparatorWidth; + if( x1 < offset + s && x2 >= offset ) + { + QPen pen( mColor.rightSeparatorFg, mLayout.rightSeparatorWidth ); + paint.setPen( pen ); + int center = offset + mLayout.rightSeparatorWidth/2; + paint.drawLine( center, 0, center, lineHeight() ); + } + offset += s; + } + else + { + offset += (mLayout.separatorMarginWidth * 3) / 2; + } + + int s = mUnitWidth; + for( uint i = 0; i < dataSize; i++ ) + { + if( x1 < offset + s && x2 >= offset ) + { + int flag = printAsciiCell( mPrintBuf, fileData[i] ); + if( mSelect.inside( fileOffset+i ) ) + { + paint.setPen( mColor.selectFg ); + } + else if( mMark.inside( fileOffset+i ) ) + { + paint.setPen( mColor.markFg ); + } + else + { + paint.setPen( flag == 0 ? mColor.secondaryFg : mColor.nonPrintFg ); + } + + // ## paint.drawText( offset, mFontAscent, mPrintBuf, 1 ); + paint.drawText( offset, mFontAscent, + QString::fromLocal8Bit(mPrintBuf), 1 ); + } + offset += s; + } + } + + // + // Draw the bookmark identifiers on this line (if any). We use the + // bitmask to minimize the number of times we try to draw the bookmarks. + // + int bookmarkPosition = 0; + if( mBookmarkMap.testBit(fileOffset/200) || + mBookmarkMap.testBit((fileOffset+mLayout.lineSize-1)/200 ) ) + { + // Returns a bookmark postion state + bookmarkPosition = drawBookmarks( paint, line, sx ); + } + + // + // Draw the offset area. We have delayed the drawing until now because + // it is possible to draw a bookmark indicator in this area. + // + offset = mLayout.edgeMarginWidth - sx; + if( mLayout.offsetVisible == true ) + { + int s0 = mOffsetSize * mUnitWidth; + int s1 = s0 + mLayout.separatorMarginWidth + mLayout.edgeMarginWidth - sx; + if( x1 < s1 && x2 > 0 ) + { + QColor bg = mShowBookmarkInOffsetColumn && + (bookmarkPosition & BookmarkOnLine) ? + mColor.bookmarkBg : mColor.offsetBg; + if( outsideText == true ) + { + paint.fillRect( 0, 0, s1, lineHeight(), bg ); + } + else + { + // + // I want to display the grid here so I cant use lineHeight() + // + paint.fillRect( 0, 0, s1, mFontHeight, bg ); + } + } + + if( x1 < offset + s0 && x2 >= offset && fileData != 0 ) + { + paint.setPen( mShowBookmarkInOffsetColumn && + bookmarkPosition & BookmarkOnLine ? + mColor.bookmarkFg : mColor.offsetFg ); + THIS_FPTR(printOffset)( mPrintBuf, fileOffset ); + // ## paint.drawText(offset,mFontAscent,&mPrintBuf[mOffsetIndex], + // mOffsetSize); + paint.drawText( offset, mFontAscent, + QString::fromLocal8Bit(&mPrintBuf[mOffsetIndex]), + mOffsetSize ); + } + + offset += s0; + + if( mLayout.leftSeparatorWidth > 0 ) + { + offset += mLayout.separatorMarginWidth; + + int s2 = mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth; + if( x1 < offset + s2 && x2 >= offset ) + { + QPen pen( mColor.leftSeparatorFg, mLayout.leftSeparatorWidth ); + paint.setPen( pen ); + int center = offset + mLayout.leftSeparatorWidth/2; + paint.drawLine( center, 0, center, lineHeight() ); + } + } + } + + + // + // If the cursors are located on the line we have drawn we redraw + // them unless they have been disabled. + // + if( mDisableCursor == false ) + { + if( mCursor.curr.inside( fileOffset, fileOffset + mLayout.lineSize ) ) + { + drawCursor( paint, line, sx, bookmarkPosition & BookmarkOnCursor ); + } + } + +} + + + + +void CHexBuffer::drawText( QPainter &paint, uint line, int x1, int x2, int y, + bool useBlackWhite ) +{ + uint fileOffset = line * mLayout.lineSize; + + bool outsideText; + if( size() == 0 || fileOffset > documentSize() || fileOffset >= mMaximumSize) + { + outsideText = true; + } + else + { + outsideText = false; + } + + if( (line+1) % 2 || outsideText == true ) + { + paint.fillRect( x1, y, x2, lineHeight(), + useBlackWhite == true ? Qt::white : mColor.textBg ); + } + else + { + paint.fillRect( x1, y, x2, lineHeight(), + useBlackWhite == true ? Qt::white : mColor.secondTextBg ); + } + + if( mLayout.horzGridWidth > 0 && outsideText == false ) + { + QPen pen( useBlackWhite == true ? Qt::black : mColor.gridFg, + mLayout.horzGridWidth ); + paint.setPen( pen ); + paint.drawLine( x1, y+mFontHeight, x2+x1, y+mFontHeight ); + } + + uint dataSize; + unsigned char *fileData; + if( outsideText == true ) + { + if( size() == 0 ) + { + return; + } + dataSize = 0; + fileData = 0; + } + else + { + dataSize = documentSize() - fileOffset; + if( dataSize > mLayout.lineSize ) { dataSize = mLayout.lineSize; } + fileData = (unsigned char*)&(data()[ fileOffset ]); + } + + int offset = mLayout.edgeMarginWidth + x1; + + if( mLayout.offsetVisible == true ) + { + int s1 = mOffsetSize * mUnitWidth; + if( fileData != 0 ) + { + paint.setPen( useBlackWhite == true ? Qt::black : mColor.offsetFg ); + THIS_FPTR(printOffset)( mPrintBuf, fileOffset ); + // ## paint.drawText( offset, mFontAscent+y, &mPrintBuf[mOffsetIndex], + // mOffsetSize ); + paint.drawText( offset, mFontAscent+y, + QString::fromLocal8Bit(&mPrintBuf[mOffsetIndex]), + mOffsetSize ); + } + offset += s1; + + if( mLayout.leftSeparatorWidth > 0 ) + { + offset += mLayout.separatorMarginWidth; + + int s2 = mLayout.leftSeparatorWidth + mLayout.separatorMarginWidth; + QPen pen( useBlackWhite == true ? Qt::black : mColor.leftSeparatorFg, + mLayout.leftSeparatorWidth ); + paint.setPen( pen ); + int center = offset + mLayout.leftSeparatorWidth/2; + paint.drawLine( center, y, center, mFontHeight+y ); + offset += s2; + } + else + { + offset += (mLayout.separatorMarginWidth * 3) / 2; + } + } + + int localOffset = offset; + for( uint i = 0; i < dataSize; i++ ) + { + int s = mNumCell * mUnitWidth + + ((i+1) % mLayout.columnSize == 0) * mSplitWidth; + int flag = THIS_FPTR(printCell)( mPrintBuf, fileData[i] ); + if( useBlackWhite == true ) + { + paint.setPen( Qt::black ); + } + else + { + paint.setPen( flag == 0 ? foregroundColor( i ) : mColor.nonPrintFg ); + } + // ## paint.drawText( localOffset, mFontAscent+y, mPrintBuf, mNumCell ); + paint.drawText( localOffset, mFontAscent+y, + QString::fromLocal8Bit(mPrintBuf), mNumCell ); + localOffset += s; + + if( mLayout.vertGridWidth > 0 && i+1 < dataSize ) + { + if( (i+1) % mLayout.columnSize == 0 ) + { + QPen pen( useBlackWhite == true ? Qt::black : mColor.gridFg, + mLayout.vertGridWidth ); + paint.setPen( pen ); + int x = localOffset - (mSplitWidth+1) / 2; + paint.drawLine( x, y, x, y+mFontHeight ); + } + } + + } + + offset += mPrimaryWidth; + + if( mLayout.secondaryMode != SDisplayLayout::hide ) + { + if( mLayout.rightSeparatorWidth > 0 ) + { + offset += mLayout.separatorMarginWidth; + int s = mLayout.separatorMarginWidth + mLayout.rightSeparatorWidth; + QPen pen( useBlackWhite == true ? Qt::black : mColor.rightSeparatorFg, + mLayout.rightSeparatorWidth ); + paint.setPen( pen ); + int center = offset + mLayout.rightSeparatorWidth/2; + paint.drawLine( center, y, center, mFontHeight+y ); + offset += s; + } + else + { + offset += (mLayout.separatorMarginWidth * 3) / 2; + } + + + int s = mUnitWidth; + for( uint i = 0; i < dataSize; i++ ) + { + int flag = printAsciiCell( mPrintBuf, fileData[i] ); + if( useBlackWhite == true ) + { + paint.setPen( Qt::black ); + } + else + { + paint.setPen( flag == 0 ? mColor.secondaryFg : mColor.nonPrintFg ); + } + // ## paint.drawText( offset, mFontAscent+y, mPrintBuf, 1 ); + paint.drawText( offset, mFontAscent+y, + QString::fromLocal8Bit(mPrintBuf), 1 ); + offset += s; + } + } + +} + + +int CHexBuffer::headerHeight( QPainter &paint ) +{ + QFont font( paint.font() ); + paint.setFont( KGlobalSettings::generalFont() ); + const QFontMetrics &fm = paint.fontMetrics(); + + int height = fm.height(); + paint.setFont( font ); + return( height ); +} + +int CHexBuffer::headerMargin( QPainter &paint ) +{ + QFont font( paint.font() ); + paint.setFont( KGlobalSettings::generalFont() ); + const QFontMetrics &fm = paint.fontMetrics(); + + int margin = fm.height() / 2; + paint.setFont( font ); + return( margin ); +} + + +void CHexBuffer::drawHeader( QPainter &paint, int sx, int width, int y, + bool isFooter, const SPageHeader &header, + const SPagePosition &position ) +{ + QFont font( paint.font() ); + paint.setFont( KGlobalSettings::generalFont() ); + const QFontMetrics &fm = paint.fontMetrics(); + + paint.fillRect( sx, y, width, fm.height(), Qt::white ); + paint.setPen( Qt::black ); + if( header.line == SPageHeader::SingleLine ) + { + if( isFooter == false ) + { + paint.drawLine( sx, y+fm.height(), sx+width, y+fm.height() ); + } + else + { + paint.drawLine( sx, y, sx+width, y ); + } + } + else if( header.line == SPageHeader::Rectangle ) + { + paint.drawRect( sx, y, width, fm.height() ); + } + + int pos[3] = + { + QPainter::AlignLeft, QPainter::AlignHCenter, QPainter::AlignRight + }; + + QString msg; + for( int i=0; i<3; i++ ) + { + if( header.pos[i] == SPageHeader::DateTime ) + { + QDateTime datetime; + datetime.setTime_t( position.now ); + msg = KGlobal::locale()->formatDateTime(datetime); + } + else if( header.pos[i] == SPageHeader::PageNumber ) + { + msg = i18n("Page %1 of %2") + .arg(KGlobal::locale()->formatNumber(position.curPage, 0)) + .arg(KGlobal::locale()->formatNumber(position.maxPage, 0)); + } + else if( header.pos[i] == SPageHeader::FileName ) + { + msg = mUrl; + } + else + { + continue; + } + + if( 0 && pos[i] == QPainter::AlignRight ) + { + //const QFontMetrics &f = QFontMetrics( KGlobalSettings::generalFont() ); + //QRect r = paint.boundingRect(sx, y, width, fm.height(), pos[i], msg ); + //printf("R: %d, %d, %d, %d\n", r.x(), r.y(), r.width(), r.height() ); + + int x = sx + width - /*r.width();*/ fm.width(msg); + paint.drawText( x, y+fm.height(), msg ); + //printf("paint at %d\n", x ); + } + else + { + paint.drawText( sx, y, width, fm.height(), pos[i], msg ); + } + } + + // + // restore original font. + // + paint.setFont( font ); +} + + + + +int CHexBuffer::drawBookmarks( QPainter &paint, uint line, int startx ) +{ + if( documentPresent() == false || mLoadingData == true ) + { + return( 0 ); + } + + uint start = line*mLayout.lineSize; + uint stop = start+mLayout.lineSize; + QColor bg = mColor.bookmarkBg; + QColor fg = mColor.bookmarkFg; + + int bookmarkPosition = 0; + + for( SCursorOffset *c=mBookmarkList.first(); c!=0; c=mBookmarkList.next() ) + { + if( c->offset >= start && c->offset < stop ) + { + int x = c->offset - start; + int x1 = mTextStart1 + x * mUnitWidth * mNumCell; + x1 += (x / mLayout.columnSize) * mSplitWidth; + int x2 = mTextStart2 + x * mUnitWidth; + + bookmarkPosition |= BookmarkOnLine; + + if( mShowBookmarkInEditor == false ) + { + continue; + } + + uint offset = line*mLayout.lineSize+x; + if( offset == mCursor.curr.offset ) + { + bookmarkPosition |= BookmarkOnCursor; + } + + if( mSelect.inside( offset ) || mMark.inside( offset ) ) + { + paint.fillRect( x1-startx, 2, mUnitWidth*mNumCell, mFontHeight-4, bg ); + if( mLayout.secondaryMode != SDisplayLayout::hide ) + { + paint.fillRect( x2-startx, 2, mUnitWidth, mFontHeight-4, bg ); + } + } + else + { + paint.fillRect( x1-startx, 1, mUnitWidth*mNumCell, mFontHeight-2, bg ); + if( mLayout.secondaryMode != SDisplayLayout::hide ) + { + paint.fillRect( x2-startx, 1, mUnitWidth, mFontHeight-2, bg ); + } + } + + unsigned char c = (data()[ line*mLayout.lineSize+x]); + + int flag = THIS_FPTR(printCell)( mPrintBuf, c ); + paint.setPen( flag == 0 ? fg : mColor.nonPrintFg ); + // ## paint.drawText( x1-startx, mFontAscent, mPrintBuf, mNumCell ); + paint.drawText( x1-startx, mFontAscent, + QString::fromLocal8Bit(mPrintBuf), mNumCell ); + if( mLayout.secondaryMode != SDisplayLayout::hide ) + { + flag = printAsciiCell( mPrintBuf, c ); + paint.setPen( flag == 0 ? fg : mColor.nonPrintFg ); + // ## paint.drawText( x2-startx, mFontAscent, mPrintBuf, 1 ); + paint.drawText( x2-startx, mFontAscent, + QString::fromLocal8Bit(mPrintBuf), 1 ); + } + } + } + + return bookmarkPosition; +} + + + +void CHexBuffer::drawCursor( QPainter &paint, uint line, int startx, + bool onBookmark ) +{ + if( documentPresent() == false || mLoadingData == true ) + { + return; + } + + SCursorSpec &c = mCursor.curr; + + // + // Draw the cursor in primary edit area. + // + QColor bg, fg; + bool useFg; + if( mMark.inside( c.offset ) == true ) + { + bg = mColor.markBg; + fg = mSelect.inside( c.offset ) ? mColor.selectFg : mColor.markFg; + useFg = true; + } + else if( mSelect.inside( c.offset ) == true ) + { + bg = mColor.selectBg; + fg = mColor.selectFg; + useFg = true; + } + else + { + bg = (line+1) % 2 ? mColor.textBg : mColor.secondTextBg; + fg = foregroundColor( c.offset % mLayout.lineSize ); + useFg = false; // Can be true later. + } + + QColor cbg = mColor.cursorBg; + QColor cfg = mColor.cursorFg; + + // + // Fill in the general backround color + // + paint.fillRect( c.x1 - startx, 0, mUnitWidth, mFontHeight, bg ); + if( onBookmark == true ) + { + int w = mUnitWidth * (mNumCell-c.cell); // Rest of cell + if( useFg == true ) + { + paint.fillRect( c.x1-startx, 2, w, mFontHeight-4, mColor.bookmarkBg ); + } + else + { + paint.fillRect( c.x1-startx, 1, w, mFontHeight-2, mColor.bookmarkBg ); + } + } + + // + // Draw the cursor shape + // + bool transparent = false; + if( mActiveEditor == edit_primary ) + { + if( mShowCursor == true ) // Cursor blink on + { + if( c.mPrimaryShape == SCursorSpec::thin ) + { + paint.setPen( cbg ); + int center = c.x1 - startx - 1; + transparent = true; + + if( c.thickState == true ) + { + paint.drawLine( center, 0, center, mFontHeight - 1 ); + paint.drawLine( center+1, 0, center+1, mFontHeight - 1 ); + } + else + { + paint.drawLine( center, 0, center, mFontHeight - 1 ); + paint.drawLine( center-2, 0, center+2, 0 ); + paint.drawLine( center-2, mFontHeight-1, center+2, mFontHeight-1 ); + } + } + else // Solid block shape + { + paint.fillRect( c.x1 - startx, 0, mUnitWidth, mFontHeight, cbg ); + useFg = true; + fg = cfg; + } + } + } + else + { + transparent = true; + paint.setPen( cbg ); + paint.drawRect( c.x1 - startx, 0, mUnitWidth*mNumCell, mFontHeight ); + } + + // + // Draw the text on the cursor position and to the end of the cell. + // + if( c.offset < documentSize() ) + { + int flag = THIS_FPTR(printCell)( mPrintBuf, (unsigned char)c.data ); + if( onBookmark == true ) + { + // Inside bookmark. Draw text with bookmark foreground. + paint.setPen( mColor.bookmarkFg ); + // ## paint.drawText( c.x1-startx, mFontAscent, &mPrintBuf[c.cell], + // mNumCell-c.cell ); + paint.drawText( c.x1-startx, mFontAscent, + QString::fromLocal8Bit(&mPrintBuf[c.cell]), + mNumCell-c.cell ); + } + + if( transparent == false || onBookmark == false ) + { + paint.setPen( flag == 0 || useFg == true ? fg : mColor.nonPrintFg ); + // ## paint.drawText( c.x1 - startx, mFontAscent, &mPrintBuf[c.cell], 1); + paint.drawText( c.x1 - startx, mFontAscent, + QString::fromLocal8Bit(&mPrintBuf[c.cell]), 1 ); + } + } + + // + // Draw the cursor in secodary edit area. + // + if( mLayout.secondaryMode == SDisplayLayout::hide ) + { + return; + } + + + if( mMark.inside( c.offset ) == true ) + { + bg = mColor.markBg; + fg = mSelect.inside( c.offset ) ? mColor.selectFg : mColor.markFg; + useFg = true; + } + else if( mSelect.inside( c.offset ) == true ) + { + bg = mColor.selectBg; + fg = mColor.selectFg; + useFg = true; + } + else + { + bg = (line+1) % 2 ? mColor.textBg : mColor.secondTextBg; + fg = mColor.secondaryFg; + useFg = false; // Can be true later. + } + + + + // + // Fill in the general backround color + // + if( onBookmark == true ) + { + if( useFg == true ) + { + paint.fillRect( c.x2-startx, 2, mUnitWidth, mFontHeight-4, + mColor.bookmarkBg ); + } + else + { + paint.fillRect( c.x2-startx, 1, mUnitWidth, mFontHeight-2, + mColor.bookmarkBg ); + } + } + else + { + paint.fillRect( c.x2 - startx, 0, mUnitWidth, mFontHeight, bg ); + } + + // + // Draw the cursor shape + // + transparent = false; + if( mActiveEditor == edit_secondary ) + { + if( mShowCursor == true ) // Cursor blink on + { + if( c.mSecondaryShape == SCursorSpec::thin ) + { + paint.setPen( cbg ); + int center = c.x2 - startx - 1; + transparent = true; + + if( c.thickState == true ) + { + paint.drawLine( center, 0, center, mFontHeight - 1 ); + paint.drawLine( center+1, 0, center+1, mFontHeight - 1 ); + } + else + { + paint.drawLine( center, 0, center, mFontHeight - 1 ); + paint.drawLine( center-2, 0, center+2, 0 ); + paint.drawLine( center-2, mFontHeight-1, center+2, mFontHeight-1 ); + } + } + else + { + paint.fillRect( c.x2 - startx, 0, mUnitWidth, mFontHeight, cbg ); + useFg = true; + fg = cfg; + } + } + } + else + { + transparent = true; + paint.setPen( cbg ); + paint.drawRect( c.x2 - startx, 0, mUnitWidth, mFontHeight ); + } + + // + // Draw the text on the cursor position and to the end of the cell. + // + if( c.offset < documentSize() ) + { + int flag = printAsciiCell( mPrintBuf, (unsigned char)c.data ); + if( onBookmark == true ) + { + // Inside bookmark. Draw text with bookmark foreground. + paint.setPen( flag == 0 ? mColor.bookmarkFg : mColor.nonPrintFg ); + // ## paint.drawText( c.x2-startx, mFontAscent, mPrintBuf, 1 ); + paint.drawText( c.x2-startx, mFontAscent, + QString::fromLocal8Bit(mPrintBuf), 1 ); + } + if( transparent == false || onBookmark == false ) + { + paint.setPen( flag == 0 || useFg == true ? fg : mColor.nonPrintFg ); + // ## paint.drawText( c.x2 - startx, mFontAscent, mPrintBuf, 1 ); + paint.drawText( c.x2 - startx, mFontAscent, + QString::fromLocal8Bit(mPrintBuf), 1 ); + } + } + +} + + + + +void CHexBuffer::cursorReset( void ) +{ + mCursor.reset(); + cursorCompute(); +} + +void CHexBuffer::cursorCompute( void ) +{ + mCursor.prev = mCursor.curr; + + if( mCursor.next.offset >= documentSize() ) + { + if( documentSize() == 0 ) + { + mCursor.curr.offset = 0; + mCursor.curr.data = 0; + mCursor.curr.cell = 0; + mCursor.curr.maxCell = mNumCell; + + int x = mCursor.curr.offset % mLayout.lineSize; + mCursor.curr.x1 = mTextStart1; + mCursor.curr.x1 += (x * mNumCell + mCursor.curr.cell) * mUnitWidth; + mCursor.curr.x1 += (x / mLayout.columnSize) * mSplitWidth; + mCursor.curr.x2 = mTextStart2 + x * mUnitWidth; + mCursor.curr.y = (mCursor.curr.offset/mLayout.lineSize) * + (mFontHeight+mLayout.horzGridWidth); + return; + + } + if( mFixedSizeMode == true ) + { + uint max = mMaximumSize - 1; + uint off = mCursor.curr.offset % mLayout.lineSize; + uint end = max % mLayout.lineSize; + if( off > end ) + { + uint diff = off - end; + if( max + diff > mLayout.lineSize ) + { + mCursor.next.offset = max + diff - mLayout.lineSize; + } + else + { + mCursor.next.offset = 0; + } + } + else + { + uint diff = end - off; + mCursor.next.offset = diff > max ? max : max - diff; + } + } + else + { + mCursor.next.offset = documentSize(); + } + } + + mCursor.curr.offset = mCursor.next.offset; + mCursor.curr.data = data()[ mCursor.curr.offset ]; + mCursor.curr.cell = mCursor.next.cell; + mCursor.curr.maxCell = mNumCell; + + int x = mCursor.curr.offset % mLayout.lineSize; + + mCursor.curr.x1 = mTextStart1; + mCursor.curr.x1 += (x * mNumCell + mCursor.curr.cell) * mUnitWidth; + mCursor.curr.x1 += (x / mLayout.columnSize) * mSplitWidth; + mCursor.curr.x2 = mTextStart2 + x * mUnitWidth; + mCursor.curr.y = (mCursor.curr.offset/mLayout.lineSize) * + (mFontHeight + mLayout.horzGridWidth); +} + + +bool CHexBuffer::setCursorPosition( int x, int y, bool init, bool cellLevel ) +{ + if( documentPresent() == false ) + { + return( false ); + } + + uint line = y < 0 ? 0 : y / lineHeight(); + uint entry = 0; + int bit = 7; + + if( init == false ) + { + if( mCursor.area() == edit_primary ) + { + int start = mTextStart1; + if( x < start - (int)mLayout.separatorMarginWidth ) + { + return( false ); + } + else + { + int stop = mTextStart1 + mPrimaryWidth + mLayout.separatorMarginWidth; + int width = mNumCell * mUnitWidth; + int space = mSplitWidth; + + for( int position = start, i=0; position < stop; i++ ) + { + if( x <= position + width ) + { + if( cellLevel == true ) + { + while( bit > 0 ) + { + if( x <= position + mUnitWidth ) + { + break; + } + bit -= mCursor.cellWeight(); + position += mUnitWidth; + } + } + break; + } + position += width + (((i+1) % mLayout.columnSize) ? 0 : space); + entry += 1; + } + } + } + else + { + int start = mTextStart2; + if( x < start - (int)mLayout.separatorMarginWidth || + mLayout.secondaryMode == SDisplayLayout::hide ) + { + return( false ); + } + int stop = mTextStart2 + mLayout.lineSize * mUnitWidth; + int width = mUnitWidth * 1; + int space = 0; + + for( int position = start; position < stop; ) + { + if( x <= position + width ) + { + break; + } + position += width + space; + entry += 1; + } + } + } + else + { + int start = mTextStart1; + int stop = start + mPrimaryWidth + mLayout.separatorMarginWidth; + if( x >= start - (int)mLayout.separatorMarginWidth && x <= stop ) + { + int width = mUnitWidth * mNumCell; + int space = mSplitWidth; + + for( int position = start, i=0; position < stop; i++ ) + { + if( x <= position + width ) + { + if( cellLevel == true ) + { + while( bit > 0 ) + { + if( x <= position + mUnitWidth ) + { + break; + } + bit -= mCursor.cellWeight(); + position += mUnitWidth; + } + } + break; + } + position += width + (((i+1) % mLayout.columnSize) ? 0 : space); + entry += 1; + } + + mActiveEditor = edit_primary; + } + else if( mLayout.secondaryMode != SDisplayLayout::hide ) + { + start = mTextStart2; + stop = mTextStart2 + mLayout.lineSize * mUnitWidth + + mLayout.edgeMarginWidth; + if( x >= start - (int)mLayout.separatorMarginWidth && x <= stop ) + { + int width = mUnitWidth * 1; + int space = 0; + + for( int position = start; position < stop; ) + { + if( x <= position + width ) + { + break; + } + position += width + space; + entry += 1; + } + + mActiveEditor = edit_secondary; + } + } + else + { + return( false ); + } + } + + uint offset = line * mLayout.lineSize + entry; + if( offset > documentSize() ) + { + offset = documentSize(); + } + + mCursor.setOffset( offset ); + mCursor.setBit( bit < 0 ? 0 : bit ); + + cursorCompute(); + if( mActiveEditor != mCursor.area() ) + { + mCursor.setArea( mActiveEditor ); + setEditMode( mEditMode ); + } + + return( true ); +} + + + + +bool CHexBuffer::inputAtCursor( QChar c ) +{ + if( documentPresent() == false || mInputMode.noInput() == true ) + { + if( mInputMode.noInput() == true ) { inputSound(); } + return( false ); + } + + if( c.isPrint() == false ) + { + inputSound(); + return( false ); + } + + unsigned char dest; + bool insert; + if( mEditMode == EditReplace || mCursor.curr.cell > 0 ) + { + if( mCursor.curr.offset >= documentSize() ) + { + dest = 0; + insert = true; + } + else + { + dest = (unsigned char)data()[ mCursor.curr.offset ]; + insert = false; + } + } + else + { + dest = 0; + insert = true; + } + + if( insert == true && mInputMode.allowResize == false ) + { + inputSound(); + return( false ); + } + + if( mActiveEditor == edit_primary ) + { + // ## if( THIS_FPTR(inputCell)( &dest, c.latin1(), mCursor.curr.cell ) + //== false ) + if( THIS_FPTR(inputCell)( &dest, QString(c).local8Bit()[0], + mCursor.curr.cell ) == false ) + { + inputSound(); + return( false ); + } + } + else if( mActiveEditor == edit_secondary ) + { + // ## if( inputAscii( &dest, c.latin1(), mCursor.curr.cell ) == false ) + if( !inputAscii( &dest, QString(c).local8Bit()[0], mCursor.curr.cell ) ) + { + inputSound(); + return( false ); + } + } + else + { + return( false ); + } + + recordStart( mCursor ); + recordReplace( mCursor, insert == true ? 0 : 1, (char*)&dest, 1 ); + cursorRight( cursorPrimaryEdit() ); + recordEnd( mCursor ); + + computeNumLines(); + return( true ); +} + + + +int CHexBuffer::inputAtCursor( const QByteArray &buf, uint oldSize ) +{ + if( documentPresent() == false ) + { + return( Err_NoActiveDocument ); + } + if( buf.isNull() == true ) + { + return( Err_EmptyArgument ); + } + + if( mInputMode.noInput() == true ) + { + inputSound(); + return( Err_WriteProtect ); + } + + if( mInputMode.allowResize == false ) + { + inputSound(); + return( Err_NoResize ); + } + + recordStart( mCursor ); + recordReplace( mCursor, oldSize, (char*)&buf[0], buf.size() ); + cursorStep( buf.size(), true, false ); + recordEnd( mCursor ); + + computeNumLines(); + return( Err_Success ); +} + + +bool CHexBuffer::removeAtCursor( bool beforeCursor ) +{ + if( documentPresent() == false ) + { + return( false ); + } + + if( mInputMode.noInput() == true || mInputMode.allowResize == false ) + { + inputSound(); + return( false ); + } + + + if( mSelect.valid() == true ) + { + cutSelection(); + return( true ); + } + + + if( beforeCursor == true ) + { + if( mCursor.curr.offset == 0 ) + { + return( false ); + } + + recordStart( mCursor ); + cursorLeft( false ); + recordReplace( mCursor, 1, 0, 0 ); + recordEnd( mCursor ); + + computeNumLines(); + return( true ); + } + else + { + if( mCursor.curr.offset + 1 > documentSize() ) + { + return( false ); + } + + recordStart( mCursor ); + recordReplace( mCursor, 1, 0, 0 ); + recordEnd( mCursor ); + + computeNumLines(); + return( true ); + } +} + + + +int CHexBuffer::locateRange(const SExportRange &range, uint &start, uint &stop) +{ + if( range.mode == SExportRange::All ) + { + start = 0; + stop = documentSize(); + } + else if( range.mode == SExportRange::Selection ) + { + if( mSelect.valid() == false ) + { + return( Err_NoSelection ); + } + start = mSelect.curr.start; + stop = mSelect.curr.stop; + } + else if( range.mode == SExportRange::Range ) + { + start = range.start; + stop = range.stop; + } + else + { + return( Err_IllegalMode ); + } + + if( start >= stop ) + { + return( Err_IllegalRange ); + } + + return( Err_Success ); +} + + +int CHexBuffer::exportText( const SExportText &ex, CProgress &p ) +{ + uint start, stop; + int errCode = locateRange( ex.range, start, stop ); + if( errCode != Err_Success ) + { + p.finish(); + return( errCode ); + } + + QFile file( ex.destFile ); + if( file.open( IO_WriteOnly ) == false ) + { + p.finish(); + return( Err_OpenWriteFailed ); + } + + uint startLine = calculateLine( start ); + if( startLine >= (uint)numLines() ) + { + startLine = numLines() == 0 ? 0 : numLines() - 1; + } + + uint stopLine = calculateLine( stop ); + if( stopLine >= (uint)numLines() ) + { + stopLine = numLines() == 0 ? 0 : numLines() - 1; + } + + uint totalSize = stopLine - startLine + 1; + uint remaining = stopLine - startLine + 1; + uint bytePerLine = mOffsetSize + 1 + (mNumCell + 2)*mLayout.lineSize + 1; + uint linePerStep = 20; + + QByteArray array( bytePerLine * linePerStep + 1 ); // Line is 0 terminated + if( array.isEmpty() == true ) + { + p.finish(); + return( Err_NoMemory ); + } + + while( remaining > 0 ) + { + uint blockSize = remaining > linePerStep ? linePerStep : remaining; + uint printSize = 0; + + for( uint i = 0; i < blockSize; i++, startLine++ ) + { + printSize += printLine( &array[printSize], startLine ); + } + + int writeSize = file.writeBlock( &array[0], printSize ); + if( writeSize == -1 ) + { + p.finish(); + return( Err_WriteFailed ); + } + + remaining -= blockSize; + if( p.expired() == true ) + { + int errCode = p.step( (float)(totalSize-remaining)/(float)totalSize ); + if( errCode == Err_Stop && remaining > 0 ) + { + p.finish(); + return( Err_OperationAborted ); + } + } + } + + p.finish(); + return( Err_Success ); +} + + + +int CHexBuffer::exportHtml( const SExportHtml &ex, CProgress &p ) +{ + uint start, stop; + int errCode = locateRange( ex.range, start, stop ); + if( errCode != Err_Success ) + { + p.finish(); + return( errCode ); + } + + uint startLine = calculateLine( start ); + if( startLine >= (uint)numLines() ) + { + startLine = numLines() == 0 ? 0 : numLines() - 1; + } + + uint stopLine = calculateLine( stop ); + if( stopLine >= (uint)numLines() ) + { + stopLine = numLines() == 0 ? 0 : numLines() - 1; + } + + uint totalSize = stopLine - startLine + 1; + uint remaining = stopLine - startLine + 1; + + if( ex.linePerPage == 0 ) + { + p.finish(); + return( Err_IllegalArgument ); + } + + uint linePerPage = ex.linePerPage; + uint numFiles = remaining/linePerPage + (remaining%linePerPage ? 1 : 0); + uint fileCount = 0; + + QStringList fileNames, offsets; + QString name, offset; + for( uint i=0; i < numFiles; i++ ) + { + name.sprintf( "%08d.html", i+1 ); + fileNames.append( QString("%1/%2%3").arg(ex.package).arg(ex.prefix). + arg(name)); + } + name.sprintf( "%08d.html", 0 ); + QString tocName =QString("%1/%2%3").arg(ex.package).arg(ex.prefix).arg(name); + + QString linkName; + if( ex.symLink == true ) + { + linkName = QString("%1/%2").arg(ex.package).arg("index.html"); + } + + while( remaining > 0 ) + { + THIS_FPTR(printOffset)( mPrintBuf, startLine*mLayout.lineSize ); + mPrintBuf[mOffsetSize]=0; + offset.sprintf("[%s]", mPrintBuf ); + + uint pageSize = remaining > linePerPage ? linePerPage : remaining; + printHtmlDataPage( tocName, fileNames, fileCount, ex, startLine, pageSize); + + remaining -= pageSize; + startLine += pageSize; + fileCount += 1; + + THIS_FPTR(printOffset)( mPrintBuf, (startLine-1)*mLayout.lineSize ); + mPrintBuf[mOffsetSize]=0; + offset += QString(" %1 [%2]").arg(i18n("to")).arg(mPrintBuf); + offsets.append(offset); + + if( p.expired() == true ) + { + int errCode = p.step( (float)(totalSize-remaining)/(float)totalSize ); + if( errCode == Err_Stop && remaining > 0 ) + { + printHtmlTocPage( tocName, linkName, fileNames, offsets, fileCount ); + p.finish(); + return( Err_OperationAborted ); + } + } + } + + printHtmlTocPage( tocName, linkName, fileNames, offsets, fileCount ); + + p.finish(); + return( Err_Success ); +} + + +int CHexBuffer::exportCArray( const SExportCArray &ex, CProgress &p ) +{ + uint start, stop; + int errCode = locateRange( ex.range, start, stop ); + if( errCode != Err_Success ) + { + p.finish(); + return( errCode ); + } + + QFile file( ex.destFile ); + if( file.open( IO_WriteOnly ) == false ) + { + p.finish(); + return( Err_OpenWriteFailed ); + } + + uint startLine = calculateLine( start ); + if( startLine >= (uint)numLines() ) + { + startLine = numLines() == 0 ? 0 : numLines() - 1; + } + + uint stopLine = calculateLine( stop ); + if( stopLine >= (uint)numLines() ) + { + stopLine = numLines() == 0 ? 0 : numLines() - 1; + } + + uint elementSize = ex.elementSize(); + uint elementOnThisLine = 0; + + QTextStream dest( &file ); + + dest << ex.variableName(stop-start).latin1() << "={" << endl; + for( unsigned int i=start; i= ex.elementPerLine ) + { + dest << endl; + elementOnThisLine = 0; + } + + if( p.expired() == true ) + { + int errCode = p.step( (float)(i-start)/(float)(stop-start) ); + if( errCode == Err_Stop && (i+elementSize) < stop) + { + p.finish(); + return( Err_OperationAborted ); + } + } + } + dest << "};" << endl; + + p.finish(); + return( Err_Success ); +} + + + + + + + +int CHexBuffer::copySelectedText( QByteArray &array, int columnSegment ) +{ + SExportRange range; + range.mode = SExportRange::Selection; + return( copyText( array, range, columnSegment ) ); +} + + +int CHexBuffer::copyAllText( QByteArray &array ) +{ + SExportRange range; + range.mode = SExportRange::All; + return( copyText( array, range, VisibleColumn ) ); +} + + +int CHexBuffer::copyText( QByteArray &array, const SExportRange &range, + int columnSegment ) +{ + uint start, stop; + int errCode = locateRange( range, start, stop ); + if( errCode != Err_Success ) + { + return( errCode ); + } + + uint startLine = calculateLine( start ); + uint stopLine = calculateLine( stop ); + if( startLine >= (uint)numLines() ) + { + startLine = numLines() == 0 ? 0 : numLines() - 1; + } + if( stopLine >= (uint)numLines() ) + { + stopLine = numLines() == 0 ? 0 : numLines() - 1; + } + + uint bytePerLine = mOffsetSize + 1 + (mNumCell + 2)*mLayout.lineSize + 1; + uint size = (stopLine - startLine + 1)*bytePerLine; + if( array.resize( size+1 ) == false ) + { + return( Err_NoMemory ); + } + + if( columnSegment == VisibleColumn ) + { + columnSegment = PrimaryColumn; // Always visible + if( mLayout.offsetVisible == true ) + { + columnSegment |= OffsetColumn; + } + if( mLayout.secondaryMode != SDisplayLayout::hide ) + { + columnSegment |= SecondaryColumn; + } + } + + uint offset = 0; + for( uint i = startLine; i <= stopLine; i++ ) + { + offset += printLine( &array[offset], i, columnSegment ); + } + array[size] = 0; + + return( Err_Success ); +} + + +int CHexBuffer::copySelectedData( QByteArray &array ) +{ + uint start = mSelect.start(); + uint stop = mSelect.stop(); + + if( mSelect.valid() == false || start >= stop ) + { + return( Err_IllegalRange ); + } + + uint size = stop - start; + if( array.resize( size ) == false ) + { + return( Err_NoMemory ); + } + + //unsigned char *src = (unsigned char*)data(); + //char *dst = (char*)array.data(); + + memcpy( &array[0], &data()[start], size ); + return( Err_Success ); +} + + +uint CHexBuffer::numPage( CHexPrinter &printer ) +{ + QPainter paint( &printer ); + paint.setFont( font() ); + + SPageMargin margin = printer.pageMargin(); + SPageSize size = printer.pageUsableSize(); + int headHeight, footHeight, headMargin, footMargin, freeHeight; + + headHeight = footHeight = headMargin = footMargin = 0; + if( printer.pageHeader().enable == true ) + { + headHeight = headerHeight( paint ); + headMargin = headerMargin( paint ); + } + if( printer.pageFooter().enable == true ) + { + footHeight = headerHeight( paint ); + footMargin = headerMargin( paint ); + } + freeHeight = size.height - headHeight - footHeight - headMargin - footMargin; + + float scale = 1.0; + if( (uint)mLineWidth > size.width ) + { + scale = (float)size.width / (float)mLineWidth; + } + uint linePerPage = (uint) ((float)freeHeight/((float)lineHeight()*scale)); + + uint remaining = numLines(); + + return( remaining / linePerPage + (remaining % linePerPage ? 1 : 0) ); +} + + + +int CHexBuffer::print( CHexPrinter &printer, CProgress &p ) +{ + printer.setDocName( mUrl ); + + QPainter paint( &printer ); + paint.setFont( font() ); + + SPageMargin margin = printer.pageMargin(); + SPageSize size = printer.pageUsableSize(); + paint.setClipRect( margin.left, margin.top, size.width, size.height ); + + //printf("%d,%d,%d,%d\n", margin.left, margin.top, size.width, size.height ); + + int headHeight, footHeight, headMargin, footMargin, freeHeight; + + headHeight = footHeight = headMargin = footMargin = 0; + if( printer.pageHeader().enable == true ) + { + headHeight = headerHeight( paint ); + headMargin = headerMargin( paint ); + } + if( printer.pageFooter().enable == true ) + { + footHeight = headerHeight( paint ); + footMargin = headerMargin( paint ); + } + freeHeight = size.height - headHeight - footHeight - headMargin - footMargin; + + float scale = 1.0; + if( (uint)mLineWidth > size.width ) + { + scale = (float)size.width / (float)mLineWidth; + paint.scale( scale, scale ); + } + + uint linePerPage = (uint) ((float)freeHeight/((float)lineHeight()*scale)); + uint sx = (uint) ((float)margin.left/scale); + uint sy = (uint) ((float)(margin.top+headHeight+headMargin)/scale); + + uint remaining = numLines(); + uint line = 0; + + #ifdef PRINTER_TEST + remaining = remaining > linePerPage * 10 ? linePerPage * 10 : remaining; + #endif + + + SPagePosition pageData( time(0), remaining, linePerPage ); + while( remaining > 0 ) + { + uint lineInPage = remaining > linePerPage ? linePerPage : remaining; + uint y = sy; + + // + // Draw header and footer. Reset scaling during that operation. + // + paint.scale( 1.0/scale, 1.0/scale ); + if( printer.pageHeader().enable == true ) + { + drawHeader( paint, margin.left, size.width, margin.top, false, + printer.pageHeader(), pageData ); + } + if( printer.pageFooter().enable == true ) + { + drawHeader( paint, margin.left, size.width, + margin.top+size.height-footHeight, true, + printer.pageFooter(), pageData ); + } + paint.scale( scale, scale ); + + // + // Draw actual data + // + for( uint i=0; i < lineInPage; i++, line++ ) + { + drawText( paint, line, sx, mLineWidth, y, false/*printer.printBlackWhite()*/ ); + y += lineHeight();// - mLayout.horzGridWidth; // FIXME not really nice :) + + if( p.expired() == true ) + { + int errCode = p.step( pageData.current(), pageData.max() ); + if( errCode == Err_Stop ) + { + p.finish(); + return( Err_Success ); // Success here, even if we cancel + } + } + } + + if( p.expired() == true ) + { + int errCode = p.step( pageData.current(), pageData.max() ); + if( errCode == Err_Stop ) + { + p.finish(); + return( Err_Success );// Success here, even if we cancel + } + } + + remaining -= lineInPage; + if( remaining > 0 ) + { + printer.newPage(); + } + + pageData.step(); + } + + p.finish(); + return( Err_Success ); +} + + + + + +uint CHexBuffer::printLine( char *dst, uint line ) +{ + uint offset = line * mLayout.lineSize; + unsigned char *src; + char *start = dst; + + uint dataSize; + if( offset >= documentSize() ) + { + src = 0; + dataSize = 0; + } + else + { + src = (unsigned char*)&data()[ offset ]; + dataSize = documentSize() - offset; + } + + if( mLayout.offsetVisible == true ) + { + THIS_FPTR(printOffset)( dst, offset ); dst += mOffsetSize; + sprintf( dst, " " ); dst += 1; + } + for( uint i=0; i < mLayout.lineSize; i++ ) + { + if( i= documentSize() ) + { + src = 0; + dataSize = 0; + } + else + { + src = (unsigned char*)&data()[ offset ]; + dataSize = documentSize() - offset; + } + + if( columnSegment & OffsetColumn ) + { + THIS_FPTR(printOffset)( dst, offset ); dst += mOffsetSize; + sprintf( dst, " " ); dst += 1; + } + + if( columnSegment & PrimaryColumn ) + { + for( uint i=0; i < mLayout.lineSize; i++ ) + { + if( imStartOffset, group->mStartBit ); + + return( true ); +} + + +bool CHexBuffer::redo( void ) +{ + if( documentPresent() == false || mUndoIndex >= mUndoList.count() || + mInputMode.noInput() == true ) + { + if( mInputMode.noInput() == true ) { inputSound(); } + return( false ); + } + + CHexActionGroup *group = mUndoList.at( mUndoIndex ); + if( group == 0 ) + { + return( false ); + } + + mUndoIndex += 1; + doActionGroup( group ); + + cursorGoto( group->mStopOffset, group->mStopBit ); + + return( true ); +} + + +int CHexBuffer::addBookmark( int position ) +{ + if( documentPresent() == false ) + { + return( Err_NoData ); + } + + if( mBookmarkList.count() >= 9 && position == -1 ) + { + return( Err_ListFull ); + } + + SCursorOffset *co = new SCursorOffset; + if( co == 0 ) + { + fatalSound(); + return( Err_NoMemory ); + } + + co->offset = mCursor.curr.offset; + co->bit = mCursor.bit(); + + if( position == -1 || position > (int)mBookmarkList.count() ) + { + mBookmarkList.append( co ); + } + else + { + mBookmarkList.remove( (uint)position ); + mBookmarkList.insert( (uint)position, co ); + } + + updateBookmarkMap(false); + return( Err_Success ); +} + + +bool CHexBuffer::removeBookmark( int position ) +{ + if( position < 0 ) + { + if( mBookmarkList.count() == 0 ) + { + return( false ); + } + mBookmarkList.clear(); + } + else + { + if( (uint)position >= mBookmarkList.count() ) + { + return( false ); + } + mBookmarkList.remove( position ); + } + + updateBookmarkMap(false); + return( true ); +} + + +void CHexBuffer::updateBookmarkMap( bool resize ) +{ + if( resize == true ) + { + mBookmarkMap.resize( documentSize()/200 + 3 ); + } + mBookmarkMap.fill(0); + + int bookmarkMapSize = mBookmarkMap.size(); + for( SCursorOffset *c=mBookmarkList.first(); c!=0; c=mBookmarkList.next() ) + { + int bookmarkOffset = c->offset / 200; + if( bookmarkOffset < bookmarkMapSize ) + { + // + // Espen 2000-05-16: + // I do this test to avoid some Qt warnings when I have closed + // or reduced the size of the documnet while the (now invalid) + // bookmarks still exist. + // + mBookmarkMap.setBit(bookmarkOffset); + } + } +} + + +int CHexBuffer::findFirst( SSearchControl &sc ) +{ + mMark.reset(); + int errCode = scanData( sc, true ); + return( errCode ); +} + +int CHexBuffer::findNext( SSearchControl &sc ) +{ + sc.fromCursor = true; + int errCode = scanData( sc, false ); + return( errCode ); +} + +int CHexBuffer::findWrap( SSearchControl &sc ) +{ + if( sc.wrapValid == false ) + { + return( Err_NoMatch ); + } + sc.wrapValid = false; + + sc.fromCursor = false; + sc.wrapActive = true; + int errCode = scanData( sc, false ); + sc.fromCursor = true; + return( errCode ); +} + + + + +int CHexBuffer::replaceAll( SSearchControl &sc, bool init ) +{ + if( init == true ) + { + initScanData( sc ); + } + + if( sc.key.isEmpty() == true ) + { + return( Err_EmptyArgument ); + } + + if( documentSize() == 0 ) + { + return( Err_EmptyDocument ); + } + + uint head, tail; + if( sc.inSelection == true ) + { + if( mSelect.valid() == false ) + { + return( Err_NoSelection ); + } + + head = mSelect.start(); + tail = mSelect.stop(); + } + else + { + head = 0; + tail = documentSize(); + } + + uint start, stop; + if( sc.fromCursor == false ) + { + if( sc.wrapActive == true ) + { + start = sc.forward == true ? head : sc.wrapMark; + stop = sc.forward == true ? sc.wrapMark+sc.key.size() : tail; + } + else + { + start = head; + stop = tail; + } + } + else if( sc.forward == true ) + { + start = cursorOffset() < head ? head : cursorOffset(); + stop = sc.wrapActive == true ? sc.wrapMark+sc.key.size() : tail; + } + else + { + start = sc.wrapActive == true ? sc.wrapMark : head; + stop = cursorOffset() > tail ? tail : cursorOffset(); + } + + if( sc.forward == true && start + sc.key.size() > stop ) + { + // + // When searching backwards "stop" is the last offset from where + // we do a memcmp() upward in memory. An overflow for that + // situation is taken care of below. + // + return( Err_NoMatch ); + } + + if( stop + sc.key.size() > tail ) + { + uint diff = stop + sc.key.size() - tail; + stop = stop > diff ? stop - diff : 0; + } + + if( mInputMode.noInput() == true ) + { + inputSound(); + return( Err_WriteProtect ); + } + + recordStart( mCursor ); + uint numReplaced = 0; + + if( sc.forward == true ) + { + for( uint i = start; i <= stop ; ) + { + if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) != 0 ) + { + i++; + } + else + { + cursorGoto( i, 7 ); + recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() ); + numReplaced += 1; + + if( sc.inSelection == true ) + { + if( sc.key.size() > sc.val.size() ) + { + mSelect.shrink( sc.key.size() - sc.val.size() ); + } + else + { + mSelect.expand( sc.val.size() - sc.key.size() ); + } + } + + if( sc.key.size() > sc.val.size() ) + { + uint diff = sc.key.size() - sc.val.size(); + stop -= QMIN( stop, diff ); + } + else if( sc.key.size() < sc.val.size() ) + { + stop += sc.val.size() - sc.key.size(); + } + + i += sc.val.size(); + cursorStep( sc.val.size(), true, false ); + } + } + } + else + { + for( uint i = stop; i >= start; ) + { + if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) != 0 ) + { + if( i == 0 ) { break; } + i--; + } + else + { + cursorGoto( i, 7 ); + recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() ); + numReplaced += 1; + + if( sc.inSelection == true ) + { + if( sc.key.size() > sc.val.size() ) + { + mSelect.shrink( sc.key.size() - sc.val.size() ); + } + else + { + mSelect.expand( sc.val.size() - sc.key.size() ); + } + } + + i -= QMIN( i, sc.key.size() ); + if( i == 0 ) { break; } + } + } + } + + recordEnd( mCursor ); + computeNumLines(); + + if( numReplaced == 0 ) + { + return( Err_NoMatch ); + } + + sc.numReplace += numReplaced; + sc.match = true; + mMark.reset(); + + return( Err_Success ); +} + + +int CHexBuffer::replaceMarked( SSearchControl &sc ) +{ + if( documentSize() == 0 ) + { + return( Err_EmptyDocument ); + } + + if( mMark.valid() == false ) + { + return( Err_NoMark ); + } + + bool inSelection; + if( mSelect.valid() == true ) + { + if( mMark.start() >= mSelect.start() && mMark.stop() <= mSelect.stop() ) + { + inSelection = true; + } + else + { + inSelection = false; + } + } + else + { + inSelection = false; + } + + if( mInputMode.noInput() == true ) + { + inputSound(); + return( Err_WriteProtect ); + } + + recordStart( mCursor ); + cursorGoto( mMark.start(), 7 ); + recordReplace( mCursor, mMark.size(), sc.val.data(), sc.val.size() ); + sc.numReplace += 1; + + if( inSelection == true ) + { + if( mMark.size() > sc.val.size() ) + { + mSelect.shrink( mMark.size() - sc.val.size() ); + } + else + { + sc.wrapMark += sc.val.size() - mMark.size(); + mSelect.expand( sc.val.size() - mMark.size() ); + } + } + + + if( sc.wrapActive == false ) + { + if( sc.forward == false ) + { + sc.wrapMark += mMark.size() > sc.val.size() ? + mMark.size() - sc.val.size() : sc.val.size() - mMark.size(); + } + } + + + recordEnd( mCursor ); + computeNumLines(); + + if( sc.forward == true ) + { + // + // We must step over the area we have just altered. This is + // vital if the search key contains a pattern that exists in + // the replace data buffer. + // + cursorStep( sc.val.size(), true, false ); + } + mMark.reset(); + return( Err_Success ); +} + + +#if 0 + +int CHexBuffer::replaceAll( SSearchControl &sc, bool init ) +{ + if( init == true ) + { + initScanData( sc ); + } + + if( sc.key.isEmpty() == true ) + { + return( Err_EmptyArgument ); + } + + if( documentSize() == 0 ) + { + return( Err_EmptyDocument ); + } + + uint head, tail; + if( sc.inSelection == true ) + { + if( mSelect.valid() == false ) + { + return( Err_NoSelection ); + } + + head = mSelect.start(); + tail = mSelect.stop(); + } + else + { + head = 0; + tail = documentSize(); + } + + uint start, stop; + if( sc.fromCursor == false ) + { + if( sc.wrapActive == true ) + { + start = sc.forward == true ? head : sc.wrapMark; + stop = sc.forward == true ? sc.wrapMark : tail; + } + else + { + start = head; + stop = tail; + } + } + else if( sc.forward == true ) + { + start = cursorOffset() < head ? head : cursorOffset(); + stop = sc.wrapActive == true ? sc.wrapMark : tail; + } + else + { + start = sc.wrapActive == true ? sc.wrapMark : head; + stop = cursorOffset() > tail ? tail : cursorOffset(); + } + + + if( start + sc.key.size() > stop ) + { + return( Err_NoMatch ); + } + + if( stop + sc.key.size() > tail ) + { + uint diff = stop + sc.key.size() - tail; + stop = stop > diff ? stop - diff : 0; + } + + if( mInputMode.noInput() == true ) + { + inputSound(); + return( Err_WriteProtect ); + } + + recordStart( mCursor ); + uint numReplaced = 0; + + if( sc.forward == true ) + { + for( uint i = start; i <= stop; i++ ) + { + if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) == 0 ) + { + cursorGoto( i, 7 ); + recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() ); + numReplaced += 1; + + if( sc.inSelection == true ) + { + if( sc.key.size() > sc.val.size() ) + { + mSelect.shrink( sc.key.size() - sc.val.size() ); + } + else + { + mSelect.expand( sc.val.size() - sc.key.size() ); + } + } + + if( sc.key.size() > sc.key.size() ) + { + uint diff = sc.key.size() - sc.val.size(); + i += diff - 1; + } + else if( sc.key.size() < sc.val.size() ) + { + uint diff = sc.val.size() - sc.key.size(); + stop += diff; + } + else + { + i += sc.val.size() - 1; + } + cursorStep( sc.val.size(), true, false ); + } + } + } + else + { + for( uint i = stop; i >= start; i-- ) + { + if( memcmp( &data()[i], sc.key.data(), sc.key.size() ) == 0 ) + { + cursorGoto( i, 7 ); + recordReplace( mCursor, sc.key.size(), sc.val.data(), sc.val.size() ); + numReplaced += 1; + + if( sc.inSelection == true ) + { + if( sc.key.size() > sc.val.size() ) + { + mSelect.shrink( sc.key.size() - sc.val.size() ); + } + else + { + mSelect.expand( sc.val.size() - sc.key.size() ); + } + } + + } + if( i == 0 ) { break; } + } + } + + recordEnd( mCursor ); + computeNumLines(); + + if( numReplaced == 0 ) + { + return( Err_NoMatch ); + } + + sc.numReplace += numReplaced; + sc.match = true; + mMark.reset(); + + return( Err_Success ); +} + + +int CHexBuffer::replaceMarked( SSearchControl &sc ) +{ + if( documentSize() == 0 ) + { + return( Err_EmptyDocument ); + } + + if( mMark.valid() == false ) + { + return( Err_NoMark ); + } + + bool inSelection; + if( mSelect.valid() == false ) + { + if( mMark.start() >= mSelect.start() && mMark.stop() <= mSelect.stop() ) + { + inSelection = true; + } + else + { + inSelection = false; + } + } + else + { + inSelection = false; + } + + if( mInputMode.noInput() == true ) + { + inputSound(); + return( Err_WriteProtect ); + } + + recordStart( mCursor ); + cursorGoto( mMark.start(), 7 ); + recordReplace( mCursor, mMark.size(), sc.val.data(), sc.val.size() ); + sc.numReplace += 1; + + if( inSelection == true ) + { + if( mMark.size() > sc.val.size() ) + { + mSelect.shrink( mMark.size() - sc.val.size() ); + } + else + { + mSelect.expand( sc.val.size() - mMark.size() ); + } + } + + recordEnd( mCursor ); + computeNumLines(); + mMark.reset(); + + return( Err_Success ); +} + +#endif + + +int CHexBuffer::initScanData( SSearchControl &sc ) +{ + sc.wrapValid = false; + sc.wrapActive = false; + sc.wrapMark = 0; + sc.match = false; + sc.numReplace = 0; + + uint head, tail; + if( sc.inSelection == true ) + { + if( mSelect.valid() == false ) + { + return( Err_NoSelection ); + } + + head = mSelect.start(); + tail = mSelect.stop(); + } + else + { + head = 0; + tail = documentSize(); + } + + if( sc.fromCursor == false ) + { + sc.wrapValid = false; + sc.wrapActive = false; + sc.wrapMark = 0; + } + else if( sc.forward == true ) + { + if( cursorOffset() > tail ) + { + sc.wrapValid = true; + sc.wrapActive = false; + sc.wrapMark = tail; + } + else if( cursorOffset() <= head ) + { + sc.wrapValid = false; + sc.wrapActive = false; + sc.wrapMark = 0; + } + else + { + sc.wrapValid = true; + sc.wrapActive = false; + sc.wrapMark = cursorOffset(); + } + } + else + { + if( cursorOffset() >= tail ) + { + sc.wrapValid = false; + sc.wrapActive = false; + sc.wrapMark = 0; + } + else if( cursorOffset() < head ) + { + sc.wrapValid = true; + sc.wrapActive = false; + sc.wrapMark = head; + } + else + { + sc.wrapValid = true; + sc.wrapActive = false; + sc.wrapMark = cursorOffset(); + } + } + + return( Err_Success ); +} + + + +int CHexBuffer::scanData( SSearchControl &sc, bool init ) +{ + if( init == true ) + { + int errCode = initScanData( sc ); + if( errCode != Err_Success ) + { + return( errCode ); + } + } + + if( sc.key.isEmpty() == true ) + { + return( Err_EmptyArgument ); + } + + if( documentSize() == 0 ) + { + return( Err_EmptyDocument ); + } + + uint head, tail; + if( sc.inSelection == true ) + { + if( mSelect.valid() == false ) + { + return( Err_NoSelection ); + } + + head = mSelect.start(); + tail = mSelect.stop(); + } + else + { + head = 0; + tail = documentSize(); + } + + uint start, stop; + if( sc.fromCursor == false ) + { + if( sc.wrapActive == true ) + { + start = sc.forward == true ? head : sc.wrapMark; + stop = sc.forward == true ? sc.wrapMark+sc.key.size() : tail; + } + else + { + start = head; + stop = tail; + } + } + else if( sc.forward == true ) + { + start = cursorOffset() < head ? head : cursorOffset(); + stop = sc.wrapActive == true ? sc.wrapMark : tail; + } + else + { + start = sc.wrapActive == true ? sc.wrapMark : head; + stop = cursorOffset() > tail ? tail : cursorOffset(); + } + + if( sc.forward == true && start + sc.key.size() > stop ) + { + // + // When searching backwards "stop" is the last offset from where + // we do a memcmp() upward in memory. An overflow for that + // situation is taken care of below. + // + return( stop + sc.key.size() < tail ? Err_WrapBuffer : Err_NoData ); + } + + if( stop + sc.key.size() > tail ) + { + uint diff = stop + sc.key.size() - tail; + stop = stop > diff ? stop - diff : 0; + } + + if( sc.forward == true ) + { + for( uint i = start; i <= stop; i++ ) + { + int result; + if( sc.ignoreCase == true ) + { + result = strncasecmp( &data()[i], sc.key.data(), sc.key.size() ); + } + else + { + result = memcmp( &data()[i], sc.key.data(), sc.key.size() ); + } + if( result == 0 ) + { + if( i != cursorOffset() || mMark.size() != sc.key.size() ) + { + sc.match = true; + cursorGoto( i, 7 ); + markSet( i, sc.key.size() ); + return( Err_Success ); + } + } + } + return( start > head ? Err_WrapBuffer : Err_NoData ); + } + else + { + for( uint i = stop; i >= start; i-- ) + { + int result; + if( sc.ignoreCase == true ) + { + result = strncasecmp( &data()[i], sc.key.data(), sc.key.size() ); + } + else + { + result = memcmp( &data()[i], sc.key.data(), sc.key.size() ); + } + if( result == 0 ) + { + if( i != cursorOffset() || mMark.size() != sc.key.size() ) + { + sc.match = true; + cursorGoto( i, 7 ); + markSet( i, sc.key.size() ); + return( Err_Success ); + } + } + if( i == 0 ) { break; } + } + + return( stop + sc.key.size() <= tail ? Err_WrapBuffer : Err_NoData ); + } +} + + + + + +int CHexBuffer::filter( SFilterControl &fc ) +{ + uint head, tail; + if( fc.inSelection == true ) + { + if( mSelect.valid() == false ) + { + return( Err_NoSelection ); + } + + head = mSelect.start(); + tail = mSelect.stop(); + } + else + { + head = 0; + tail = documentSize(); + } + + uint start, stop; + if( fc.fromCursor == false ) + { + start = head; + stop = tail; + } + else if( fc.forward == true ) + { + start = cursorOffset() < head ? head : cursorOffset(); + stop = tail; + } + else + { + start = head; + stop = cursorOffset() > tail ? tail : cursorOffset(); + } + + if( mInputMode.noInput() == true ) + { + inputSound(); + return( Err_WriteProtect ); + } + + if( start >= stop ) { return( Err_IllegalRange ); } + QByteArray buf( stop - start ); + if( buf.isEmpty() == true ) { return( Err_NoMemory ); } + + int errCode = fc.execute((uchar*)&buf[0],(uchar*)&data()[start],buf.size()); + if( errCode == Err_Success ) + { + recordStart( mCursor ); + cursorGoto( start, 7 ); + recordReplace( mCursor, buf.size(), buf.data(), buf.size() ); + recordEnd( mCursor ); + } + + return( errCode ); +} + + + +int CHexBuffer::collectStrings( CStringCollectControl &sc ) +{ + uint startOffset = 0; + uint start, i; + bool on = false; + + if( sc.minLength < 1 ) { sc.minLength = 1; } + + start = startOffset; + for( i = startOffset; i= 128 ) + { + if( on == true && i-start >= sc.minLength ) + { + QByteArray a( i-start ); + for( uint j=0; j<(i-start); a[j]=data()[start+j], j++ ); + sc.add( start, a ); + } + on = false; + } + else + { + if( on == false ) { start = i; } + on = true; + } + } + + if( on == true && i-start >= sc.minLength ) + { + QByteArray a( i-start ); + for( uint j=0; j<(i-start); a[j]=data()[start+j], j++ ); + sc.add( start, a ); + } + + return( Err_Success ); +} + + +int CHexBuffer::collectStatistic( SStatisticControl &sc, CProgress &p ) +{ + sc.documentSize = documentSize(); + sc.documentName = mUrl; + + for( uint i = 0; imHexAction; + group->mHexAction = 0; + + while( action != 0 ) + { + doAction( action ); + CHexAction *next = action->mNext; + group->insertAction( action ); + action = next; + } + + computeNumLines(); +} + + +void CHexBuffer::doAction( CHexAction *action ) +{ + if( action->mAction == CHexAction::replace ) + { + doReplace( action, true ); + } +} + + + + + +void CHexBuffer::recordStart( SCursor &cursor ) +{ + // + // Step 1: Remove any undo element that is more recent than the + // current undo index + // + while( mUndoList.count() > mUndoIndex ) + { + mUndoList.removeLast(); + } + + // + // Step 2: Make sure the undo list is no larger than the undo limit. + // We remove the oldest elements in the list. + // + while( mUndoList.count() >= mUndoLimit ) + { + mUndoList.removeFirst(); + mUndoIndex -= 1; + } + + CHexActionGroup *group = new CHexActionGroup( cursor.curr.offset, + cursor.bit() ); + if( group == 0 ) + { + return; + } + + mUndoList.append( group ); + mUndoIndex += 1; +} + + +void CHexBuffer::recordReplace( SCursor &cursor, uint size, char *data1, + uint data1Size ) +{ + CHexAction *hexAction = new CHexAction( CHexAction::replace, + cursor.curr.offset ); + if( hexAction == 0 ) + { + return; + } + + hexAction->mSize = size; + hexAction->mData = data1; + hexAction->mDataSize = data1Size; + + doReplace( hexAction, false ); + mUndoList.getLast()->insertAction( hexAction ); + + if( mCursor.curr.offset < documentSize() ) + { + mCursor.curr.data = data()[ mCursor.curr.offset ]; + } + +} + +void CHexBuffer::recordEnd( SCursor &cursor ) +{ + mUndoList.getLast()->mStopOffset = cursor.curr.offset; + mUndoList.getLast()->mStopBit = cursor.bit(); +} + + +// +// This method is the only place where the doucument data can be changed. +// +void CHexBuffer::doReplace( CHexAction *hexAction, bool removeData ) +{ + uint offset = hexAction->mOffset; + uint oldSize = hexAction->mSize; + char *newData = hexAction->mData; + uint newSize = hexAction->mDataSize; + + hexAction->setData( newSize, &data()[offset], oldSize ); + + // + // Input new data. Resize buffer first if necessary. We always mark the + // data as changed (dirty) when the buffer is resized, otherwise only + // when the new data differ from the current. Nice feature :-) + // + int errCode; + if( newSize > oldSize ) + { + errCode = moveBuffer( offset + newSize - oldSize, offset ); + mDocumentModified = true; + } + else if( newSize < oldSize ) + { + errCode = moveBuffer( offset, offset + oldSize - newSize ); + mDocumentModified = true; + } + else + { + errCode = Err_Success; + if( memcmp( &data()[offset], newData, newSize ) != 0 ) + { + mDocumentModified = true; + } + } + + if( errCode == Err_Success ) + { + memcpy( &data()[offset], newData, newSize ); + } + + // + // Data is removed regardless of success or not. Otherwise we will + // have a mmeory leak. The single reason why the operation above could + // fail is because there was that no more memory that could be + // allocated. + // + if( removeData == true ) + { + delete [] newData; + } + +} + + +bool CHexBuffer::inputDummy( unsigned char *dest, int value, uint cell ) +{ + (void)dest; + (void)value; + (void)cell; + return( false ); +} + + +bool CHexBuffer::inputHexadecimal( unsigned char *dest, int value, uint cell ) +{ + if( value >= '0' && value <= '9' ) + { + value = value - '0'; + } + else if( value >= 'A' && value <= 'F' ) + { + value = value - 'A' + 10; + } + else if( value >= 'a' && value <= 'f' ) + { + value = value - 'a' + 10; + } + else + { + return( false ); + } + + if( cell > 1 ) + { + return( false ); + } + + uint shift = 1 - cell; + *dest = (*dest & ~(0xF<<(shift*4)) ) | (value<<(shift*4)); + return( true ); +} + + +bool CHexBuffer::inputDecimal( unsigned char *dest, int value, uint cell ) +{ + // + // 2000-01-22 Espen Sand + // I do the insertion a bit different here since decimal is special + // with respect to bitwidths. + // + if( value < '0' || value > '9' || cell > 2 ) + { + return( false ); + } + + char buf[4]; + printDecimalCell( buf, *dest ); + buf[cell]=value; + buf[3]=0; + + int tmp = atoi(buf); + if( tmp > 255 ) + { + return( false ); + } + + *dest = tmp; + return( true ); +} + + +bool CHexBuffer::inputOctal( unsigned char *dest, int value, uint cell ) +{ + if( value >= '0' && value <= '7' ) + { + value = value - '0'; + if( cell == 0 && value > 3 ) + { + return( false ); + } + } + else + { + return( false ); + } + + if( cell >= 3 ) + { + return( false ); + } + + uint shift = 2 - cell; + *dest = (*dest & ~(0x7<<(shift*3)) ) | (value<<(shift*3)); + return( true ); +} + + +bool CHexBuffer::inputBinary( unsigned char *dest, int value, uint cell ) +{ + if( value >= '0' && value <= '1' ) + { + value = value - '0'; + } + else + { + return( false ); + } + + if( cell > 7 ) + { + return( false ); + } + + uint shift = 7 - cell; + *dest = (*dest & ~(1< documentSize() || destOffset == srcOffset ) + { + return( Err_Success ); + } + + if( destOffset < srcOffset ) + { + char *dest = &data()[ destOffset ]; + char *src = &data()[ srcOffset ]; + + memmove( dest, src, documentSize() - srcOffset ); + setDocumentSize( documentSize() - (srcOffset - destOffset) ); + return( Err_Success ); + } + else + { + uint s = documentSize() - srcOffset; + if( destOffset + s >= size() ) + { + int errCode = resizeBuffer( destOffset + s ); + if( errCode != Err_Success ) + { + fatalSound(); + return( errCode ); + } + } + else + { + setDocumentSize( documentSize() + (destOffset - srcOffset) ); + } + + char *dest = &data()[ destOffset ]; + char *src = &data()[ srcOffset ]; + + memmove( dest, src, s ); + memset( src, 0, destOffset - srcOffset ); + return( Err_Success ); + } +} + + + + +int CHexBuffer::resizeBuffer( uint newSize ) +{ + if( newSize < documentSize() ) + { + return( Err_Success ); + } + + if( newSize >= size() ) + { + QByteArray tmp; + tmp.duplicate( data(), size() ); + if( tmp.isNull() == true ) + { + return( Err_NoMemory ); + } + + if( fill( '\0', newSize + 100 ) == false ) + { + return( Err_NoMemory ); + } + + memcpy( data(), &tmp[0], tmp.size() ); + } + + setDocumentSize( newSize ); + return( Err_Success ); +} + + +void CHexBuffer::inputSound( void ) +{ + if( mInputErrorSound == true ) + { + KNotifyClient::beep( QObject::tr("Edit operation failed") ); + } +} + + +void CHexBuffer::fatalSound( void ) +{ + if( mFatalErrorSound == true ) + { + KNotifyClient::beep( QObject::tr("Could not allocate memory") ); + } +} + + +int CHexBuffer::printHtmlDataPage( const QString &tocName, + const QStringList &fileNames, uint index, + const SExportHtml &ex, + uint line, uint numLine ) +{ + if( fileNames.count() == 0 ) + { + return( Err_NullArgument ); + } + + if( index >= fileNames.count() ) + { + index = fileNames.count()-1; + } + + QFile file( fileNames[index] ); + if( file.open( IO_WriteOnly ) == false ) + { + return( Err_OperationAborted ); + } + + QTextStream os( &file ); + const QString *next = index+1 >= fileNames.count() ? 0 : &fileNames[index+1]; + const QString *prev = index == 0 ? 0 : &fileNames[index-1]; + const QString *toc = tocName.length() == 0 ? 0 : &tocName; + + printHtmlHeader( os, true ); + if( ex.navigator == true ) + { + printHtmlNavigator( os, next, prev, toc ); + } + + printHtmlCaption( os, ex.topCaption, index+1, fileNames.count() ); + printHtmlTable( os, line, numLine, ex.blackWhite ); + printHtmlCaption( os, ex.bottomCaption, index+1, fileNames.count() ); + + if( ex.navigator == true ) + { + printHtmlNavigator( os, next, prev, toc ); + } + printHtmlHeader( os, false ); + + return( Err_Success ); +} + + +void CHexBuffer::printHtmlTocPage( const QString &tocName, + const QString &linkName, + const QStringList &fileNames, + const QStringList &offsets, + uint numPage ) +{ + if( numPage == 0 || fileNames.count() == 0 ) + { + return; + } + if( numPage >= fileNames.count() ) + { + numPage = fileNames.count() - 1; + } + + QFile file( tocName ); + if( file.open( IO_WriteOnly ) == false ) + { + return; + } + + QTextStream os( &file ); + printHtmlHeader( os, true ); + + os << "

" << endl; + os << "" << endl; + os << mUrl << endl; + os << "" << endl; + os << "

" << endl; + + os << "

" << endl; + for( uint i=0; i<=numPage; i++ ) + { + QString n( fileNames[i].right( fileNames[i].length() - + fileNames[i].findRev('/') - 1) ); + os << "" << i18n("Page") << i+1; + os << ""; + os << " " << offsets[i]; + os << "
" << endl; + } + os << "

" << endl; + + printHtmlHeader( os, false ); + + if( linkName.isEmpty() == false ) + { + // + // Make a symlink. We ignore any error here. I don't consider + // it to be fatal. + // + QString n( tocName.right( tocName.length() - tocName.findRev('/') - 1) ); + symlink( n.latin1(), linkName.latin1() ); + } + +} + + + +void CHexBuffer::printHtmlCaption( QTextStream &os, uint captionType, + uint curPage, uint numPage ) +{ + QString caption; + switch( captionType ) + { + case 0: + return; + break; + + case 1: + caption = mUrl; + break; + + case 2: + caption = mUrl.right( mUrl.length() - mUrl.findRev('/') - 1); + break; + + case 3: + caption = i18n("Page %1 of %2").arg(curPage).arg(numPage); + break; + } + + os << "

" << endl; + os << "" << endl; + os << caption << endl; + os << "" << endl; + os << "

" << endl; +} + + + +void CHexBuffer::printHtmlNavigator( QTextStream &os, const QString *next, + const QString *prev, const QString *toc ) +{ + os << "" << endl; + os << "" << endl; + os << "" << endl; + + os << "" << endl; + os << "" << endl << "
" << endl; + if( next == 0 ) + { + os << i18n("Next") << " "; + } + else + { + QString n( next->right( next->length() - next->findRev('/') - 1) ); + os << "" << i18n("Next") << "" << " "; + } + + if( prev == 0 ) + { + os << i18n("Previous") << " "; + } + else + { + QString p( prev->right( prev->length() - prev->findRev('/') - 1) ); + os << "" << i18n("Previous") << "" << " "; + } + + if( toc == 0 ) + { + os << i18n("Contents") << " "; + } + else + { + QString t( toc->right( toc->length() - toc->findRev('/') - 1) ); + os << "" << i18n("Contents"); + os << "" << " "; + } + + os << "" << endl; + os << ""; + os << i18n("Generated by khexedit"); + os << "" << " "; + + os << "
" << endl; +} + + +int CHexBuffer::printHtmlHeader( QTextStream &os, bool isFront ) +{ + if( isFront == true ) + { + os << "" << endl << "" << endl; + os << "" << endl; + os << "" << endl; + os << "" << endl << "" << endl; + } + else + { + os << "" << endl << "" << endl; + } + + return( Err_Success ); +} + + +int CHexBuffer::printHtmlTable( QTextStream &os, uint line, uint numLine, + bool bw ) +{ + uint i; + QColor color; + + + int numCol = 1; + if( mLayout.offsetVisible == true ) { numCol += 1; } + if( mLayout.secondaryMode != SDisplayLayout::hide ) { numCol += 1; } + + os << "" << endl; + if( mLayout.offsetVisible == true ) + { + color = bw == true ? Qt::white : mColor.offsetBg; + os << "" << endl; + } + + color = bw == true ? Qt::white : mColor.textBg; + os << "
" << endl; + os << "" << endl; + + color = bw == true ? Qt::black : mColor.offsetFg; + for( i=0; i" << endl; + } + os << "
"; + THIS_FPTR(printOffset)( mPrintBuf, (line+i)*mLayout.lineSize ); + mPrintBuf[mOffsetSize]=0; + os << mPrintBuf << "
" << endl << "
" << endl; + os << "" << endl; + for( i=0; i" << endl << "" << endl; + + if( mLayout.secondaryMode != SDisplayLayout::hide ) + { + color = bw == true ? Qt::white : mColor.textBg; + os << "" << endl; + return( Err_Success ); + } + + for( uint i=0; i < mLayout.lineSize; i++ ) + { + if( isPrimary == true ) + { + if( offset+i >= documentSize() ) + { + memset(mPrintBuf, ' ', mNumCell ); + mPrintBuf[mNumCell] = 0; + if( i == 0 ) + { + color = bw == true ? Qt::black : foregroundColor(i); + } + else + { + color = prevColor; + } + } + else + { + unsigned char val = (unsigned char)data()[offset+i]; + if( THIS_FPTR(printCell)( mPrintBuf, val ) == 0 ) + { + color = bw == true ? Qt::black : foregroundColor(i); + } + else + { + color = bw == true ? Qt::black : mColor.nonPrintFg; + } + } + mPrintBuf[mNumCell] = 0; + if( i == 0 ) + { + os << ""; + } + else if( color != prevColor ) + { + os << ""; + } + prevColor = color; + + if( mPrintBuf[0] == '<' ) + { + os << "<"; + } + else + { + os << mPrintBuf; + if( (i+1) % mLayout.columnSize == 0 && (i+1) != mLayout.lineSize ) + { + os << " "; + } + } + } + else + { + if( offset+i >= documentSize() ) + { + memset(mPrintBuf, ' ', 1 ); + if( i == 0 ) + { + color = bw == true ? Qt::black : mColor.secondaryFg; + } + else + { + color = prevColor; + } + } + else + { + unsigned char val = (unsigned char)data()[offset+i]; + if( printAsciiCell( mPrintBuf, val ) == 0 ) + { + color = bw == true ? Qt::black : mColor.secondaryFg; + } + else + { + color = bw == true ? Qt::black : mColor.nonPrintFg; + } + mPrintBuf[1] = 0; + + if( i == 0 ) + { + os << ""; + } + else if( color != prevColor ) + { + os << ""; + } + prevColor = color; + + mPrintBuf[1] = 0; + os << (mPrintBuf[0] == '<' ? "<" : mPrintBuf); + } + + } + } + os << "" << endl; + return( Err_Success ); +} + + + + + diff --git a/khexedit/hexbuffer.h b/khexedit/hexbuffer.h new file mode 100644 index 0000000..ea11d95 --- /dev/null +++ b/khexedit/hexbuffer.h @@ -0,0 +1,2040 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_BUFFER_H_ +#define _HEX_BUFFER_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "conversion.h" +#include "hexeditstate.h" +#include "hexprinter.h" +#include "progress.h" + +// +// Marco to simplify usage of function pointers +// +#define THIS_FPTR( func ) ((this->*func)) + +struct SSearchControl +{ + QByteArray key; + QByteArray val; + uint keyType; + bool fromCursor; + bool inSelection; + bool forward; + bool ignoreCase; + bool match; + uint numReplace; + + bool wrapValid; + bool wrapActive; + uint wrapMark; +}; + + +struct SFilterControl +{ + enum Operation + { + OperandAndData = 0, + OperandOrData, + OperandXorData, + InvertData, + ReverseData, + RotateData, + ShiftData, + SwapBits + }; + + int execute( uchar *dest, uchar *src, uint size ); + + + QByteArray operand; + int rotate[2]; + Operation operation; + bool fromCursor; + bool inSelection; + bool forward; +}; + + +struct SInsertData +{ + uint size; + QByteArray pattern; + uint offset; + bool repeatPattern; + bool onCursor; +}; + + +struct SExportRange +{ + enum EMode + { + All = 0, + Selection, + Range + }; + + EMode mode; + uint start; + uint stop; +}; + + +struct SExportText +{ + SExportRange range; + QString destFile; +}; + + +struct SExportHtml +{ + SExportRange range; + QString package; + QString prefix; + uint linePerPage; + uint topCaption; + uint bottomCaption; + bool symLink; + bool navigator; + bool blackWhite; +}; + + +struct SExportCArray +{ + enum ElementType + { + Char = 0, + Uchar, + Short, + Ushort, + Int, + Uint, + Float, + Double + }; + + const char *printFormatted( const char *b, uint maxSize ) const; + QString variableName( uint range ) const; + int elementSize( void ) const; + + SExportRange range; + QString destFile; + QString arrayName; + int elementType; + uint elementPerLine; + bool unsignedAsHexadecimal; +}; + + +struct SStatisticControl +{ + SStatisticControl( void ) + { + memset( occurrence, 0, sizeof(occurrence) ); + documentSize = 0; + } + + uint documentSize; + uint occurrence[256]; + QString documentName; +}; + + +struct SPagePosition +{ + SPagePosition( time_t now, uint numLine, uint linePerPage ) + { + init( now, numLine, linePerPage ); + } + + SPagePosition( void ) + { + init( 0, 1, 1 ); + } + + void init( time_t at, uint numLine, uint linePerPage ) + { + if( linePerPage == 0 ) { linePerPage = 1; } + + now = at; + curPage = 1; + maxPage = numLine / linePerPage + (numLine % linePerPage ? 1 : 0); + if( maxPage < curPage ) { maxPage = curPage; } + } + + void step( uint stepSize=1 ) + { + curPage += stepSize; + if( curPage > maxPage ) { curPage = maxPage; } + } + + uint current( void ) + { + return( curPage ); + } + + uint max( void ) + { + return( maxPage ); + } + + uint curPage; + uint maxPage; + time_t now; +}; + + + +class CStringCollectControl +{ + public: + CStringCollectControl( void ) + { + mList.setAutoDelete( true ); + } + + int add( uint offset, const QByteArray &a ) + { + QString *s = new QString(); + if( s == 0 ) + { + return( Err_NoMemory ); + } + + if( decimalOffset == true ) + { + s->sprintf( "%010u", offset ); + } + else + { + s->sprintf( "%04x:%04x", offset>>16, offset&0x0000FFFF ); + } + + *s += QString( a ); + + mList.append( s ); + return( Err_Success ); + } + + uint offsetLen( void ) + { + return( decimalOffset ? 10 : 9 ); + } + + void clear( void ) + { + mList.clear(); + } + + const QString *get( uint index ) + { + return( mList.at( index ) ); + } + + int count( void ) + { + return( mList.count() ); + } + + QPtrList &list( void ) + { + return( mList ); + } + + public: + uint minLength; + bool decimalOffset; + bool allow8bit; + + private: + QPtrList mList; +}; + + + + + + +struct SCursorConfig +{ + SCursorConfig( void ) + { + state = 0; + } + + bool selectOn( void ) + { + return( state & Qt::ShiftButton ); + } + + bool removeSelection( void ) + { + return( state & Qt::ShiftButton ? false : true ); + } + + void setKeepSelection( bool val ) + { + state = val == true ? state|Qt::ShiftButton : state&~Qt::ShiftButton; + } + + bool controlButton( void ) + { + return( state & Qt::ControlButton ? true : false ); + } + + bool shiftButton( void ) + { + return( state & Qt::ShiftButton ? true : false ); + } + + bool altButton( void ) + { + return( state & Qt::AltButton ? true : false ); + } + + + void emulateControlButton( bool val ) + { + state = val == true ? state|Qt::ControlButton : state&~Qt::ControlButton; + } + + int state; +}; + + + +struct SCursorSpec +{ + enum EShape + { + solid = 0, + frame, + thin + }; + + void reset( void ) + { + offset = 0; + x1 = x2 = y = cell = maxCell = 0; + } + + void setShape( EShape primaryShape, EShape secondaryShape, uint unitWidth, + uint numCell ) + { + + if( primaryShape == thin ) + { + if( onlyBlock == true ) { primaryShape = solid; } + } + if( secondaryShape == thin ) + { + if( onlyBlock == true ) { secondaryShape = solid; } + } + + mPrimaryShape = primaryShape; + if( mPrimaryShape == solid ) + { + drawWidth1 = unitWidth; + drawOffset1 = 0; + } + else if( mPrimaryShape == frame ) + { + drawWidth1 = unitWidth * numCell; + drawOffset1 = 0; + } + else + { + mPrimaryShape = thin; + if( thickState == true ) + { + drawWidth1 = 2; + drawOffset1 = -1; + } + else + { + drawWidth1 = 5; + drawOffset1 = -3; + } + } + + mSecondaryShape = secondaryShape; + if( mSecondaryShape == solid ) + { + drawWidth2 = unitWidth; + drawOffset2 = 0; + } + else if( mSecondaryShape == frame ) + { + drawWidth2 = unitWidth * numCell; + drawOffset2 = 0; + } + else + { + mSecondaryShape = thin; + if( thickState == true ) + { + drawWidth2 = 2; + drawOffset2 = -1; + } + else + { + drawWidth2 = 5; + drawOffset2 = -3; + } + } + } + + void setShapeModifier( bool alwaysBlock, bool useThick ) + { + onlyBlock = alwaysBlock; + thickState = useThick; + } + + void dump( void ) + { + std::cout << "offset: " << offset << " y: " << y << " x1: " << x1 << std::endl; + std::cout << "x2: " << x2 << " cell: " << cell << std::endl; + } + + bool inside( uint min, uint max ) + { + return( offset >= min && offset < max ); + } + + int drawX1( void ) + { + return( x1 + drawOffset1 ); + } + + int drawX2( void ) + { + return( x2 + drawOffset2 ); + } + + int width1( void ) + { + return( drawWidth1 ); + } + + int width2( void ) + { + return( drawWidth2 ); + } + + uint offset; + int y; + int x1; + int x2; + int cell; + int maxCell; + bool onlyBlock; + bool thickState; + + char data; + + int mPrimaryShape; + int mSecondaryShape; + int drawWidth1; + int drawWidth2; + int drawOffset1; + int drawOffset2; +}; + + +struct SCursor +{ + SCursor( void ) + { + mLineSize = 1; + mDocumentSize = 0; + mFixedSizeMode = false; + mArea = 0; + } + + void reset( void ) + { + prev.reset(); + curr.reset(); + next.reset(); + } + + void setDocumentSize( uint documentSize ) + { + mDocumentSize = documentSize; + } + + void setFixedSizeMode( bool fixedSizeMode ) + { + mFixedSizeMode = fixedSizeMode; + } + + bool incCell( void ) + { + if( curr.cell + 1 >= curr.maxCell ) + { + addOffset( 1 ); + return( true ); + } + else + { + next.cell = curr.cell + 1; + return( false ); + } + } + + bool decCell( void ) + { + if( curr.cell == 0 ) + { + if( curr.offset > 0 ) + { + decOffset( 1, true ); + next.cell = curr.maxCell > 0 ? curr.maxCell - 1 : 0; + } + return( true ); + } + else + { + next.cell = curr.cell - 1; + return( false ); + } + } + + void resetCell( void ) + { + next.cell = 0; + } + + + void addOffset( uint val ) + { + setOffset( curr.offset + val ); + } + + void decOffset( uint val, bool ignoreCell ) + { + if( ignoreCell == true || curr.cell == 0 ) + { + setOffset( val > curr.offset ? curr.offset%mLineSize : curr.offset-val); + } + else + { + setOffset( curr.offset ); + } + } + + void setOffset( uint offset ) + { + /* + if( offset >= mDocumentSize ) + { + if( mFixedSizeMode == true ) + { + offset = mDocumentSize > 0 ? mDocumentSize - 1 : 0; + } + else + { + offset = mDocumentSize; + } + } + */ + + next.offset = offset; + next.cell = 0; + } + + uint getOffset( void ) + { + return( curr.offset ); + } + + void setOffset( uint offset, uint bit, bool backward, bool fromCursor, + uint textSize ) + { + if( fromCursor == true ) + { + if( backward == true ) + { + setOffset( offset > curr.offset ? 0 : curr.offset - offset ); + } + else + { + setOffset( curr.offset + offset ); + } + } + else + { + if( backward == true ) + { + setOffset( offset > textSize ? 0 : textSize - offset ); + } + else + { + setOffset( offset > textSize ? textSize : offset ); + } + } + setBit( bit ); + } + + + void setBit( uint bit ) + { + bit = (bit > 7) ? 0 : 7 - bit; + next.cell = bit / mCellWeight; + } + + + void home( bool toExtreme ) + { + if( toExtreme == true ) + { + setOffset( 0 ); + } + else + { + setOffset( next.offset - curr.offset % mLineSize ); + } + } + + void end( bool toExtreme ) + { + uint maxOffset; + if( mFixedSizeMode == true ) + { + maxOffset = mDocumentSize > 0 ? mDocumentSize-1 : mDocumentSize; + } + else + { + maxOffset = mDocumentSize; + } + + if( toExtreme == true ) + { + setOffset( maxOffset ); + } + else + { + uint newOffset = next.offset + (mLineSize-1) - curr.offset % mLineSize; + setOffset( newOffset > maxOffset ? maxOffset : newOffset ); + } + + } + + void up( uint numLines ) + { + decOffset( numLines * mLineSize, true ); + } + + void down( uint numLines ) + { + addOffset( numLines * mLineSize ); + } + + bool changed( void ) + { + return( prev.offset != curr.offset || prev.cell != curr.cell || + prev.data != curr.data ? true : false ); + } + + uint bit( void ) + { + uint bitValue = mCellWeight*(curr.maxCell - curr.cell) - 1; + return( bitValue > 7 ? 7 : bitValue ); + } + + uint cellWeight( void ) + { + return( mCellWeight ); + } + + void setLineSize( uint lineSize ) + { + mLineSize = lineSize < 1 ? 1 : lineSize; + } + + void setCellWeight( uint cellWeight ) + { + mCellWeight = cellWeight; + } + + int area( void ) + { + return( mArea ); + } + + void setArea( int area ) + { + mArea = area; + } + + void setShape( SCursorSpec::EShape primary, SCursorSpec::EShape secondary, + uint unitWidth, uint numCell ) + { + curr.setShape( primary, secondary, unitWidth, numCell ); + } + + void setShapeModifier( bool alwaysBlock, bool useThick ) + { + curr.setShapeModifier( alwaysBlock, useThick ); + } + + uint mLineSize; + uint mDocumentSize; + uint mCellWeight; + int mArea; + bool mFixedSizeMode; + SCursorSpec prev; + SCursorSpec curr; + SCursorSpec next; +}; + + +struct SCursorPosition +{ + int x; + int y; + int w; + int h; +}; + +struct SCursorOffset +{ + uint offset; + uint bit; +}; + + +struct SSelectSpec +{ + void init( uint offset ) + { + start = stop = anchor = offset; + } + + void set( uint offset ) + { + if( offset < anchor ) + { + start = offset; + stop = anchor; + } + else + { + stop = offset; + start = anchor; + } + } + + void expand( uint value ) + { + if( anchor == stop ) { anchor +=value; } + stop += value; + //set( stop + value ); + } + + void shrink( uint value ) + { + uint newVal = start + value > stop ? start : stop - value; + if( anchor == stop ) { anchor = newVal; } + stop = newVal; + /* + if( start + value > stop ) + { + set( start ); + } + else + { + set( stop - value ); + } + */ + } + + + uint start; + uint stop; + uint anchor; +}; + + +struct SSelect +{ + SSelect( void ) + { + reset(); + } + + bool init( uint offset ) + { + curr.init( offset ); + if( isValid == true ) + { + isValid = false; + return( true ); + } + else + { + return( false ); + } + } + + void reset( void ) + { + curr.init( 0 ); + isValid = false; + } + + bool set( uint offset ) + { + isValid = true; + + curr.set( offset ); + if( curr.start != prev.start || curr.stop != prev.stop ) + { + return( true ); + } + else + { + return( false ); + } + } + + void expand( uint value ) + { + if( isValid == false ) + { + return; + } + curr.expand( value ); + } + + void shrink( uint value ) + { + if( isValid == false ) + { + return; + } + curr.shrink( value ); + } + + + void sync( void ) + { + prev = curr; + } + + bool inside( uint offset ) + { + return( isValid == true && offset >= curr.start && offset < curr.stop ); + } + + bool inside( uint offset, uint range ) + { + return( isValid == true && (offset + range) >= curr.start && + offset < curr.stop ); + } + + bool verify( uint &start, uint &stop ) + { + if( isValid == false ) + { + return( false ); + } + + if( start < curr.start ) { start = curr.start; } + if( stop > curr.stop ) { stop = curr.stop; } + return( true ); + } + + uint start( uint offset ) + { + // + // If 'curr.star' is smaller than 'offset' then the start is at + // the start of line. + // + return( curr.start < offset ? 0 : curr.start - offset ); + } + + uint start( void ) + { + return( curr.start ); + } + + uint stop( uint offset, uint range ) + { + return( curr.stop > offset + range ? range : curr.stop - offset ); + } + + uint stop( void ) + { + return( curr.stop ); + } + + bool valid( void ) + { + return( isValid ); + } + + uint size( void ) + { + if( isValid == false ) + { + return( 0 ); + } + else + { + return( curr.start >= curr.stop ? 0 : curr.stop - curr.start ); + } + } + + void startChange( uint &first, uint &last ) + { + if( curr.start <= prev.start ) + { + first = curr.start; + last = prev.start; + } + else + { + first = prev.start; + last = curr.start; + } + } + + void stopChange( uint &first, uint &last ) + { + if( curr.stop <= prev.stop ) + { + first = curr.stop; + last = prev.stop; + } + else + { + first = prev.stop; + last = curr.stop; + } + } + + + bool isValid; + SSelectSpec prev; + SSelectSpec curr; +}; + + + +class CHexAction +{ + public: + enum HexAction + { + replace + }; + + public: + CHexAction( HexAction action, uint offset ); + ~CHexAction( void ); + void setData( uint size, char *data, uint dataSize ); + + public: + HexAction mAction; + uint mOffset; + uint mSize; + char *mData; + uint mDataSize; + CHexAction *mNext; +}; + +class CHexActionGroup +{ + public: + CHexActionGroup( uint startOffset, uint startBit ); + ~CHexActionGroup( void ); + void insertAction( CHexAction *hexAction ); + + public: + uint mStartOffset; + uint mStopOffset; + uint mStartBit; + uint mStopBit; + CHexAction *mHexAction; +}; + + + +struct SCursorState +{ + bool valid; + uint selectionOffset; + uint selectionSize; + uint offset; + uint cell; + unsigned char data[8]; + uint undoState; + bool charValid; +}; + +struct SFileState +{ + bool valid; + uint size; + bool modified; +}; + + + + + +class CHexBuffer; +typedef int (CHexBuffer::*PrintCellFunc)( char *buf, unsigned char data ); +typedef bool (CHexBuffer::*InputCellFunc)( unsigned char *dest, int value, + uint cell ); +typedef void (CHexBuffer::*PrintOffsetFunc)( char *buf, uint offset ); + + +class CHexBuffer : public QByteArray +{ + public: + enum EColumn + { + VisibleColumn = 0x0, + OffsetColumn = 0x1, + PrimaryColumn = 0x2, + SecondaryColumn = 0x4, + EveryColumn = 0x7 + }; + + enum EEditArea + { + edit_none = 0, + edit_primary, + edit_secondary + }; + + enum ECursorMode + { + cursor_curr = 0, + cursor_prev + }; + + enum EEditMode + { + EditInsert = 0, + EditReplace + }; + + enum EUndoState + { + UndoOk = 1, + RedoOk = 2 + }; + + public: + CHexBuffer( void ); + ~CHexBuffer( void ); + + int setLayout( SDisplayLayout &layout ); + void setColor( SDisplayColor &color ); + void setInputMode( SDisplayInputMode &mode ); + bool toggleEditor( void ); + + bool matchWidth( uint width ); + + void setNonPrintChar( QChar nonPrintChar ); + void setShowCursor( bool showCursor ); + void setDisableCursor( bool disableCursor ); + void setCursorShapeModifier( bool alwaysBlock, bool thickInsert ); + void setEditMode( EEditMode editMode ); + void setEditMode( EEditMode editMode, bool alwaysBlock, bool thickInsert ); + void setMaximumSize( uint size ); + void setDocumentSize( uint size ); + void setUndoLevel( uint level ); + void setSoundState( bool inputSound, bool fatalSound ); + void setBookmarkVisibility( bool showInColumn, bool showInEditor ); + + void setFont( const SDisplayFontInfo &fontInfo ); + int setEncoding( CConversion::EMode mode, CProgress &p ); + + bool setCursorPosition( int x, int y, bool init, bool cellLevel ); + + int readFile( QFile &file, const QString &url, CProgress &p ); + int insertFile( QFile &file, CProgress &p ); + int writeFile( QFile &file, CProgress &p ); + int newFile( const QString &url ); + void closeFile( void ); + void registerDiskModifyTime( const QFile &file ); + + bool changedOnDisk( void ); + + void drawText( QPainter &paint, uint line, int sx, int x, int w ); + void drawText( QPainter &paint, uint line, int x1, int x2, int y, + bool useBlackWhite ); + + void drawHeader( QPainter &paint, int sx, int width, int y, bool isFooter, + const SPageHeader &header,const SPagePosition &position ); + int headerHeight( QPainter &paint ); + int headerMargin( QPainter &paint ); + + bool inputAtCursor( QChar c ); + int inputAtCursor( const QByteArray &buf, uint oldSize ); + bool removeAtCursor( bool beforeCursor ); + + int locateRange( const SExportRange &range, uint &start, uint &stop ); + int exportText( const SExportText &ex, CProgress &p ); + int exportHtml( const SExportHtml &ex, CProgress &p ); + int exportCArray( const SExportCArray &ex, CProgress &p ); + int copySelectedText( QByteArray &array, int columnSegment=VisibleColumn); + int copyAllText( QByteArray &array ); + int copyText( QByteArray &array, const SExportRange &range, + int columnSegment ); + int copySelectedData( QByteArray &array ); + + uint numPage( CHexPrinter &printer ); + int print( CHexPrinter &printer, CProgress &p ); + + uint printLine( char *dst, uint line ); + uint printLine( char *dst, uint line, int columnSegment ); + + bool cutSelection( void ); + bool undo( void ); + bool redo( void ); + int addBookmark( int position ); + bool removeBookmark( int position ); + void updateBookmarkMap( bool resize ); + + int findFirst( SSearchControl &sc ); + int findNext( SSearchControl &sc ); + int findWrap( SSearchControl &sc ); + int replaceAll( SSearchControl &sc, bool init ); + int replaceMarked( SSearchControl &sc ); + int filter( SFilterControl &fc ); + int collectStrings( CStringCollectControl &sc ); + int collectStatistic( SStatisticControl &sc, CProgress &p ); + + void doActionGroup( CHexActionGroup *group ); + void doAction( CHexAction *action ); + + inline SCursorState &cursorState( void ); + inline void valueOnCursor( QByteArray &buf, uint size ); + inline SFileState &fileState( void ); + inline const SDisplayLayout &layout( void ); + + inline const SDisplayInputMode &inputMode( void ); + inline QPtrList &bookmarkList( void ); + + inline bool documentPresent( void ); + inline bool modified( void ); + inline uint undoState( void ); + inline uint documentSize( void ); + inline EEditMode editMode( void ); + inline const SEncodeState &encoding( void ); + inline bool losslessEncoding( CConversion::EMode mode ); + + inline QString &url( void ); + bool hasFileName( void ); + inline void setUrl( const QString &url ); + inline void setModified( bool modified ); + inline const QDateTime &diskModifyTime( void ); + + + + inline uint calculateLine( uint offset ); + inline int lineSize( void ); + inline int lineHeight( void ); + inline int fontAscent( void ); + inline int lineWidth( void ); + inline int unitWidth( void ); + inline int numLines( void ); + inline int totalHeight( void ); + inline const QFont &font( void ); + inline SCursor *textCursor( void ); + inline const QColor &backgroundColor( void ); + inline int startX( void ); + inline int startY( void ); + inline void setStartX( int val ); + inline void setStartY( int val ); + + inline bool selectionSet( uint offset, bool init ); + inline void selectionSyncronize( void ); + inline void selectionStartChange( uint &offset1, uint &offset2 ); + inline void selectionStopChange( uint &offset1, uint &offset2 ); + inline bool cursorInsideSelection( void ); + + inline void markSet( uint offset, uint size ); + inline bool markSet( uint offset, bool init ); + inline bool markRemove( void ); + inline void markSyncronize( void ); + inline void markStartChange( uint &offset1, uint &offset2 ); + inline void markStopChange( uint &offset1, uint &offset2 ); + + inline uint cursorOffset( void ); + inline uint cursorBit( void ); + inline uint cursorLine( void ); + inline uint prevCursorLine( void ); + inline SCursor &cursor( void ); + + inline void currCursor( EEditArea editArea, SCursorPosition &p ); + inline void prevCursor( EEditArea editArea, SCursorPosition &p ); + + inline void cursorUp( uint lines ); + inline void cursorDown( uint lines ); + inline void cursorRight( bool cellLevel ); + inline void cursorLeft( bool cellLevel ); + inline void cursorStep( uint size, bool forward, bool modulo ); + inline void cursorHome( bool toExtreme ); + inline void cursorEnd( bool toExtreme ); + inline void cursorGoto( uint offset, uint bit ); + inline void cursorGoto( uint offset, uint bit, bool backward, + bool fromCursor ); + inline bool cursorChanged( void ); + inline void cursorResetEditArea( void ); + inline bool cursorPrimaryEdit( void ); + inline int cursorFixedPosition( int position, int height ); + inline int cursorChangePosition( int position, int height ); + void cursorReset( void ); + + private: + enum { BookmarkOnLine = 0x01, BookmarkOnCursor = 0x02 }; + + void computeLineWidth( void ); + void computeNumLines( void ); + void cursorCompute( void ); + + void drawSelection( QPainter &paint, QColor &color, uint start, uint stop, + int sx ); + int drawBookmarks(QPainter &paint, uint line, int startx); + void drawCursor( QPainter &paint, uint line, int startx, bool onBookmark ); + + void recordStart( SCursor &cursor ); + void recordReplace( SCursor &cursor, uint size, char *data, uint dataSize); + void recordEnd( SCursor &cursor ); + void doReplace( CHexAction *hexAction, bool removeData ); + int scanData( SSearchControl &sc, bool init ); + int initScanData( SSearchControl &sc ); + + inline const QColor &foregroundColor( uint column ); + inline int printDummyCell( char *buf, unsigned char data ); + inline int printHexadecimalBigCell( char *buf, unsigned char data ); + inline int printHexadecimalSmallCell( char *buf, unsigned char data ); + inline int printDecimalCell( char *buf, unsigned char data ); + inline int printOctalCell( char *buf, unsigned char data ); + inline int printBinaryCell( char *buf, unsigned char data ); + inline int printAsciiCell( char *buf, unsigned char data ); + inline void printDummyOffset( char *buf, uint offset ); + inline void printHexadecimalBigOffset( char *buf, uint offset ); + inline void printHexadecimalSmallOffset( char *buf, uint offset ); + inline void printDecimalOffset( char *buf, uint offset ); + + bool inputDummy( unsigned char *dest, int value, uint cell ); + bool inputHexadecimal( unsigned char *dest, int value, uint cell ); + bool inputDecimal( unsigned char *dest, int value, uint cell ); + bool inputOctal( unsigned char *dest, int value, uint cell ); + bool inputBinary( unsigned char *dest, int value, uint cell ); + bool inputAscii( unsigned char *dest, int value, uint cell ); + + int moveBuffer( uint destOffset, uint srcOffset ); + int resizeBuffer( uint offset ); + + void inputSound( void ); + void fatalSound( void ); + + int printHtmlDataPage( const QString &tocName, + const QStringList &fileNames, uint index, + const SExportHtml &ex, uint line, uint numLine ); + void printHtmlCaption( QTextStream &os, uint captionType, uint curPage, + uint numPage ); + void printHtmlNavigator( QTextStream &os, const QString *next, + const QString *prev, const QString *toc ); + void printHtmlTocPage( const QString &tocName, + const QString &linkName, + const QStringList &fileNames, + const QStringList &offsets, uint numPage ); + int printHtmlHeader( QTextStream &os, bool isFront ); + int printHtmlTable( QTextStream &os, uint line, uint numLine, bool bw ); + int printHtmlLine( QTextStream &os, uint offset, bool isPrimary, bool bw ); + + signals: + void fileSize( uint size ); + + private: + QString mUrl; + QDateTime mDiskModifyTime; + SDisplayLayout mLayout; + SDisplayColor mColor; + SDisplayFontInfo mFontInfo; + CConversion mEncode; + bool mCharValid[256]; + + unsigned char *mColorIndex; + char *mPrintBuf; + bool mLoadingData; + int mStartX; + int mStartY; + + int mFontHeight; + int mFontAscent; + int mLineWidth; + int mFixedWidth; + int mUnitWidth; + int mSplitWidth; + int mNumLines; + int mTextStart1; + int mTextStart2; + int mNumCell; + + uint mDocumentSize; + uint mMaximumSize; + bool mFixedSizeMode; + bool mDocumentModified; + EEditMode mEditMode; + SDisplayInputMode mInputMode; + + int mOffsetSize; + int mOffsetIndex; + int mPrimaryWidth; + int mSecondaryWidth; + int mActiveEditor; + + SSelect mSelect; + SSelect mMark; + + SCursor mCursor; + bool mShowCursor; + bool mDisableCursor; + + bool mInputErrorSound; + bool mFatalErrorSound; + + bool mShowBookmarkInOffsetColumn; + bool mShowBookmarkInEditor; + + uint mUndoLimit; + uint mUndoIndex; + QPtrList mUndoList; + QPtrList mBookmarkList; + QBitArray mBookmarkMap; + + PrintCellFunc printCell; + PrintOffsetFunc printOffset; + InputCellFunc inputCell; + + static char mHexBigBuffer[16]; + static char mHexSmallBuffer[16]; + static char mDecBuffer[10]; + static char mOctBuffer[8]; + static SCursorState mCursorState; + static SFileState mFileState; +}; + + + +inline SCursorState &CHexBuffer::cursorState( void ) +{ + if( size() == 0 ) + { + mCursorState.valid = false; + mCursorState.selectionOffset = 0; + mCursorState.selectionSize = 0; + mCursorState.offset = 0; + mCursorState.cell = 0; + mCursorState.undoState = 0; + memset( mCursorState.data, 0, sizeof(mCursorState.data) ); + mCursorState.charValid = false; + } + else + { + mCursorState.valid = true; + mCursorState.selectionOffset = mSelect.start(); + mCursorState.selectionSize = mSelect.size(); + mCursorState.offset = cursorOffset(); + mCursorState.cell = cursorBit(); + mCursorState.undoState = undoState(); + + for( uint i = 0; i < sizeof( mCursorState.data ); i++ ) + { + mCursorState.data[i] = (mCursorState.offset+i >= mDocumentSize) ? 0 : + (unsigned char)data()[mCursorState.offset+i]; + } + + mCursorState.charValid = mCharValid[ mCursorState.data[0] ]; + } + return( mCursorState ); +} + + +inline void CHexBuffer::valueOnCursor( QByteArray &buf, uint size ) +{ + int offset = cursorOffset(); + if( offset + size >= mDocumentSize ) + { + size = mDocumentSize - offset; + } + + buf.resize(size); + for( uint i=0; i &CHexBuffer::bookmarkList( void ) +{ + return( mBookmarkList ); +} + + + + +inline SFileState &CHexBuffer::fileState( void ) +{ + if( size() == 0 ) + { + mFileState.valid = false; + mFileState.size = 0; + mFileState.modified = false; + + } + else + { + mFileState.valid = true; + mFileState.size = mDocumentSize; + mFileState.modified = mDocumentModified; + } + + return( mFileState ); +} + + + + + + + + +inline bool CHexBuffer::modified( void ) +{ + return( mDocumentModified ); +} + +inline void CHexBuffer::setModified( bool modified ) +{ + mDocumentModified = modified; +} + +inline uint CHexBuffer::undoState( void ) +{ + return( (mUndoIndex > 0 ? UndoOk : 0) | + (mUndoIndex < mUndoList.count() ? RedoOk : 0) ); +} + + +inline uint CHexBuffer::documentSize( void ) +{ + return( mDocumentSize ); +} + + +inline CHexBuffer::EEditMode CHexBuffer::editMode( void ) +{ + return( mEditMode ); +} + + +inline const SEncodeState &CHexBuffer::encoding( void ) +{ + return( mEncode.state() ); +} + +inline bool CHexBuffer::losslessEncoding( CConversion::EMode mode ) +{ + return( mEncode.lossless(mode) ); +} + +inline QString &CHexBuffer::url( void ) +{ + return( mUrl ); +} + +inline bool CHexBuffer::documentPresent( void ) +{ + return( size() == 0 ? false : true ); +} + +inline void CHexBuffer::setUrl( const QString &url ) +{ + mUrl = url; +} + +inline const QDateTime &CHexBuffer::diskModifyTime( void ) +{ + return( mDiskModifyTime ); +} + +inline uint CHexBuffer::calculateLine( uint offset ) +{ + return( mLayout.lineSize == 0 ? 0 : offset / mLayout.lineSize ); +} + +inline const QColor &CHexBuffer::foregroundColor( uint column ) +{ + if( column > mLayout.lineSize ) + { + return( Qt::black ); + } + else + { + return( mColor.primaryFg[ mColorIndex[ column ] ] ); + } +} + +inline bool CHexBuffer::selectionSet( uint offset, bool init ) +{ + if( offset >= size() ) { offset = size() > 0 ? size() - 1 : 0; } + + if( init == true ) + { + return( mSelect.init( offset ) ); + } + else + { + return( mSelect.set( offset ) ); + } +} + +inline void CHexBuffer::selectionSyncronize( void ) +{ + mSelect.sync(); +} + +inline void CHexBuffer::selectionStartChange( uint &offset1, uint &offset2 ) +{ + mSelect.startChange( offset1, offset2 ); +} + +inline void CHexBuffer::selectionStopChange( uint &offset1, uint &offset2 ) +{ + mSelect.stopChange( offset1, offset2 ); +} + +inline bool CHexBuffer::cursorInsideSelection( void ) +{ + return( mSelect.inside( cursorOffset() ) ); +} + +inline void CHexBuffer::markSet( uint offset, uint size ) +{ + markSet( offset, true ); + markSet( offset+size, false ); + mMark.sync(); +} + +inline bool CHexBuffer::markSet( uint offset, bool init ) +{ + if( offset >= size() ) { offset = size() > 0 ? size() - 1 : 0; } + + if( init == true ) + { + return( mMark.init( offset ) ); + } + else + { + return( mMark.set( offset ) ); + } +} + +inline bool CHexBuffer::markRemove( void ) +{ + return( mMark.init( mMark.start() ) ); +} + + +inline void CHexBuffer::markSyncronize( void ) +{ + mMark.sync(); +} + +inline void CHexBuffer::markStartChange( uint &offset1, uint &offset2 ) +{ + mMark.startChange( offset1, offset2 ); +} + +inline void CHexBuffer::markStopChange( uint &offset1, uint &offset2 ) +{ + mMark.stopChange( offset1, offset2 ); +} + + +inline uint CHexBuffer::cursorOffset( void ) +{ + return( mCursor.curr.offset ); +} + +inline uint CHexBuffer::cursorBit( void ) +{ + return( mCursor.bit() ); +} + + +inline uint CHexBuffer::cursorLine( void ) +{ + return( mCursor.curr.y / lineHeight() ); +} + +inline uint CHexBuffer::prevCursorLine( void ) +{ + return( mCursor.prev.y / lineHeight() ); +} + +inline SCursor &CHexBuffer::cursor( void ) +{ + return( mCursor ); +} + + +inline void CHexBuffer::currCursor( EEditArea editArea, SCursorPosition &p ) +{ + if( editArea == edit_primary ) + { + if( mActiveEditor == edit_primary ) + { + p.x = mCursor.curr.drawX1(); + p.w = mCursor.curr.width1(); + } + else + { + p.x = mCursor.curr.drawX2(); + p.w = mUnitWidth; + } + } + else + { + if( mActiveEditor == edit_primary ) + { + p.x = mCursor.curr.drawX2(); + p.w = mUnitWidth; + } + else + { + p.x = mCursor.curr.drawX1(); + p.w = mUnitWidth * mNumCell; + } + } + + p.x -= mStartX; + p.y = mCursor.curr.y - mStartY; + p.h = lineHeight(); + +} + +inline void CHexBuffer::prevCursor( EEditArea editArea, SCursorPosition &p ) +{ + if( editArea == edit_primary ) + { + if( mActiveEditor == edit_primary ) + { + p.x = mCursor.prev.drawX1(); + p.w = mUnitWidth * mNumCell; + } + else + { + p.x = mCursor.prev.drawX2(); + p.w = mUnitWidth; + } + } + else + { + if( mActiveEditor == edit_primary ) + { + p.x = mCursor.prev.drawX2(); + p.w = mUnitWidth; + } + else + { + p.x = mCursor.prev.drawX1(); + p.w = mUnitWidth * mNumCell; + } + } + + p.x -= mStartX; + p.y = mCursor.prev.y - mStartY; + p.h = lineHeight(); +} + + + + + + +inline void CHexBuffer::cursorUp( uint lines ) +{ + mCursor.up( lines ); + cursorCompute(); +} + +inline void CHexBuffer::cursorDown( uint lines ) +{ + mCursor.down( lines ); + cursorCompute(); +} + + +inline void CHexBuffer::cursorRight( bool cellLevel ) +{ + if( cellLevel == true && mActiveEditor == edit_primary ) + { + mCursor.incCell(); + } + else + { + mCursor.addOffset( 1 ); + } + cursorCompute(); +} + + +inline void CHexBuffer::cursorStep( uint size, bool forward, bool modulo ) +{ + if( forward == true ) + { + if( modulo == true ) + { + uint offset = mCursor.getOffset() + size; + mCursor.setOffset( offset - offset % size ); + } + else + { + mCursor.addOffset( size ); + } + } + else + { + if( modulo == true ) + { + uint offset = mCursor.getOffset(); + if( offset % size ) + { + mCursor.decOffset( offset % size, false ); + } + else + { + mCursor.setOffset( offset < size ? 0 : offset - size ); + } + } + else + { + mCursor.decOffset( size, false ); + } + } + cursorCompute(); +} + + +inline void CHexBuffer::cursorLeft( bool cellLevel ) +{ + if( cellLevel == true && mActiveEditor == edit_primary ) + { + mCursor.decCell(); + } + else + { + mCursor.decOffset( 1, false ); + } + cursorCompute(); +} + +inline void CHexBuffer::cursorHome( bool toExtreme ) +{ + mCursor.home( toExtreme ); + cursorCompute(); +} + +inline void CHexBuffer::cursorEnd( bool toExtreme ) +{ + mCursor.end( toExtreme ); + cursorCompute(); +} + + +inline void CHexBuffer::cursorGoto( uint offset, uint bit, bool backward, + bool fromCursor ) +{ + uint maxOffset = mFixedSizeMode == true ? mMaximumSize-1 : documentSize(); + mCursor.setOffset( offset, bit, backward, fromCursor, maxOffset ); + cursorCompute(); +} + +inline void CHexBuffer::cursorGoto( uint offset, uint bit ) +{ + mCursor.setOffset( offset ); + mCursor.setBit( bit ); + cursorCompute(); +} + +inline bool CHexBuffer::cursorChanged( void ) +{ + return( mCursor.changed() ); +} + +inline void CHexBuffer::cursorResetEditArea( void ) +{ + mCursor.setArea( edit_none ); +} + +inline bool CHexBuffer::cursorPrimaryEdit( void ) +{ + return( mActiveEditor == edit_primary ? true : false ); +} + +inline int CHexBuffer::cursorFixedPosition( int position, int height ) +{ + position += mCursor.curr.y - mCursor.prev.y; + if( position < 0 ) + { + return( 0 ); + } + else if( position + height > totalHeight() ) + { + return( height > totalHeight() ? 0 : totalHeight() - height ); + } + else + { + if( mCursor.curr.y < position ) + { + return( mCursor.curr.y ); + } + else if( mCursor.curr.y > position + height ) + { + return( mCursor.curr.y - height + lineHeight() ); + } + else + { + return( position ); + } + } +} + +inline int CHexBuffer::cursorChangePosition( int position, int height ) +{ + if( mCursor.curr.y < position || mCursor.curr.y > position + height ) + { + // When cursor is at top of window + position = mCursor.curr.y; + } + else if( mCursor.curr.y > position + height - lineHeight() ) + { + // When cursor is at bottom of window + position = mCursor.curr.y - height + lineHeight(); + } + + return( position ); +} + +inline int CHexBuffer::printDummyCell( char *buf, unsigned char ) +{ + buf[0] = 0; + return( 0 ); +} + +inline int CHexBuffer::printHexadecimalBigCell( char *buf, unsigned char data ) +{ + buf[0] = mHexBigBuffer[ (data>>4)&0x0F ]; + buf[1] = mHexBigBuffer[ data&0x0F ]; + return( 0 ); +} + +inline int CHexBuffer::printHexadecimalSmallCell( char *buf, + unsigned char data ) +{ + buf[0] = mHexSmallBuffer[ (data>>4)&0x0F ]; + buf[1] = mHexSmallBuffer[ data&0x0F ]; + return( 0 ); +} + + +inline int CHexBuffer::printDecimalCell( char *buf, unsigned char data ) +{ + buf[0] = mDecBuffer[ data/100 ]; + data -= (data/100) * 100; + buf[1] = mDecBuffer[ data/10 ]; + data -= (data/10) * 10; + buf[2] = mDecBuffer[ data ]; + return( 0 ); +} + +inline int CHexBuffer::printOctalCell( char *buf, unsigned char data ) +{ + buf[0] = mOctBuffer[ (data>>6)&0x07 ]; + buf[1] = mOctBuffer[ (data>>3)&0x07 ]; + buf[2] = mOctBuffer[ data&0x07 ]; + return( 0 ); +} + +inline int CHexBuffer::printBinaryCell( char *buf, unsigned char data ) +{ + for( int i = 0; i < 8; i++ ) + { + buf[7-i] = (data&(1<>16, offset&0x0000FFFF ); +} + +inline void CHexBuffer::printHexadecimalSmallOffset( char *buf, uint offset ) +{ + sprintf( buf, "%04x:%04x", offset>>16, offset&0x0000FFFF ); +} + +inline void CHexBuffer::printDecimalOffset( char *buf, uint offset ) +{ + sprintf( buf, "%010u", offset ); +} + +inline int CHexBuffer::lineSize( void ) +{ + return( mLayout.lineSize ); +} + +inline int CHexBuffer::lineHeight( void ) +{ + return( mFontHeight + mLayout.horzGridWidth ); +} + +inline int CHexBuffer::fontAscent( void ) +{ + return( mFontAscent ); +} + +inline int CHexBuffer::lineWidth( void ) +{ + return( mLineWidth ); +} + +inline int CHexBuffer::unitWidth( void ) +{ + return( mUnitWidth ); +} + +inline int CHexBuffer::numLines( void ) +{ + return( mNumLines ); +} + +inline int CHexBuffer::totalHeight( void ) +{ + return( mNumLines * (mFontHeight+mLayout.horzGridWidth) ); +} + +inline const QFont &CHexBuffer::font( void ) +{ + return( mFontInfo.font ); +} + +inline SCursor *CHexBuffer::textCursor( void ) +{ + return( &mCursor ); +} + +inline const QColor &CHexBuffer::backgroundColor( void ) +{ + return( documentPresent() == true ? mColor.textBg : mColor.inactiveBg ); +} + +inline int CHexBuffer::startX( void ) +{ + return( mStartX ); +} + +inline int CHexBuffer::startY( void ) +{ + return( mStartY ); +} + +inline void CHexBuffer::setStartX( int val ) +{ + mStartX = val; +} + +inline void CHexBuffer::setStartY( int val ) +{ + mStartY = val; +} + + + +#endif + diff --git a/khexedit/hexclipboard.cc b/khexedit/hexclipboard.cc new file mode 100644 index 0000000..0de70d6 --- /dev/null +++ b/khexedit/hexclipboard.cc @@ -0,0 +1,254 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +// +// This is a VERY crude implementation, which serves my requirements and +// nothing more. +// + + +#include +#include "hexclipboard.h" + + +static const uchar *base64EncodeTable( void ) +{ + static uchar table[64] = + { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', + }; + + return( table ); +} + +static const uchar *base64DecodeTable( void ) +{ + static uchar table[255]; + static bool init = false; + if( init == false ) + { + uint i; + for( i = 0; i < 255; i++ ) { table[i] = 0x80; } + for( i = 'A'; i <= 'Z'; i++ ) { table[i] = 0 + (i - 'A'); } + for( i = 'a'; i <= 'z'; i++ ) { table[i] = 26 + (i - 'a'); } + for( i = '0'; i <= '9'; i++ ) { table[i] = 52 + (i - '0'); } + table[(uchar)'+'] = 62; + table[(uchar)'/'] = 63; + table[(uchar)'='] = 0; + init = true; + } + return( table ); +} + + +static const char *mimeHeader( void ) +{ + static const char *data = + "Content-Type: application/octet-stream; " \ + "name=\"khexedit_copy\"\r\n" \ + "Content-Transfer-Encoding: base64\r\n\r\n"; + return( data ); +} + + + + + + + + +CHexClipboard::CHexClipboard( void ) +{ +} + + +CHexClipboard::~CHexClipboard( void ) +{ +} + + +bool CHexClipboard::encode( QByteArray &dst, QByteArray &src ) +{ + if( src.size() == 0 ) + { + return( false ); + } + + uint srcSize = src.size(); + uint mimeSize = strlen( mimeHeader() ); + uint lineSize = 72; + uint dstSize = (srcSize / 3 + (srcSize % 3 ? 1 : 0)) * 4; + dstSize += ((dstSize/lineSize) + 1)*2 + 1; + + dst.resize( dstSize + mimeSize + 1 ); + if( dst.isNull() == true ) + { + return( false ); + } + + unsigned char inBuf[3], outBuf[4]; + uint lineLen = 0; + + memcpy( dst.data(), mimeHeader(), mimeSize ); + uint j = mimeSize; + + + const uchar *table = base64EncodeTable(); + for( uint i=0; i < srcSize; i += 3 ) + { + memset( inBuf, 0, sizeof(inBuf) ); + uint n; + for( n=0; n < 3; n++ ) + { + if( i+n >= srcSize ) + { + break; + } + inBuf[n] = src[i+n]; + } + + if( n > 0 ) + { + outBuf[0] = table[ inBuf[0] >> 2 ]; + outBuf[1] = table[ ((inBuf[0] & 0x3) << 4) | (inBuf[1] >> 4) ]; + outBuf[2] = table[ ((inBuf[1] & 0xF) << 2) | (inBuf[2] >> 6) ]; + outBuf[3] = table[ inBuf[2] & 0x3F ]; + + if( n < 3 ) + { + outBuf[3] = '='; + if( n < 2 ) + { + outBuf[2] = '='; + } + } + + for( uint m=0; m<4; m++ ) + { + if( lineLen >= lineSize ) + { + dst[j++] = '\r'; + dst[j++] = '\n'; + lineLen = 0; + } + dst[j++] = outBuf[m]; + lineLen += 1; + } + } + } + dst[j++] = '\r'; + dst[j++] = '\n'; + dst[j++] = '\0'; + return( true ); +} + + + + +bool CHexClipboard::decode( QByteArray &dst, QString &src ) +{ + uint mimeSize = strlen( mimeHeader() ); + if( src.length() <= mimeSize ) + { + return( plainDecode( dst, src ) ); + } + + if( memcmp( src.ascii(), mimeHeader(), mimeSize ) != 0 ) + { + return( plainDecode( dst, src ) ); + } + + uint srcSize = src.length(); + uint dstSize = (srcSize * 3) / 4; + uchar srcBuf[4], valBuf[4], dstBuf[3]; + uint sumElement = 0; + + dst.resize( dstSize ); + if( dst.isNull() == true ) + { + return( plainDecode( dst, src ) ); + } + + uint i,j; + uint n = 0; + + const uchar *table = base64DecodeTable(); + for( i=mimeSize; i= srcSize ) + { + dst.truncate( sumElement ); + return( j > 0 ? false : true ); + } + + int c = src[i++].latin1(); + if( c <= ' ' ) + { + continue; + } + if( table[c] & 0x80 ) + { + return( plainDecode( dst, src ) ); + } + + srcBuf[j] = c; + valBuf[j] = table[c]; + j++; + } + + dstBuf[0] = (valBuf[0] << 2) | (valBuf[1] >> 4); + dstBuf[1] = (valBuf[1] << 4) | (valBuf[2] >> 2); + dstBuf[2] = (valBuf[2] << 6) | (valBuf[3]); + + uint numElement = srcBuf[2] == '=' ? 1 : (srcBuf[3] == '=' ? 2 : 3); + for( uint m=0; m < numElement; m++ ) + { + dst[n++] = dstBuf[m]; + } + sumElement += numElement; + + if( numElement < 3 ) + { + break; + } + } + + dst.truncate( sumElement ); + return( true ); +} + + +bool CHexClipboard::plainDecode( QByteArray &dst, QString &src ) +{ + dst.resize( src.length() ); + if( dst.isNull() == true ) + { + return( false ); + } + + for( uint i=0; i < src.length(); dst[i] = src[i].latin1(), i++ ); + return( true ); +} + diff --git a/khexedit/hexclipboard.h b/khexedit/hexclipboard.h new file mode 100644 index 0000000..9a7710d --- /dev/null +++ b/khexedit/hexclipboard.h @@ -0,0 +1,40 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_CLIPBOARD_H_ +#define _HEX_CLIPBOARD_H_ + +#include + +class CHexClipboard +{ + public: + CHexClipboard( void ); + ~CHexClipboard( void ); + + bool encode( QByteArray &dst, QByteArray &src ); + bool decode( QByteArray &dst, QString &src ); + + private: + bool plainDecode( QByteArray &dst, QString &src ); +}; + + +#endif diff --git a/khexedit/hexdrag.cc b/khexedit/hexdrag.cc new file mode 100644 index 0000000..d09b28d --- /dev/null +++ b/khexedit/hexdrag.cc @@ -0,0 +1,130 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include "hexdrag.h" +static const char *mediaString = "application/octet-stream"; + + +CHexDrag::CHexDrag( const QByteArray &data, QWidget *dragSource, + const char *name ) + :QDragObject(dragSource,name) +{ + setData( data ); + prepPixmap(); +} + + +CHexDrag::CHexDrag( QWidget *dragSource, const char *name ) + :QDragObject(dragSource,name) +{ + prepPixmap(); +} + + +void CHexDrag::setData( const QByteArray &data ) +{ + mData = data; +} + + + +void CHexDrag::prepPixmap(void) +{ + // + // Wont use it yet, + // + /* + KIconLoader &loader = *KGlobal::iconLoader(); + QPixmap pix = loader.loadIcon( "binary.xpm" ); + + QPoint hotspot( pix.width()-20,pix.height()/2 ); + setPixmap( pix, hotspot ); + */ +} + + +const char *CHexDrag::format( int i ) const +{ + if( i == 0 ) + { + return( mediaString ); + } + else + { + return( 0 ); + } + return( i == 0 ? mediaString : 0 ); +} + + +QByteArray CHexDrag::encodedData( const char *fmt ) const +{ + if( fmt != 0 ) + { + if( strcmp( fmt, mediaString) == 0 ) + { + return( mData ); + } + } + + QByteArray buf; + return( buf ); +} + + +bool CHexDrag::canDecode( const QMimeSource *e ) +{ + return( e->provides(mediaString) ); +} + + +bool CHexDrag::decode( const QMimeSource *e, QByteArray &dest ) +{ + dest = e->encodedData(mediaString); + return( dest.size() == 0 ? false : true ); + + // + // I get an + // "X Error: BadAtom (invalid Atom parameter) 5 + // Major opcode: 17" + // + // if I try to use the code below on a source that has been + // collected from QClipboard. It is the e->provides(mediaString) + // that fail (Qt-2.0). Sometimes it works :( + // + // printf("0: %s\n", e->format(0) ); No problem. + // printf("1: %s\n", e->format(1) ); Crash. + // + #if 0 + if( e->provides(mediaString) == true ) + { + dest = e->encodedData(mediaString); + return( true ); + } + else + { + return( false ); + } + #endif +} + + +#include "hexdrag.moc" diff --git a/khexedit/hexdrag.h b/khexedit/hexdrag.h new file mode 100644 index 0000000..b29b197 --- /dev/null +++ b/khexedit/hexdrag.h @@ -0,0 +1,54 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_DRAG_H_ +#define _HEX_DRAG_H_ + + +#include +#include + +class CHexDrag : public QDragObject +{ + Q_OBJECT + + public: + CHexDrag( const QByteArray &data, QWidget *dragSource = 0, + const char *name = 0 ); + CHexDrag( QWidget *dragSource = 0, const char *name = 0 ); + + void setData( const QByteArray &data ); + const char* format ( int i ) const; + QByteArray encodedData( const char *fmt ) const; + + + static bool canDecode( const QMimeSource *e ); + static bool decode( const QMimeSource *e, QByteArray &dest ); + + private: + void prepPixmap( void ); + + private: + QByteArray mData; + +}; + + +#endif diff --git a/khexedit/hexeditorwidget.cc b/khexedit/hexeditorwidget.cc new file mode 100644 index 0000000..16b62a4 --- /dev/null +++ b/khexedit/hexeditorwidget.cc @@ -0,0 +1,2443 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include +#include + +#undef Unsorted + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chartabledialog.h" +#include "converterdialog.h" +#include "dialog.h" +#include "exportdialog.h" +#include "fileinfodialog.h" +#include "hexeditorwidget.h" +#include "hexerror.h" +#include "optiondialog.h" +#include "printdialogpage.h" +#include "stringdialog.h" + + + + +CHexEditorWidget::CHexEditorWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + CHexBuffer *hexBuffer = new CHexBuffer; + if( hexBuffer == 0 ) { return; } + + mDocumentList.setAutoDelete( true ); + mDocumentList.append( hexBuffer ); + mUntitledCount = 1; + + mHexView = new CHexViewWidget( this, "hexview", hexBuffer ); + if( mHexView == 0 || mHexView->widgetValid() == false ) { return; } + + connect( mHexView, SIGNAL(pleaseOpenNewFile()), SLOT( newFile()) ); + connect( mHexView, SIGNAL(pleaseOpenFile( const QString&, bool, uint )), + SLOT( open(const QString&, bool, uint)) ); + connect( mHexView, SIGNAL(pleaseStepFile(bool)), SLOT( stepFile(bool)) ); + connect( kapp, SIGNAL( kdisplayFontChanged() ), SLOT( fontChanged() ) ); + connect( kapp, SIGNAL( kdisplayPaletteChanged() ),SLOT( paletteChanged()) ); + connect( mHexView, SIGNAL( layoutChanged( const SDisplayLayout & ) ), + SLOT( layoutChanged( const SDisplayLayout & ) ) ); + connect( mHexView, SIGNAL( inputModeChanged( const SDisplayInputMode & ) ), + this, SLOT( inputModeChanged( const SDisplayInputMode & ) ) ); + + mHexView->setFocus(); + setBackgroundColor( palette().active().base() ); + + mProgressBusy = false; + mGotoDialog = 0; + mFindDialog = 0; + mReplaceDialog = 0; + mInsertDialog = 0; + mFilterDialog = 0; + mOptionDialog = 0; + mStringDialog = 0; + mCharTableDialog = 0; + mFileInfoDialog = 0; + mExportDialog = 0; + mConverterDialog = 0; + mFindNavigatorDialog = 0; + mReplacePromptDialog = 0; +} + +CHexEditorWidget::~CHexEditorWidget( void ) +{ + delete mHexView; + delete mGotoDialog; + delete mFindDialog; + delete mReplaceDialog; + delete mInsertDialog; + delete mFilterDialog; + delete mOptionDialog; + delete mStringDialog; + delete mCharTableDialog; + delete mFileInfoDialog; + delete mExportDialog; + delete mConverterDialog; + delete mFindNavigatorDialog; + delete mReplacePromptDialog; +} + + +void CHexEditorWidget::initialize( void ) +{ + setColor( mDisplayState.color ); + setFont( mDisplayState.font ); + mHexView->setMisc( mDisplayState.misc ); + mHexView->setCursor( mDisplayState.cursor, false ); + mHexView->setLayout( mDisplayState.layout ); + mHexView->setInputMode( mDisplayState.input ); + mHexView->setInsertMode( mDisplayState.misc.insertMode ); +} + + +void CHexEditorWidget::writeConfiguration( KConfig &config ) +{ + SDisplayLayout &layout = mDisplayState.layout; + config.setGroup( "Display Options" ); + config.writeEntry( "PrimaryMode", layout.primaryModeString() ); + config.writeEntry( "SecondaryMode", layout.secondaryModeString() ); + config.writeEntry( "OffsetMode", layout.offsetModeString() ); + config.writeEntry( "OffsetVisible", layout.offsetVisible ); + config.writeEntry( "PrimaryUpperCase", layout.primaryUpperCase ); + config.writeEntry( "OffsetUpperCase", layout.offsetUpperCase ); + config.writeEntry( "LineSize", layout.lineSize ); + config.writeEntry( "ColumnSize", layout.columnSize ); + config.writeEntry( "LockLine", layout.lockLine ); + config.writeEntry( "LockColumn", layout.lockColumn ); + config.writeEntry( "ColumnCharSpace", layout.columnCharSpace ); + config.writeEntry( "ColumnSpacing", layout.columnSpacing ); + config.writeEntry( "SeparatorMarginWidth", layout.separatorMarginWidth ); + config.writeEntry( "EdgeMarginWidth", layout.edgeMarginWidth ); + config.writeEntry( "LeftSeparatorWidth", layout.leftSeparatorWidth ); + config.writeEntry( "RightSeparatorWidth", layout.rightSeparatorWidth ); + config.writeEntry( "GridMode", layout.gridModeString() ); + + SDisplayLine &line = mDisplayState.line; + config.setGroup( "Line Size" ); + config.writeEntry( "Hexadecimal",line.lineSize[SDisplayLine::hexadecimal] ); + config.writeEntry( "Decimal", line.lineSize[SDisplayLine::decimal] ); + config.writeEntry( "Octal", line.lineSize[SDisplayLine::octal] ); + config.writeEntry( "Binary", line.lineSize[SDisplayLine::binary] ); + config.writeEntry( "TextOnly", line.lineSize[SDisplayLine::textOnly] ); + config.setGroup( "Column Size" ); + config.writeEntry( "Hexadecimal",line.columnSize[SDisplayLine::hexadecimal]); + config.writeEntry( "Decimal", line.columnSize[SDisplayLine::decimal] ); + config.writeEntry( "Octal", line.columnSize[SDisplayLine::octal] ); + config.writeEntry( "Binary", line.columnSize[SDisplayLine::binary] ); + config.writeEntry( "TextOnly", line.columnSize[SDisplayLine::textOnly] ); + + SDisplayColor &color = mDisplayState.color; + config.setGroup( "Display Colors" ); + config.writeEntry( "UseSystemColor", color.useSystemColor ); + config.writeEntry( "TextBg", color.textBg ); + config.writeEntry( "SecondTextBg", color.secondTextBg ); + config.writeEntry( "OffsetBg", color.offsetBg ); + config.writeEntry( "InactiveBg", color.inactiveBg ); + config.writeEntry( "PrimaryFg1", color.primaryFg[0] ); + config.writeEntry( "PrimaryFg2", color.primaryFg[1] ); + config.writeEntry( "OffsetFg", color.offsetFg ); + config.writeEntry( "SecondaryFg", color.secondaryFg ); + config.writeEntry( "MarkBg", color.markBg ); + config.writeEntry( "MarkFg", color.markFg ); + config.writeEntry( "LeftSeparatorFg", color.leftSeparatorFg ); + config.writeEntry( "RightSeparatorFg", color.leftSeparatorFg ); + config.writeEntry( "NonPrintFg", color.nonPrintFg ); + config.writeEntry( "CursorBg", color.cursorBg ); + config.writeEntry( "CursorFg", color.cursorFg ); + config.writeEntry( "GridFg", color.gridFg ); + config.writeEntry( "BookmarkBg", color.bookmarkBg ); + config.writeEntry( "BookmarkFg", color.bookmarkFg ); + + SDisplayFont &font = mDisplayState.font; + config.setGroup( "Display Font" ); + config.writeEntry( "UseSystemFont", font.useSystemFont ); + config.writeEntry( "LocalFont", font.localFont ); + config.writeEntry( "NonPrintChar", font.nonPrintChar.unicode() ); + + SDisplayCursor &cursor = mDisplayState.cursor; + config.setGroup( "Display Cursor" ); + config.writeEntry( "NeverBlink", cursor.alwaysVisible ); + config.writeEntry( "AlwaysBlockShape", cursor.alwaysBlockShape ); + config.writeEntry( "ThickInsertShape", cursor.thickInsertShape ); + config.writeEntry( "FocusMode", cursor.focusModeString() ); + config.writeEntry( "Interval", cursor.interval ); + + SDisplayMisc &misc = mDisplayState.misc; + config.setGroup( "Display Misc" ); + config.writeEntry( "UndoLevel", misc.undoLevel ); + config.writeEntry( "OpenFile", misc.openFileString() ); + config.writeEntry( "InputSound", misc.inputSound ); + config.writeEntry( "FatalSound", misc.fatalSound ); + config.writeEntry( "AutoCopyToClipboard", misc.autoCopyToClipboard ); + config.writeEntry( "InsertMode", misc.insertMode ); + config.writeEntry( "WriteProtect", misc.writeProtect ); + config.writeEntry( "ConfirmWrap", misc.confirmWrap ); + config.writeEntry( "CursorJump", misc.cursorJump ); + config.writeEntry( "MakeBackup", misc.makeBackup ); + config.writeEntry( "ConfirmThreshold", misc.confirmThreshold ); + config.writeEntry( "ThresholdValue", misc.thresholdValue ); + config.writeEntry( "DiscardRecent", misc.discardRecent ); + config.writeEntry( "GotoOnStartup", misc.gotoOnStartup ); + config.writeEntry( "GotoOnReload", misc.gotoOnReload ); + config.writeEntry( "ShowBookmarkInOffsetColumn", misc.bookmarkOffsetColumn ); + config.writeEntry( "ShowBookmarkInEditor", misc.bookmarkEditor ); + + if( mExportDialog != 0 ) + { + mExportDialog->writeConfiguration(); + } +} + +void CHexEditorWidget::readConfiguration( KConfig &config ) +{ + SDisplayLayout &layout = mDisplayState.layout; + config.setGroup( "Display Options" ); + layout.setPrimaryMode( config.readEntry("PrimaryMode") ); + layout.setSecondaryMode( config.readEntry("SecondaryMode") ); + layout.setOffsetMode( config.readEntry("OffsetMode") ); + layout.offsetVisible = config.readBoolEntry( + "OffsetVisible", layout.offsetVisible ); + layout.primaryUpperCase = config.readBoolEntry( + "PrimaryUpperCase", layout.primaryUpperCase ); + layout.offsetUpperCase = config.readBoolEntry( + "OffsetUpperCase", layout.offsetUpperCase ); + layout.lineSize = config.readNumEntry( + "LineSize", layout.lineSize ); + layout.columnSize = config.readNumEntry( + "ColumnSize", layout.columnSize ); + layout.lockLine = config.readBoolEntry( + "LockLine", layout.lockLine ); + layout.lockColumn = config.readBoolEntry( + "LockColumn", layout.lockColumn ); + layout.columnCharSpace = config.readBoolEntry( + "ColumnCharSpace", layout.columnCharSpace ); + layout.columnSpacing = config.readNumEntry( + "ColumnSpacing", layout.columnSpacing ); + layout.separatorMarginWidth = config.readNumEntry( + "SeparatorMarginWidth", layout.separatorMarginWidth ); + layout.edgeMarginWidth = config.readNumEntry( + "EdgeMarginWidth", layout.edgeMarginWidth ); + layout.leftSeparatorWidth = config.readNumEntry( + "LeftSeparatorWidth", layout.leftSeparatorWidth ); + layout.rightSeparatorWidth = config.readNumEntry( + "RightSeparatorWidth", layout.rightSeparatorWidth ); + layout.setGridMode( config.readEntry("GridMode") ); + + SDisplayLine &line = mDisplayState.line; + config.setGroup( "Line Size" ); + line.lineSize[SDisplayLine::hexadecimal] = config.readUnsignedNumEntry( + "Hexadecimal", line.lineSize[SDisplayLine::hexadecimal] ); + line.lineSize[SDisplayLine::decimal] = config.readUnsignedNumEntry( + "Decimal", line.lineSize[SDisplayLine::decimal] ); + line.lineSize[SDisplayLine::octal] = config.readUnsignedNumEntry( + "Octal", line.lineSize[SDisplayLine::octal] ); + line.lineSize[SDisplayLine::binary] = config.readUnsignedNumEntry( + "Binary", line.lineSize[SDisplayLine::binary] ); + line.lineSize[SDisplayLine::textOnly] = config.readUnsignedNumEntry( + "TextOnly", line.lineSize[SDisplayLine::textOnly] ); + config.setGroup( "Column Size" ); + line.columnSize[SDisplayLine::hexadecimal] = config.readUnsignedNumEntry( + "Hexadecimal", line.columnSize[SDisplayLine::hexadecimal] ); + line.columnSize[SDisplayLine::decimal] = config.readUnsignedNumEntry( + "Decimal", line.columnSize[SDisplayLine::decimal] ); + line.columnSize[SDisplayLine::octal] = config.readUnsignedNumEntry( + "Octal", line.columnSize[SDisplayLine::octal] ); + line.columnSize[SDisplayLine::binary] = config.readUnsignedNumEntry( + "Binary", line.columnSize[SDisplayLine::binary] ); + line.columnSize[SDisplayLine::textOnly] = config.readUnsignedNumEntry( + "TextOnly", line.columnSize[SDisplayLine::textOnly] ); + + SDisplayFont &font = mDisplayState.font; + config.setGroup( "Display Font" ); + font.useSystemFont = config.readBoolEntry( + "UseSystemFont", true ); + font.localFont = config.readFontEntry( + "LocalFont", &font.localFont ); + font.nonPrintChar = config.readNumEntry( + "NonPrintChar", font.nonPrintChar ); + + SDisplayColor &color = mDisplayState.color; + config.setGroup( "Display Colors" ); + color.useSystemColor = config.readBoolEntry( + "UseSystemColor", color.useSystemColor ); + color.textBg = config.readColorEntry( + "TextBg", &color.textBg ); + color.secondTextBg = config.readColorEntry( + "SecondTextBg", &color.secondTextBg ); + color.offsetBg = config.readColorEntry( + "OffsetBg", &color.offsetBg ); + color.inactiveBg = config.readColorEntry( + "InactiveBg", &color.inactiveBg ); + color.primaryFg[0] = config.readColorEntry( + "PrimaryFg1", &color.primaryFg[0] ); + color.primaryFg[1] = config.readColorEntry( + "PrimaryFg2", &color.primaryFg[1] ); + color.offsetFg = config.readColorEntry( + "OffsetFg", &color.offsetFg ); + color.secondaryFg = config.readColorEntry( + "SecondaryFg", &color.secondaryFg ); + color.markBg = config.readColorEntry( + "MarkBg", &color.markBg ); + color.markFg = config.readColorEntry( + "MarkFg", &color.markFg ); + color.cursorBg = config.readColorEntry( + "CursorBg", &color.cursorBg ); + color.cursorFg = config.readColorEntry( + "CursorFg", &color.cursorFg ); + color.leftSeparatorFg = config.readColorEntry( + "LeftSeparatorFg", &color.leftSeparatorFg ); + color.rightSeparatorFg = config.readColorEntry( + "RightSeparatorFg", &color.rightSeparatorFg ); + color.nonPrintFg = config.readColorEntry( + "NonPrintFg", &color.nonPrintFg ); + color.gridFg = config.readColorEntry( + "GridFg", &color.gridFg ); + color.bookmarkBg = config.readColorEntry( + "BookmarkBg", &color.bookmarkBg ); + color.bookmarkFg = config.readColorEntry( + "BookmarkFg", &color.bookmarkFg ); + + SDisplayCursor &cursor = mDisplayState.cursor; + config.setGroup( "Display Cursor" ); + cursor.alwaysVisible = config.readBoolEntry( + "NeverBlink", cursor.alwaysVisible ); + cursor.alwaysBlockShape = config.readBoolEntry( + "AlwaysBlockShape", cursor.alwaysBlockShape ); + cursor.thickInsertShape = config.readBoolEntry( + "ThickInsertShape", cursor.thickInsertShape ); + cursor.setFocusMode( config.readEntry("FocusMode") ); + cursor.interval = config.readNumEntry( + "Interval", cursor.interval ); + + SDisplayMisc &misc = mDisplayState.misc; + config.setGroup( "Display Misc" ); + misc.undoLevel = config.readNumEntry( + "UndoLevel", misc.undoLevel ); + misc.setOpenFile( config.readEntry("OpenFile") ); + misc.inputSound = config.readBoolEntry( + "InputSound", misc.inputSound ); + misc.fatalSound = config.readBoolEntry( + "FatalSound", misc.fatalSound ); + misc.autoCopyToClipboard = config.readBoolEntry( + "AutoCopyToClipboard", misc.autoCopyToClipboard ); + misc.insertMode = config.readBoolEntry( + "InsertMode", misc.insertMode ); + misc.writeProtect = config.readBoolEntry( + "WriteProtect", misc.writeProtect ); + misc.confirmWrap = config.readBoolEntry( + "ConfirmWrap", misc.confirmWrap ); + misc.cursorJump = config.readBoolEntry( + "CursorJump", misc.cursorJump ); + misc.makeBackup = config.readBoolEntry( + "MakeBackup", misc.makeBackup ); + misc.confirmThreshold = config.readBoolEntry( + "ConfirmThreshold", misc.confirmThreshold ); + misc.thresholdValue = config.readNumEntry( + "ThresholdValue", misc.thresholdValue ); + misc.discardRecent = config.readBoolEntry( + "DiscardRecent", misc.discardRecent ); + misc.gotoOnStartup = config.readBoolEntry( + "GotoOnStartup", misc.gotoOnStartup ); + misc.gotoOnReload = config.readBoolEntry( + "GotoOnReload", misc.gotoOnReload ); + misc.bookmarkOffsetColumn = config.readBoolEntry( + "ShowBookmarkInOffsetColumn", misc.bookmarkOffsetColumn ); + misc.bookmarkEditor = config.readBoolEntry( + "ShowBookmarkInEditor", misc.bookmarkEditor ); +} + + + +void CHexEditorWidget::resizeEvent( QResizeEvent *e ) +{ + mHexView->resize( e->size().width(), e->size().height() ); +} + + +void CHexEditorWidget::fontChanged( void ) +{ + if( mDisplayState.font.useSystemFont == true ) + { + setFont( mDisplayState.font ); + } +} + +void CHexEditorWidget::paletteChanged( void ) +{ + setColor( mDisplayState.color ); +} + +void CHexEditorWidget::layoutChanged( const SDisplayLayout &/*layout*/ ) +{ + //mDisplayState.layout = layout; +} + +void CHexEditorWidget::inputModeChanged( const SDisplayInputMode &input ) +{ + mDisplayState.input = input; +} + + +void CHexEditorWidget::setLineSize(const SDisplayLine &line ) +{ + mDisplayState.line = line; +} + +void CHexEditorWidget::setLayout( const SDisplayLayout &layout ) +{ + // + // We only set the values that can be modified by the dialog + // + mDisplayState.layout.lockLine = layout.lockLine; + mDisplayState.layout.lockColumn = layout.lockColumn; + mDisplayState.layout.leftSeparatorWidth = layout.leftSeparatorWidth; + mDisplayState.layout.rightSeparatorWidth = layout.rightSeparatorWidth; + mDisplayState.layout.separatorMarginWidth = layout.separatorMarginWidth; + mDisplayState.layout.edgeMarginWidth = layout.edgeMarginWidth; + mDisplayState.layout.columnCharSpace = layout.columnCharSpace; + mDisplayState.layout.columnSpacing = layout.columnSpacing; + mDisplayState.layout.horzGridWidth = layout.horzGridWidth; + mDisplayState.layout.vertGridWidth = layout.vertGridWidth; + + // + // Select the line and column sizes we shall use now. + // + SDisplayLayout &l = mDisplayState.layout; + l.lineSize = mDisplayState.line.lineSize[ l.primaryMode ]; + l.columnSize = mDisplayState.line.columnSize[ l.primaryMode ]; + + mHexView->setLayout( mDisplayState.layout ); +} + +void CHexEditorWidget::setCursor( const SDisplayCursor &cursor ) +{ + mDisplayState.cursor = cursor; + mHexView->setCursor( mDisplayState.cursor, true ); +} + +void CHexEditorWidget::setColor( const SDisplayColor &color ) +{ + mDisplayState.color = color; + + // + // The selection colors can not be chosen. + // + mDisplayState.color.selectBg = kapp->palette().active().highlight(); + mDisplayState.color.selectFg = kapp->palette().active().highlightedText(); + + if( mDisplayState.color.useSystemColor == true ) + { + SDisplayColor c = mDisplayState.color; + c.textBg = kapp->palette().active().base(); + c.secondTextBg = kapp->palette().active().base(); + c.offsetBg = kapp->palette().active().base(); + c.inactiveBg = kapp->palette().active().base(); + c.primaryFg[0] = kapp->palette().active().text(); + c.primaryFg[1] = kapp->palette().active().text(); + c.nonPrintFg = kapp->palette().active().text(); + c.offsetFg = kapp->palette().active().text(); + c.secondaryFg = kapp->palette().active().text(); + c.leftSeparatorFg = kapp->palette().active().text(); + c.rightSeparatorFg = kapp->palette().active().text(); + c.cursorBg = kapp->palette().active().text(); + c.cursorFg = kapp->palette().active().base(); + c.gridFg = kapp->palette().active().text(); + SDisplayColor defaultColor; + c.bookmarkBg = defaultColor.bookmarkBg; + c.bookmarkFg = defaultColor.bookmarkFg; + + mHexView->setColor( c, true ); + } + else + { + mHexView->setColor( mDisplayState.color, true ); + } +} + + +void CHexEditorWidget::setFont( const SDisplayFont &font ) +{ + mDisplayState.font = font; + + SDisplayFontInfo fontInfo; + if( mDisplayState.font.useSystemFont == true ) + { + fontInfo.font = KGlobalSettings::fixedFont(); + } + else + { + fontInfo.font = mDisplayState.font.localFont; + } + fontInfo.nonPrintChar = mDisplayState.font.nonPrintChar; + mHexView->setFont( fontInfo, true ); +} + +void CHexEditorWidget::setMisc( const SDisplayMisc &misc ) +{ + mDisplayState.misc = misc; + mHexView->setMisc( mDisplayState.misc ); +} + + + +void CHexEditorWidget::setHexadecimalMode( void ) +{ + layout().primaryMode = SDisplayLayout::hexadecimal; + layout().lineSize = line().lineSize[ SDisplayLine::hexadecimal ]; + layout().columnSize = line().columnSize[ SDisplayLine::hexadecimal ]; + mHexView->setLayout( layout() ); +} + + +void CHexEditorWidget::setDecimalMode( void ) +{ + layout().primaryMode = SDisplayLayout::decimal; + layout().lineSize = line().lineSize[ SDisplayLine::decimal ]; + layout().columnSize = line().columnSize[ SDisplayLine::decimal ]; + mHexView->setLayout( layout() ); +} + + +void CHexEditorWidget::setOctalMode( void ) +{ + layout().primaryMode = SDisplayLayout::octal; + layout().lineSize = line().lineSize[ SDisplayLine::octal ]; + layout().columnSize = line().columnSize[ SDisplayLine::octal ]; + mHexView->setLayout( layout() ); +} + + +void CHexEditorWidget::setBinaryMode( void ) +{ + layout().primaryMode = SDisplayLayout::binary; + layout().lineSize = line().lineSize[ SDisplayLine::binary ]; + layout().columnSize = line().columnSize[ SDisplayLine::binary ]; + mHexView->setLayout( layout() ); +} + + +void CHexEditorWidget::setTextMode( void ) +{ + layout().primaryMode = SDisplayLayout::textOnly; + layout().lineSize = line().lineSize[ SDisplayLine::textOnly ]; + layout().columnSize = line().columnSize[ SDisplayLine::textOnly ]; + mHexView->setLayout( layout() ); +} + + + +void CHexEditorWidget::saveWorkingDirectory( const QString &url ) +{ + if( url.isEmpty() == true ) + { + return; + } + + int index = url.findRev( '/' ); + if( index != -1 ) + { + mWorkDir = url.left( index+1 ); + } +} + + + +void CHexEditorWidget::newFile( void ) +{ + if( busy( true ) == true ) + { + return; + } + + QString url = i18n("Untitled %1").arg( mUntitledCount ); + + // + // If the url is already present in the document list (should not happen), + // then this document is "raised". + // + bool success = selectDocument( url, false ); + if( success == true ) + { + return; + } + + // + // Prepare a new buffer we can load the document into + // + success = createBuffer(); + if( success == false ) + { + return; + } + + int errCode = mHexView->newFile( url ); + if( errCode != Err_Success ) + { + QString msg = i18n("Unable to create new document."); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Operation Failed") ); + return; + } + + mUntitledCount += 1; +} + + + + +void CHexEditorWidget::newFile( const QByteArray &data ) +{ + newFile(); + mHexView->append( data ); +} + + + + +void CHexEditorWidget::open() +{ + KURL file = KFileDialog::getOpenURL( mWorkDir, "*" ,topLevelWidget() ); + + if( file.isEmpty() ) + return; + + QString url = file.url(); + + saveWorkingDirectory( url ); + + if( busy( true ) ) + return; + + // + // If the url is already present in the document list, then this + // document is "raised". + // + if( selectDocument( url, true ) ) + return; + + // + // Prepare a new buffer we can load the document into + // + if( !createBuffer() ) + return; + + int errCode = readURL( file, false ); + if( errCode != Err_Success ) + { + emit errorLoadFile( url ); + removeBuffer(); + } + else if( errCode == Err_Success ) + { + defaultWriteProtection(); + } +} + + + +void CHexEditorWidget::open( const QString &url, bool reloadWhenChanged, + uint offset ) +{ + if( busy( true ) == true ) + { + return; + } + + // + // If the url is already present in the document list, then this + // document is "raised". + // + bool success = selectDocument( url, reloadWhenChanged ); + if( success == true ) + { + return; + } + + // + // Prepare a new buffer we can load the document into + // + success = createBuffer(); + if( success == false ) + { + return; + } + + int errCode = readURL( url, false ); + if( errCode != Err_Success ) + { + emit errorLoadFile( url ); + removeBuffer(); + } + else if( errCode == Err_Success ) + { + mHexView->gotoOffset( offset ); + defaultWriteProtection(); + } +} + + +void CHexEditorWidget::stepFile( bool next ) +{ + // + // The buffer list is is reverse when compared with the visible + // document list in the menu so I toggle the flag. + // + next = next == true ? false : true; + + CHexBuffer *hexBuffer = documentItem( mHexView->url(), next ); + if( hexBuffer == 0 ) + { + return; + } + + mHexView->setBuffer( hexBuffer ); +} + + + + + +bool CHexEditorWidget::isOpen( const QString &url, uint &offset ) +{ + CHexBuffer *hexBuffer = documentItem( url ); + if( hexBuffer == 0 ) + { + return( false ); + } + offset = hexBuffer->cursorOffset(); + return( true ); +} + + +bool CHexEditorWidget::selectDocument( const QString &url, + bool reloadWhenChanged ) +{ + CHexBuffer *hexBuffer = documentItem( url ); + if( hexBuffer == 0 ) + { + return( false ); + } + + mHexView->setBuffer( hexBuffer ); + + if( reloadWhenChanged == true && mHexView->urlValid() == true ) + { + if( modifiedByAlien( mHexView->url() ) == true ) + { + reload(); + } + } + + return( true ); +} + + +void CHexEditorWidget::insertFile( void ) +{ + KFileDialog fdlg(mWorkDir, QString::null, topLevelWidget(), 0, TRUE); + fdlg.setOperationMode( KFileDialog::Opening ); + fdlg.okButton()->setGuiItem( KStdGuiItem::insert() ); + fdlg.setCaption(i18n("Insert File")); + + if (!fdlg.exec()) return; + KURL file = fdlg.selectedURL(); + + if( file.isEmpty() ) + return; + + if( !file.isLocalFile() ) + { + KMessageBox::sorry( this, i18n( "Only local files are currently supported." ) ); + return; + } + + QString url = file.path(); + + saveWorkingDirectory( url ); + + if( busy( true ) ) + return; + + readURL( url, true ); +} + + + +void CHexEditorWidget::stop( void ) +{ + mProgressStop = mProgressBusy; +} + + +bool CHexEditorWidget::close( void ) +{ + if( busy( true ) == true ) + { + return( false ); + } + + if( querySave() == false ) + { + return( false ); + } + + removeBuffer(); + return( true ); +} + + + + +bool CHexEditorWidget::closeAll( void ) +{ + if( busy( true ) == true ) + { + return( false ); + } + + while( mDocumentList.count() > 0 ) + { + CHexBuffer *buf; + for( buf = mDocumentList.first(); buf != 0; buf = mDocumentList.next() ) + { + // + // We select the buffer we are about to close because it will + // the become visible, and because 'close()' works on the current + // buffer. + // + mHexView->setBuffer( buf ); + if( close() == false ) + { + return( false ); + } + } + + // + // The document list will always contain at least one element because + // the hexview widget needs a hexbuffer to work. If this hexbuffer is + // not valid, then all files have been closed. + // + if( mDocumentList.count() == 1 && mHexView->documentPresent() == false ) + { + break; + } + } + + return( true ); +} + + + +bool CHexEditorWidget::querySave( void ) +{ + if( mHexView->modified() == false ) + { + return( true ); + } + + QString msg = i18n("" + "The current document has been modified.\n" + "Do you want to save it?" ); + int reply = KMessageBox::warningYesNoCancel( topLevelWidget(), msg, QString::null, KStdGuiItem::save(), KStdGuiItem::discard() ); + if( reply == KMessageBox::Yes ) + { + return( save() ); + } + else if( reply == KMessageBox::No ) + { + return( true ); + } + else + { + return( false ); + } +} + + +bool CHexEditorWidget::backup( void ) +{ + if( mHexView->documentPresent() == false || mHexView->urlValid() == false ) + { + return( false ); + } + + KURL kurl( mHexView->url() ); + if( kurl.isLocalFile() == false ) + { + return( false ); + } + + const QString currentName = kurl.path(); + QString backupName = currentName + '~'; + + int errCode = rename( currentName.latin1(), backupName.latin1() ); + if( errCode != 0 ) + { + return( false ); + } + + + return( true ); +} + + + +// +// Returns false if operation was canceled +// +bool CHexEditorWidget::save( void ) +{ + if( mHexView->documentPresent() == false ) + { + return( true ); + } + + if( mHexView->urlValid() == false ) + { + return( saveAs() ); + } + else + { + if( modifiedByAlien( mHexView->url() ) == true ) + { + QString msg = i18n("" + "Current document has been changed on disk.\n" + "If you save now, those changes will be lost.\n" + "Proceed?" ); + int reply = KMessageBox::warningYesNoCancel( topLevelWidget(), msg, + i18n("Save"), KStdGuiItem::save(), KStdGuiItem::discard() ); + if( reply == KMessageBox::No || reply == KMessageBox::Cancel ) + { + return( reply == KMessageBox::No ? true : false ); + } + } + + if( mDisplayState.misc.makeBackup == true ) + { + backup(); + } + writeURL( mHexView->url() ); + } + + return( true ); +} + + +// +// Returns false if operation was canceled +// +bool CHexEditorWidget::saveAs( void ) +{ + if( mHexView->documentPresent() == false ) + { + return( true ); + } + + KURL url; + while( 1 ) + { + url = KFileDialog::getSaveURL( mHexView->url(), "*", this ); + if( url.isEmpty() == true ) + { + return( false ); + } + else + { + saveWorkingDirectory( url.url() ); + } + + if( url.isLocalFile() ) + { + QString name( url.path() ); + QFileInfo info( name ); + + if( info.exists() ) + { + QString msg = i18n("" + "A document with this name already exists.\n" + "Do you want to overwrite it?" ); + int reply = KMessageBox::warningContinueCancel( topLevelWidget(), msg, + i18n("Save As"), i18n("Overwrite") ); + if( reply == KMessageBox::Continue ) + break; + } + else + break; + } + } + + QString symbolicName( url.url() ); +// KURL::decode( symbolicName ); + + mHexView->setUrl( symbolicName ); + writeURL( mHexView->url() ); + return( true ); +} + + + +void CHexEditorWidget::reload( void ) +{ + if( mHexView->documentPresent() == false ) + { + return; + } + + if( busy( true ) == true ) + { + return; + } + + if( mHexView->urlValid() == false ) + { + QString msg = i18n( "The current document does not exist on the disk." ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Reload") ); + return; + } + + if( mHexView->modified() == true ) + { + QString msg; + if( modifiedByAlien( mHexView->url() ) == true ) + { + msg = i18n( "The current document has changed on the disk and " + "also contains unsaved modifications.\n" + "If you reload now, the modifications will be lost." ); + } + else + { + msg = i18n( "The current document contains unsaved modifications.\n" + "If you reload now, the modifications will be lost." ); + } + + int reply = KMessageBox::warningContinueCancel(topLevelWidget(),msg,i18n("Reload"), i18n("&Reload")); + if( reply != KMessageBox::Continue ) + { + return; + } + } + + QString url( mHexView->url() ); + uint offset = mHexView->offset(); + + //mHexView->closeFile(); + int errCode = readURL( url, false ); + if( errCode == Err_Success && gotoReloadOffset() == true ) + { + mHexView->gotoOffset( offset ); + } + +} + + +void CHexEditorWidget::print( void ) +{ + CHexPrinter prt; + + prt.addDialogPage( new LayoutDialogPage() ); + + prt.setPageSelection( KPrinter::SystemSide ); + prt.setFullPage( true ); // I use my own marings + + // FIXME: Make a better header for the printingdialog + if (prt.setup(topLevelWidget(), i18n("Print Hex-Document"))) + { + prt.setTopMarginMM( prt.option("kde-khexedit-topmarginmm").toInt() ); + prt.setBottomMarginMM( prt.option("kde-khexedit-bottommarginmm").toInt() ); + prt.setLeftMarginMM( prt.option("kde-khexedit-leftmarginmm").toInt() ); + prt.setRightMarginMM( prt.option("kde-khexedit-rightmarginmm").toInt() ); + + prt.setPageHeader( (prt.option("kde-khexedit-headercheck") == "true"), + prt.option("kde-khexedit-headercombo0").toInt(), + prt.option("kde-khexedit-headercombo1").toInt(), + prt.option("kde-khexedit-headercombo2").toInt(), + prt.option("kde-khexedit-headercombo3").toInt() ); + + prt.setPageFooter( (prt.option("kde-khexedit-footercheck") == "true"), + prt.option("kde-khexedit-footercombo0").toInt(), + prt.option("kde-khexedit-footercombo1").toInt(), + prt.option("kde-khexedit-footercombo2").toInt(), + prt.option("kde-khexedit-footercombo3").toInt() ); + + printPostscript(prt); + } + +} + + + + +void CHexEditorWidget::printPostscript( CHexPrinter &printer ) +{ + if( confirmPrintPageNumber( printer ) == false ) + { + return; + } + + // + // No i18n() on this one! + // Constants come from config.h + // + QString creator( PACKAGE ); + creator += " "; + creator += VERSION; + + printer.setCreator( creator ); + + int errCode = prepareProgressData( pg_print ); + if( errCode == Err_Success ) + { + errCode = mHexView->print( printer, mProgressData ); + } + + QString msg = i18n("Could not print data.\n"); + msg += hexError( errCode ); + + if( errCode != Err_Success ) + { + KMessageBox::sorry( topLevelWidget(), msg, i18n("Print") ); + } +} + + +bool CHexEditorWidget::confirmPrintPageNumber( CHexPrinter &printer ) +{ + if( mDisplayState.misc.confirmThreshold == true ) + { + uint numPage = mHexView->numPage( printer ); + printer.setMinMax( 1, numPage ); + uint numPageSelected = printer.pageList().count(); + + if( numPageSelected > mDisplayState.misc.thresholdValue ) + { + QString msg = i18n( + "Print threshold exceeded.
" + "You are about to print one page.
" + "Proceed?
", + "Print threshold exceeded.
" + "You are about to print %n pages.
" + "Proceed?
", + numPageSelected ); + int reply = KMessageBox::warningYesNo( topLevelWidget(), msg, + i18n("Print"), KStdGuiItem::print(), KStdGuiItem::cancel() ); + if( reply != KMessageBox::Continue ) + { + return( false ); + } + } + } + + return( true ); +} + + +void CHexEditorWidget::exportDialog( void ) +{ + if( mExportDialog == 0 ) + { + mExportDialog = new CExportDialog( topLevelWidget(), 0, false ); + if( mExportDialog == 0 ) { return; } + connect( mExportDialog, SIGNAL( exportText(const SExportText &)), + this, SLOT( exportText( const SExportText &)) ); + connect( mExportDialog, SIGNAL( exportHtml(const SExportHtml &)), + this, SLOT( exportHtml( const SExportHtml &)) ); + connect( mExportDialog, SIGNAL( exportCArray(const SExportCArray &)), + this, SLOT( exportCArray( const SExportCArray &)) ); + } + mExportDialog->show(); +} + + + +void CHexEditorWidget::exportText( const SExportText &ex ) +{ + int errCode = prepareProgressData( pg_export ); + if( errCode == Err_Success ) + { + errCode = mHexView->exportText( ex, mProgressData ); + } + + if( errCode != Err_Success ) + { + QString msg = i18n("Unable to export data.\n"); + msg += hexError( errCode ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Export") ); + } +} + + +void CHexEditorWidget::exportHtml( const SExportHtml &ex ) +{ + int errCode = prepareProgressData( pg_export ); + if( errCode == Err_Success ) + { + errCode = mHexView->exportHtml( ex, mProgressData ); + } + + if( errCode != Err_Success ) + { + QString msg = i18n("Unable to export data.\n"); + msg += hexError( errCode ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Export") ); + } +} + + +void CHexEditorWidget::exportCArray( const SExportCArray &ex ) +{ + int errCode = prepareProgressData( pg_export ); + if( errCode == Err_Success ) + { + errCode = mHexView->exportCArray( ex, mProgressData ); + } + + if( errCode != Err_Success ) + { + QString msg = i18n("Unable to export data.\n"); + msg += hexError( errCode ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Export") ); + } +} + + +void CHexEditorWidget::encode( CConversion::EMode mode ) +{ + if( mHexView->losslessEncoding( mode ) == false ) + { + QString msg = i18n("" + "The encoding you have selected is not reversible.\n" + "If you revert to the original encoding later, there is no " + "guarantee that the data can be restored to the original state."); + int reply = KMessageBox::warningContinueCancel( topLevelWidget(), msg, + i18n("Encode"), i18n("&Encode")); + if( reply != KMessageBox::Continue ) + { + // Restore correct menu setting + mHexView->reportEncoding(); + return; + } + } + + int errCode = prepareProgressData( pg_encode ); + if( errCode == Err_Success ) + { + errCode = mHexView->setEncoding( mode, mProgressData ); + } + + if( errCode != Err_Success ) + { + QString msg = i18n("Could not encode data.\n"); + msg += hexError( errCode ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Encode") ); + } +} + +void CHexEditorWidget::undo( void ) +{ + mHexView->undo(); +} + +void CHexEditorWidget::redo( void ) +{ + mHexView->redo(); +} + +void CHexEditorWidget::toggleWriteProtection( void ) +{ + mDisplayState.input.readOnly = mDisplayState.input.readOnly == true ? + false : true; + mHexView->setInputMode( mDisplayState.input ); +} + +void CHexEditorWidget::defaultWriteProtection( void ) +{ + mDisplayState.input.readOnly = mDisplayState.misc.writeProtect; + mHexView->setInputMode( mDisplayState.input ); +} + +void CHexEditorWidget::toggleResizeLock( void ) +{ + mDisplayState.input.allowResize = mDisplayState.input.allowResize == true ? + false : true; + mHexView->setInputMode( mDisplayState.input ); +} + +void CHexEditorWidget::setResizeLock( bool state ) +{ + mDisplayState.input.allowResize = state; + mHexView->setInputMode( mDisplayState.input ); +} + +void CHexEditorWidget::enableInputLock( bool inputLock ) +{ + mDisplayState.input.inputLock = inputLock; + mHexView->setInputMode( mDisplayState.input ); +} + +void CHexEditorWidget::toggleOffsetColumnVisibility( void ) +{ + layout().offsetVisible = layout().offsetVisible == true ? false : true; + mHexView->setLayout( layout() ); +} + +void CHexEditorWidget::toggleTextColumnVisibility( void ) +{ + layout().secondaryMode = layout().secondaryMode == SDisplayLayout::hide ? + SDisplayLayout::textOnly : SDisplayLayout::hide; + mHexView->setLayout( layout() ); +} + +void CHexEditorWidget::toggleOffsetAsDecimal( void ) +{ + layout().offsetMode = layout().offsetMode == SDisplayLayout::hexadecimal ? + SDisplayLayout::decimal : SDisplayLayout::hexadecimal; + mHexView->setLayout( layout() ); +} + +void CHexEditorWidget::toggleDataUppercase( void ) +{ + layout().primaryUpperCase = layout().primaryUpperCase == true ? false : true; + mHexView->setLayout( layout() ); +} + +void CHexEditorWidget::toggleOffsetUppercase( void ) +{ + layout().offsetUpperCase = layout().offsetUpperCase == true ? false : true; + mHexView->setLayout( layout() ); +} + +void CHexEditorWidget::toggleInsertMode( void ) +{ + mHexView->setInsertMode( !mHexView->insertMode() ); +} + +void CHexEditorWidget::benchmark( void ) +{ + mHexView->benchmark(); +} + +void CHexEditorWidget::copy( void ) +{ + mHexView->copy(); +} + +void CHexEditorWidget::copyText( void ) +{ + mHexView->copyText(); +} + +void CHexEditorWidget::paste( void ) +{ + if( mHexView->documentPresent() == false ) + { + pasteNewFile(); + } + else + { + mHexView->paste(); + } +} + +void CHexEditorWidget::pasteNewFile( void ) +{ + newFile(); + mHexView->paste(); +} + +void CHexEditorWidget::cut( void ) +{ + mHexView->cut(); +} + +void CHexEditorWidget::selectAll( void ) +{ + mHexView->selectAll(); +} + +void CHexEditorWidget::unselect( void ) +{ + mHexView->unselect(); +} + + +void CHexEditorWidget::addBookmark( void ) +{ + mHexView->addBookmark( -1 ); +} + + +void CHexEditorWidget::removeBookmark( void ) +{ + if( mHexView->bookmarkCount() > 0 ) + { + mHexView->removeBookmark( false ); + } +} + + +void CHexEditorWidget::removeAllBookmark( void ) +{ + if( mHexView->bookmarkCount() > 0 ) + { + QString msg = i18n("" + "Deleted bookmarks can not be restored.\n" + "Proceed?" ); + int reply = KMessageBox::warningContinueCancel( topLevelWidget(), msg ); + if( reply != KMessageBox::Continue ) + { + return; + } + mHexView->removeBookmark( true ); + } +} + + +void CHexEditorWidget::replaceBookmark( void ) +{ + mHexView->replaceBookmark(); +} + + +void CHexEditorWidget::gotoBookmark( int position ) +{ + mHexView->gotoBookmark( (uint)position ); +} + +void CHexEditorWidget::gotoNextBookmark( void ) +{ + mHexView->gotoNextBookmark(true); +} + +void CHexEditorWidget::gotoPrevBookmark( void ) +{ + mHexView->gotoNextBookmark(false); +} + +void CHexEditorWidget::gotoOffset( void ) +{ + if( mGotoDialog == 0 ) + { + mGotoDialog = new CGotoDialog( topLevelWidget(), 0, false ); + if( mGotoDialog == 0 ) { return; } + connect( mGotoDialog, SIGNAL(gotoOffset( uint, uint, bool, bool )), + mHexView, SLOT(gotoOffset( uint, uint, bool, bool )) ); + } + mGotoDialog->show(); +} + + +void CHexEditorWidget::find( void ) +{ + if( mFindNavigatorDialog != 0 ) + { + mFindNavigatorDialog->hide(); + } + + if( mFindDialog == 0 ) + { + mFindDialog = new CFindDialog( topLevelWidget(), 0, false ); + if( mFindDialog == 0 ) { return; } + connect( mFindDialog, + SIGNAL(findData(SSearchControl &, uint, bool)), + SLOT(findData(SSearchControl &, uint, bool)) ); + } + mFindDialog->show(); +} + + + +void CHexEditorWidget::findData( SSearchControl &sc, uint mode, bool navigator) +{ + for( uint i=0; i < 2; i++ ) + { + int errCode; + if( mode == Find_First ) + { + errCode = mHexView->findFirst( sc ); + if( errCode == Err_Success ) + { + if( navigator == true ) + { + findNavigator( sc ); + } + return; + } + } + else if( mode == Find_Next ) + { + errCode = mHexView->findNext( sc ); + if( errCode == Err_Success ) + { + if( navigator == true ) + { + findNavigator( sc ); + } + return; + } + } + else + { + return; + } + + if( errCode == Err_WrapBuffer && i == 0 ) + { + bool reply = askWrap( sc.forward, i18n("Find") ); + if( reply == false ) + { + return; + } + + sc.fromCursor = false; + mode = Find_First; + } + } + + if( mode == Find_First ) + { + QString msg = i18n( "Search key not found in document." ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Find") ); + } +} + + + +void CHexEditorWidget::findAgain( void ) +{ + if( canFind( true ) == true ) + { + mFindDialog->findAgain( CFindDialog::find_Again ); + } +} + + +void CHexEditorWidget::findNext( void ) +{ + if( canFind( true ) == true ) + { + mFindDialog->findAgain( CFindDialog::find_Next ); + } +} + + +void CHexEditorWidget::findPrevious( void ) +{ + if( canFind( true ) == true ) + { + mFindDialog->findAgain( CFindDialog::find_Previous ); + } +} + + +bool CHexEditorWidget::askWrap( bool fwd, const QString &header ) +{ + if( mDisplayState.misc.confirmWrap == false ) + { + return( true ); // Never ask the user + } + + QString msg; + if( fwd == true ) + { + msg += i18n("" + "End of document reached.\n" + "Continue from the beginning?" ); + } + else + { + msg += i18n("" + "Beginning of document reached.\n" + "Continue from the end?" ); + } + + int reply = KMessageBox::questionYesNo( topLevelWidget(), msg, header, KStdGuiItem::cont(), KStdGuiItem::cancel() ); + return( reply == KMessageBox::Yes ? true : false ); +} + + +bool CHexEditorWidget::canFind( bool showError ) +{ + if( mFindDialog == 0 || mFindDialog->isEmpty() == true ) + { + if( showError == true ) + { + QString msg = i18n("" + "Your request can not be processed.\n" + "No search pattern defined." ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Find") ); + } + return( false ); + } + + return( true ); +} + + + +void CHexEditorWidget::findNavigator( SSearchControl &sc ) +{ + if( canFind( false ) == false ) + { + return; + } + + if( mFindNavigatorDialog == 0 ) + { + mFindNavigatorDialog = new CFindNavigatorDialog(topLevelWidget(),0,false); + if( mFindNavigatorDialog == 0 ) { return; } + connect( mFindNavigatorDialog, + SIGNAL(findData(SSearchControl &, uint, bool)), + SLOT(findData(SSearchControl &, uint, bool)) ); + connect( mFindNavigatorDialog, SIGNAL(makeKey(void)), + SLOT(find()) ); + } + if( mFindNavigatorDialog->isVisible() == false ) + { + mFindNavigatorDialog->defineData( sc ); + } + mFindNavigatorDialog->show(); +} + + + +void CHexEditorWidget::replace( void ) +{ + hideReplacePrompt(); + + if( mReplaceDialog == 0 ) + { + mReplaceDialog = new CReplaceDialog( topLevelWidget(), 0, false ); + if( mReplaceDialog == 0 ) { return; } + connect( mReplaceDialog, + SIGNAL( replaceData( SSearchControl &, uint)), + SLOT( replaceData( SSearchControl &, uint))); + } + mReplaceDialog->show(); +} + + + +void CHexEditorWidget::replaceData( SSearchControl &sc, uint mode ) +{ + while( 1 ) + { + if( mode == Replace_All || mode == Replace_AllInit ) + { + mHexView->replaceAll( sc, mode == Replace_AllInit ? true : false ); + } + else if( mode == Replace_First ) + { + int errCode = mHexView->findFirst( sc ); + if( errCode == Err_Success ) + { + replacePrompt( sc ); + return; + } + } + else if( mode == Replace_Next ) + { + int errCode = mHexView->replaceMarked( sc ); + if( errCode != Err_Success ) + { + // Perhaps a notification here ? + } + errCode = mHexView->findNext( sc ); + if( errCode == Err_Success ) + { + replacePrompt( sc ); + return; + } + } + else if( mode == Replace_Ignore ) + { + int errCode = mHexView->findNext( sc ); + if( errCode == Err_Success ) + { + replacePrompt( sc ); + return; + } + } + else + { + break; + } + + if( sc.wrapValid == false ) + { + break; + } + + bool reply = askWrap( sc.forward, i18n("Find and Replace") ); + if( reply == false ) + { + break; + } + + int errCode = mHexView->findWrap( sc ); + if( errCode != Err_Success ) + { + break; + } + + if( mode == Replace_All || mode == Replace_AllInit ) + { + mode = Replace_All; + continue; + } + + replacePrompt( sc ); + return; + } + + replaceResult( sc ); +} + +void CHexEditorWidget::replacePrompt( SSearchControl &sc ) +{ + if( mReplacePromptDialog == 0 ) + { + mReplacePromptDialog = new CReplacePromptDialog(topLevelWidget(), 0,false); + if( mReplacePromptDialog == 0 ) { return; } + connect( mReplacePromptDialog, + SIGNAL( replaceData( SSearchControl &, uint)), + SLOT( replaceData( SSearchControl &, uint))); + } + if( mReplacePromptDialog->isVisible() == false ) + { + mReplacePromptDialog->defineData( sc ); + } + mReplacePromptDialog->show(); +} + + +void CHexEditorWidget::hideReplacePrompt( void ) +{ + if( mReplacePromptDialog != 0 ) + { + mReplacePromptDialog->hide(); + } +} + + + +void CHexEditorWidget::replaceResult( SSearchControl &sc ) +{ + hideReplacePrompt(); + + if( sc.match == false ) + { + QString msg; + if( sc.inSelection == true ) + { + msg += i18n( "Search key not found in selected area." ); + } + else + { + msg += i18n( "Search key not found in document." ); + } + KMessageBox::information( topLevelWidget(), msg, i18n("Find & Replace")); + } + else + { + const QString msg = i18n( + "Operation complete.

One replacement was made.
", + "Operation complete.

%n replacements were made.
", sc.numReplace ); + KMessageBox::information( topLevelWidget(), msg, i18n("Find & Replace")); + } +} + + +void CHexEditorWidget::insertPattern( void ) +{ + if( mInsertDialog == 0 ) + { + mInsertDialog = new CInsertDialog( topLevelWidget(), 0, false ); + if( mInsertDialog == 0 ) { return; } + connect( mInsertDialog, SIGNAL(execute( SInsertData & )), + mHexView, SLOT(insert( SInsertData & )) ); + } + mInsertDialog->show(); +} + + +void CHexEditorWidget::encoding( void ) +{ + QString msg = i18n("" + "Not available yet!\n" + "Define your own encoding" ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Encoding") ); +} + + +void CHexEditorWidget::strings( void ) +{ + if( mStringDialog == 0 ) + { + mStringDialog = new CStringDialog( topLevelWidget(), 0, false ); + if( mStringDialog == 0 ) { return; } + connect( mStringDialog, SIGNAL(markText( uint, uint, bool )), + mHexView, SLOT(setMark( uint, uint, bool )) ); + connect( mStringDialog, SIGNAL(collect()), SLOT(collectStrings()) ); + connect( mHexView, SIGNAL(fileName( const QString &, bool ) ), + mStringDialog, SLOT( removeList() ) ); + connect( mHexView, SIGNAL(dataChanged()), + mStringDialog, SLOT(setDirty()) ); + } + mStringDialog->show(); +} + + +void CHexEditorWidget::collectStrings( void ) +{ + int errCode = prepareProgressData( pg_strings ); + if( errCode == Err_Success ) + { + mHexView->collectStrings( mStringDialog->stringData() ); + errCode = mStringDialog->updateList( mProgressData ); + } + + if( errCode != Err_Success && errCode != Err_Stop ) + { + QString msg = i18n("Could not collect strings.\n"); + msg += hexError( errCode ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Collect Strings") ); + } + +} + + + +void CHexEditorWidget::recordView( void ) +{ + QString msg = i18n("" + "Not available yet!\n" + "Define a record (structure) and fill it with data from the document." ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Record Viewer") ); +} + +void CHexEditorWidget::filter( void ) +{ + if( mFilterDialog == 0 ) + { + mFilterDialog = new CFilterDialog( topLevelWidget(), 0, false ); + if( mFilterDialog == 0 ) { return; } + connect( mFilterDialog, SIGNAL(filterData( SFilterControl & )), + mHexView, SLOT(filter( SFilterControl & )) ); + } + mFilterDialog->show(); +} + + +void CHexEditorWidget::chart( void ) +{ + if( mCharTableDialog == 0 ) + { + mCharTableDialog = new CCharTableDialog( topLevelWidget(), 0, false ); + if( mCharTableDialog == 0 ) { return; } + connect( mCharTableDialog, SIGNAL(assign( const QByteArray & )), + mHexView, SLOT(insert( const QByteArray & )) ); + } + mCharTableDialog->show(); +} + + +void CHexEditorWidget::converter( void ) +{ + if( mConverterDialog == 0 ) + { + mConverterDialog = new CConverterDialog( this, "converter", false ); + connect( mConverterDialog, SIGNAL(probeCursorValue(QByteArray &, uint)), + mHexView, SLOT(valueOnCursor(QByteArray &, uint)) ); + } + mConverterDialog->show(); +} + + +void CHexEditorWidget::statistics( void ) +{ + if( mFileInfoDialog == 0 ) + { + mFileInfoDialog = new CFileInfoDialog( topLevelWidget(), 0, false ); + if( mFileInfoDialog == 0 ) { return; } + connect( mFileInfoDialog, SIGNAL(collectStatistic(SStatisticControl &)), + SLOT(collectStatistics(SStatisticControl &))); + connect( mHexView, SIGNAL(dataChanged()), + mFileInfoDialog, SLOT(setDirty()) ); + } + mFileInfoDialog->show(); +} + + +void CHexEditorWidget::collectStatistics( SStatisticControl &sc ) +{ + int errCode = prepareProgressData( pg_statistic ); + if( errCode == Err_Success ) + { + errCode = mHexView->collectStatistic( sc, mProgressData ); + if( errCode == Err_Success ) + { + mFileInfoDialog->setStatistics( sc ); + } + } + + if( errCode != Err_Success && errCode != Err_Stop ) + { + mFileInfoDialog->setStatistics(); // Default values + + QString msg = i18n("Could not collect document statistics.\n"); + msg += hexError( errCode ); + KMessageBox::sorry( topLevelWidget(), msg, + i18n("Collect Document Statistics") ); + } + +} + + +void CHexEditorWidget::options( void ) +{ + if( mOptionDialog == 0 ) + { + mOptionDialog = new COptionDialog( topLevelWidget(), 0, false ); + if( mOptionDialog == 0 ) { return; } + + connect( mOptionDialog, SIGNAL(lineSizeChoice(const SDisplayLine &)), + SLOT(setLineSize(const SDisplayLine &)) ); + connect( mOptionDialog, SIGNAL(layoutChoice(const SDisplayLayout &)), + SLOT(setLayout(const SDisplayLayout &)) ); + connect( mOptionDialog, SIGNAL(fontChoice(const SDisplayFont &)), + SLOT(setFont(const SDisplayFont &)) ); + connect( mOptionDialog, SIGNAL(colorChoice(const SDisplayColor &)), + SLOT(setColor(const SDisplayColor &)) ); + connect( mOptionDialog, SIGNAL(cursorChoice(const SDisplayCursor &)), + SLOT(setCursor(const SDisplayCursor &)) ); + connect( mOptionDialog, SIGNAL(miscChoice(const SDisplayMisc &)), + SLOT(setMisc(const SDisplayMisc &)) ); + connect( mOptionDialog, SIGNAL(removeRecentFiles()), + SIGNAL(removeRecentFiles()) ); + } + if( mOptionDialog->isVisible() == false ) + { + mOptionDialog->setState( mDisplayState ); + } + mOptionDialog->show(); +} + + + +void CHexEditorWidget::favorites( void ) +{ + QString msg = i18n("" + "Not available yet!\n" + "Save or retrive your favorite layout" ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Profiles") ); +} + + +int CHexEditorWidget::readURL( const KURL &url, bool insert ) +{ + // + // 1) Make sure there is data in the url + // + if( url.isEmpty() ) + return( Err_EmptyArgument ); + + // + // 2) Verify that the url is valid URL string. If not, try to repair it. + // This will work if the url contains a name of a file in the + // current directory. + // + if( !url.isValid() ) + { + QString msg = i18n("Malformed URL\n%1").arg( url.url() ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Read URL") ); + return( Err_IllegalArgument ); + } + + // + // 3) Load the file. + // + QString tmpfile; + if ( !KIO::NetAccess::download( url, tmpfile, this ) ) + return Err_ReadFailed; + + bool success = readFile( tmpfile, url.url(), insert ); + + KIO::NetAccess::removeTempFile( tmpfile ); + + return( success == true ? Err_Success : Err_ReadFailed ); +} + + +void CHexEditorWidget::writeURL( QString &url ) +{ + KURL kurl( url ); + if( kurl.isLocalFile() ) + writeFile( kurl.path() ); + else + { + bool modified = mHexView->modified(); + KTempFile tf; + tf.setAutoDelete( true ); + writeFile( tf.name() ); + if( !KIO::NetAccess::upload(tf.name(),url,this) ) + { + mHexView->setModified( modified ); + QString msg = i18n("Could not save remote file."); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") ); + } + } +} + +bool CHexEditorWidget::modifiedByAlien( const QString &url ) +{ + KURL kurl( url ); + if( kurl.isLocalFile() == false ) + { + return( false ); + } + + QFileInfo fileInfo( kurl.path() ); + if( fileInfo.exists() == false ) + { + return( false ); + } + + if( fileInfo.lastModified() == mHexView->diskModifyTime() ) + { + return( false ); + } + + return( true ); +} + + + +bool CHexEditorWidget::readFile( const QString &diskPath, const QString &url, + bool insert ) +{ + + QFileInfo info( diskPath ); + if( info.exists() == false ) + { + const QString msg = i18n("The specified file does not exist.\n%1").arg( diskPath ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Read") ); + return( false ); + } + + if( info.isDir() == true ) + { + const QString msg = i18n("You have specified a folder.\n%1").arg( diskPath ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Read") ); + return( false ); + } + + if( info.isReadable() == false ) + { + const QString msg = i18n("You do not have read permission to this file.\n%1").arg( diskPath ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Read") ); + return( false ); + } + + QFile file( diskPath ); + if( file.open( IO_ReadOnly | IO_Raw ) == false ) + { + const QString msg = i18n("An error occurred while trying to open the file.\n%1").arg( diskPath ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Read") ); + return( false ); + } + + if( mHexView->documentPresent() == false ) + { + // + // Can not insert if there is no document present. + // + insert = false; + } + + int errCode = prepareProgressData( insert == true ? pg_insert: pg_read ); + if( errCode == Err_Success ) + { + if( insert == true ) + { + errCode = mHexView->insertFile( file, mProgressData ); + } + else + { + errCode = mHexView->readFile( file, url, mProgressData ); + } + } + + if( errCode != Err_Success ) + { + QString header = insert == true ? i18n("Insert") : i18n("Read"); + QString msg = i18n("Could not read file.\n"); + msg += hexError( errCode ); + KMessageBox::sorry( topLevelWidget(), msg, header ); + } + + file.close(); + return( errCode == Err_Success || errCode == Err_Busy ? true : false ); +} + + + + +bool CHexEditorWidget::writeFile( const QString &diskPath ) +{ + QFileInfo info( diskPath ); + if( info.exists() == true ) + { + if( info.isDir() == true ) + { + QString msg = i18n("You have specified a folder."); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") ); + return( false ); + } + + if( info.isWritable() == false ) + { + QString msg = i18n("You do not have write permission."); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") ); + return( false ); + } + } + + QFile file( diskPath ); + if( file.open( IO_WriteOnly | IO_Raw | IO_Truncate ) == false ) + { + QString msg = i18n("An error occurred while trying to open the file."); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") ); + return( false ); + } + + int errCode = prepareProgressData( pg_write ); + if( errCode == Err_Success ) + { + errCode = mHexView->writeFile( file, mProgressData ); + } + if( errCode != Err_Success ) + { + QString msg = i18n("Could not write data to disk.\n"); + msg += hexError( errCode ); + KMessageBox::sorry( topLevelWidget(), msg, i18n("Write Failure") ); + } + + file.close(); + return( true ); +} + + +CHexBuffer *CHexEditorWidget::documentItem( const QString &url ) +{ + QString symbolicName( url ); +// KURL::decode( symbolicName ); + + for( CHexBuffer *hexBuffer = mDocumentList.first(); hexBuffer != 0; + hexBuffer = mDocumentList.next() ) + { + if( hexBuffer->url() == symbolicName ) + { + return( hexBuffer ); + } + } + + return( 0 ); +} + + +CHexBuffer *CHexEditorWidget::documentItem( const QString &url, bool next ) +{ + if( mDocumentList.count() <= 1 ) + { + return( 0 ); + } + + QString symbolicName( url ); +// KURL::decode( symbolicName ); + + if( next == true ) + { + CHexBuffer *hexBuffer = mDocumentList.first(); + for( ; hexBuffer != 0; hexBuffer = mDocumentList.next() ) + { + if( hexBuffer->url() == symbolicName ) + { + hexBuffer = mDocumentList.next(); + return( hexBuffer == 0 ? mDocumentList.first() : hexBuffer ); + } + } + } + else + { + CHexBuffer *hexBuffer = mDocumentList.last(); + for( ; hexBuffer != 0; hexBuffer = mDocumentList.prev() ) + { + if( hexBuffer->url() == symbolicName ) + { + hexBuffer = mDocumentList.prev(); + return( hexBuffer == 0 ? mDocumentList.last() : hexBuffer ); + } + } + } + + return( 0 ); +} + + + +bool CHexEditorWidget::createBuffer( void ) +{ + if( mHexView->documentPresent() == false ) + { + // + // The document is not valid, i.e. the buffer contains no data + // so we can use this one without destroying anything. + // + return( true ); + } + + CHexBuffer *hexBuffer = new CHexBuffer; + if( hexBuffer == 0 ) + { + QString msg = i18n( "Can not create text buffer.\n" ); + msg += hexError( Err_NoMemory ); + KMessageBox::error( topLevelWidget(), msg, i18n("Loading Failed" ) ); + return( false ); + } + + mDocumentList.append( hexBuffer ); + mHexView->setBuffer( hexBuffer ); + + return( true ); +} + + +void CHexEditorWidget::removeBuffer( void ) +{ + mHexView->closeFile(); + + if( mDocumentList.count() > 1 ) + { + CHexBuffer *prev = 0; + CHexBuffer *curr = mDocumentList.first(); + for( ; curr != 0; curr = mDocumentList.next() ) + { + if( curr == mHexView->hexBuffer() ) + { + CHexBuffer *ptr = prev != 0 ? prev : mDocumentList.next(); + if( ptr != 0 ) + { + mHexView->setBuffer( ptr ); + mDocumentList.remove( curr ); + break; + } + } + prev = curr; + } + } + +} + + +bool CHexEditorWidget::modified( void ) +{ + for( CHexBuffer *hexBuffer = mDocumentList.first(); hexBuffer != 0; + hexBuffer = mDocumentList.next() ) + { + if( hexBuffer->modified() == true ) + { + return( true ); + } + } + + return( false ); +} + + + + +int CHexEditorWidget::prepareProgressData( EProgressMode mode ) +{ + if( mode >= pg_MAX ) + { + return( Err_IllegalMode ); + } + + if( mProgressBusy == true ) + { + return( Err_Busy ); + } + + + mProgressMode = mode; + mProgressBusy = true; + mProgressStop = false; + enableInputLock( true ); + + static QString names[] = + { + i18n("Reading"), + i18n("Writing"), + i18n("Inserting"), + i18n("Printing"), + i18n("Encoding"), + i18n("Collect strings"), + i18n("Exporting"), + i18n("Scanning"), + }; + + mProgressData.define( progressReceiver, this ); + emit setProgressText( QString(names[mode]) ); + emit operationChanged( true ); + + return( Err_Success ); +} + + +int CHexEditorWidget::progressReceiver( void *clientData, SProgressData &pd ) +{ + if( clientData != 0 ) + { + int errCode = ((CHexEditorWidget*)clientData)->progressParse( pd ); + return( errCode ); + } + else + { + return( Err_Success ); + } +} + + +int CHexEditorWidget::progressParse( const SProgressData &pd ) +{ + if( pd.valid() == 0 ) + { + emit enableProgressText( false ); + emit setProgress( 0 ); + emit operationChanged( false ); + mProgressBusy = false; + enableInputLock( false ); + kapp->processEvents(); + return( Err_Success ); + } + else if( pd.useFraction == 1 ) + { + emit enableProgressText( true ); + emit setProgress( (int)(100.0 * pd.fraction ) ); + kapp->processEvents(); + } + else + { + emit enableProgressText( true ); + emit setProgress( pd.curPage, pd.maxPage ); + kapp->processEvents(); + } + + if( mProgressStop == false ) + { + return( Err_Success ); + } + + QString msg, header; + switch( mProgressMode ) + { + case pg_read: + header = i18n("Read"); + msg = i18n("Do you really want to cancel reading?"); + break; + + case pg_write: + header = i18n("Write"); + msg = i18n("Do you really want to cancel writing?\n" + "WARNING: Canceling can corrupt your data on disk"); + break; + + case pg_insert: + header = i18n("Insert"); + msg = i18n("Do you really want to cancel inserting?"); + break; + + case pg_print: + header = i18n("Print"); + msg = i18n("Do you really want to cancel printing?"); + break; + + case pg_encode: + header = i18n("Encode"); + msg = i18n("Do you really want to cancel encoding?"); + break; + + case pg_strings: + header = i18n("Collect strings"); + msg = i18n("Do you really want to cancel string scanning?"); + break; + + case pg_export: + header = i18n("Export"); + msg = i18n("Do you really want to cancel exporting?"); + break; + + case pg_statistic: + header = i18n("Collect document statistics"); + msg = i18n("Do you really want to cancel document scanning?"); + break; + + default: + return( Err_Success ); + break; + + } + + int reply = KMessageBox::warningYesNo( topLevelWidget(), msg, header, KStdGuiItem::cancel(), KStdGuiItem::cont() ); + mProgressStop = false; + return( reply == KMessageBox::Yes ? Err_Stop : Err_Success ); +} + + + +bool CHexEditorWidget::busy( bool showWarning ) +{ + if( mProgressBusy == true && showWarning == true ) + { + QString msg = i18n("Could not finish operation.\n"); + msg += hexError( Err_Busy ); + KMessageBox::sorry( topLevelWidget(), msg ); + } + + return( mProgressBusy ); +} + + + + +#include "hexeditorwidget.moc" diff --git a/khexedit/hexeditorwidget.h b/khexedit/hexeditorwidget.h new file mode 100644 index 0000000..5c4d86a --- /dev/null +++ b/khexedit/hexeditorwidget.h @@ -0,0 +1,301 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_EDITOR_WIDGET_H_ +#define _HEX_EDITOR_WIDGET_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#include +#include +#include + +#include "hexbuffer.h" +#include "hexviewwidget.h" +#include "progress.h" + +class CGotoDialog; +class CFindDialog; +class CReplaceDialog; +class CInsertDialog; +class CFilterDialog; +class COptionDialog; +class CPrinterDialog; +class CStringDialog; +class CCharTableDialog; +class CFileInfoDialog; +class CExportDialog; +class CConverterDialog; +class CFindNavigatorDialog; +class CReplacePromptDialog; +namespace KIO { class Job; } + + +class CHexEditorWidget : public QWidget +{ + Q_OBJECT + + public: + enum EProgressMode + { + pg_read = 0, + pg_write, + pg_insert, + pg_print, + pg_encode, + pg_strings, + pg_export, + pg_statistic, + pg_MAX + }; + + public: + CHexEditorWidget( QWidget *parent = 0, const char *name = 0 ); + ~CHexEditorWidget( void ); + + void initialize( void ); + void writeConfiguration( KConfig &config ); + void readConfiguration( KConfig &config ); + + bool isOpen( const QString &url, uint &offset ); + bool modified( void ); + + inline int defaultTextWidth( void ); + inline CHexViewWidget *view( void ); + inline SDisplayLayout &layout( void ); + inline SDisplayLine &line( void ); + inline SDisplayInputMode &inputMode( void ); + inline SDisplayMisc::EOpenFile openFile( void ); + inline bool discardRecentFiles( void ); + inline bool gotoStartupOffset( void ); + inline bool gotoReloadOffset( void ); + + signals: + void errorLoadFile( const QString &url ); + void setProgress( int percent ); + void setProgress( int curPage, int maxPage ); + void enableProgressText( bool state ); + void setProgressText( const QString &msg ); + void operationChanged( bool state ); + void removeRecentFiles( void ); + + public slots: + void setHexadecimalMode( void ); + void setDecimalMode( void ); + void setOctalMode( void ); + void setTextMode( void ); + void setBinaryMode( void ); + void open( const QString &url, bool reloadWhenChanged, uint offset ); + void newFile( void ); + void newFile( const QByteArray &data ); + void stepFile( bool next ); + void open( void ); + void insertFile( void ); + void stop( void ); + bool close( void ); + bool closeAll( void ); + bool backup( void ); + bool save( void ); + bool saveAs( void ); + void reload( void ); + void print( void ); + void exportDialog( void ); + void encode( CConversion::EMode mode ); + void undo( void ); + void redo( void ); + void toggleWriteProtection( void ); + void defaultWriteProtection( void ); + void toggleResizeLock( void ); + void setResizeLock( bool state ); + void toggleOffsetColumnVisibility( void ); + void toggleTextColumnVisibility( void ); + void toggleOffsetAsDecimal( void ); + void toggleDataUppercase( void ); + void toggleOffsetUppercase( void ); + void toggleInsertMode( void ); + void benchmark( void ); + void copy( void ); + void copyText( void ); + void paste( void ); + void pasteNewFile( void ); + void cut( void ); + void selectAll( void ); + void unselect( void ); + void addBookmark( void ); + void removeBookmark( void ); + void removeAllBookmark( void ); + void replaceBookmark( void ); + void gotoBookmark( int position ); + void gotoNextBookmark( void ); + void gotoPrevBookmark( void ); + void gotoOffset( void ); + void find( void ); + void findAgain( void ); + void findNext( void ); + void findPrevious( void ); + void findData( SSearchControl &sc, uint mode, bool navigator ); + void replace( void ); + void insertPattern( void ); + void encoding( void ); + void strings( void ); + void recordView( void ); + void filter( void ); + void chart( void ); + void converter( void ); + void statistics( void ); + void options( void ); + void favorites( void ); + + protected slots: + void fontChanged( void ); + void paletteChanged( void ); + void layoutChanged( const SDisplayLayout &layout ); + void inputModeChanged( const SDisplayInputMode &input ); + void setLineSize(const SDisplayLine &line ); + void setLayout( const SDisplayLayout &layout ); + void setCursor( const SDisplayCursor &cursor ); + void setColor( const SDisplayColor &color ); + void setFont( const SDisplayFont &font ); + void setMisc( const SDisplayMisc &misc ); + + void printPostscript( CHexPrinter & ); + void exportText( const SExportText & ); + void exportHtml( const SExportHtml & ); + void exportCArray( const SExportCArray &ex ); + + void findNavigator( SSearchControl &sc ); + void replaceData( SSearchControl &sc, uint mode ); + void replacePrompt( SSearchControl &sc ); + void replaceResult( SSearchControl &sc ); + void collectStrings( void ); + void collectStatistics( SStatisticControl &sc ); + + protected: + void resizeEvent( QResizeEvent *e ); + + private: + bool selectDocument( const QString &url, bool reloadWhenChanged ); + bool querySave( void ); + int readURL( const KURL &url, bool insert ); + void writeURL( QString &url ); + bool readFile( const QString &diskPath, const QString &url, bool insert ); + bool writeFile( const QString &diskPath ); + void saveWorkingDirectory( const QString &url ); + + bool confirmPrintPageNumber( CHexPrinter &printer ); + + CHexBuffer *documentItem( const QString &url ); + CHexBuffer *documentItem( const QString &url, bool next ); + bool createBuffer( void ); + void removeBuffer( void ); + + bool askWrap( bool fwd, const QString &header ); + bool canFind( bool showError ); + void hideReplacePrompt( void ); + bool modifiedByAlien( const QString &url ); + void enableInputLock( bool inputLock ); + + int prepareProgressData( EProgressMode mode ); + static int progressReceiver( void *clientData, SProgressData &pd ); + int progressParse( const SProgressData &pd ); + bool busy( bool showWarning ); + + private: + QString mWorkDir; // Remembers last directroy used by file dialogs + + uint mUntitledCount; + QPtrList mDocumentList; + SDisplayState mDisplayState; + + CProgress mProgressData; + EProgressMode mProgressMode; + bool mProgressBusy; + bool mProgressStop; + + CHexViewWidget *mHexView; + CGotoDialog *mGotoDialog; + CFindDialog *mFindDialog; + CReplaceDialog *mReplaceDialog; + CInsertDialog *mInsertDialog; + CFilterDialog *mFilterDialog; + COptionDialog *mOptionDialog; + CStringDialog *mStringDialog; + CCharTableDialog *mCharTableDialog; + CFileInfoDialog *mFileInfoDialog; + CExportDialog *mExportDialog; + CConverterDialog *mConverterDialog; + CFindNavigatorDialog *mFindNavigatorDialog; + CReplacePromptDialog *mReplacePromptDialog; +}; + +inline int CHexEditorWidget::defaultTextWidth( void ) +{ + return( mHexView->defaultWidth() ); +} + +inline CHexViewWidget *CHexEditorWidget::view( void ) +{ + return( mHexView ); +} + +inline SDisplayLayout &CHexEditorWidget::layout( void ) +{ + return( mDisplayState.layout ); +} + +inline SDisplayLine &CHexEditorWidget::line( void ) +{ + return( mDisplayState.line ); +} + +inline SDisplayInputMode &CHexEditorWidget::inputMode( void ) +{ + return( mDisplayState.input ); +} + +inline SDisplayMisc::EOpenFile CHexEditorWidget::openFile( void ) +{ + return( mDisplayState.misc.openFile ); +} + +inline bool CHexEditorWidget::discardRecentFiles( void ) +{ + return( mDisplayState.misc.discardRecent ); +} + +inline bool CHexEditorWidget::gotoStartupOffset( void ) +{ + return( mDisplayState.misc.gotoOnStartup ); +} + +inline bool CHexEditorWidget::gotoReloadOffset( void ) +{ + return( mDisplayState.misc.gotoOnReload ); +} + + + +#endif + + + diff --git a/khexedit/hexeditstate.h b/khexedit/hexeditstate.h new file mode 100644 index 0000000..f3f8fff --- /dev/null +++ b/khexedit/hexeditstate.h @@ -0,0 +1,596 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_EDIT_STATE_H_ +#define _HEX_EDIT_STATE_H_ + +#include +#include +#include +#include + + +class SDisplayLine +{ + public: + enum EViewMode + { + hexadecimal = 0, + decimal, + octal, + binary, + textOnly + }; + + SDisplayLine( void ) + { + lineSize[hexadecimal] = 16; + lineSize[decimal] = 16; + lineSize[octal] = 16; + lineSize[binary] = 8; + lineSize[textOnly] = 64; + + columnSize[hexadecimal] = 1; + columnSize[decimal] = 1; + columnSize[octal] = 1; + columnSize[binary] = 1; + columnSize[textOnly] = 64; + } + + uint getLineSize( int index ) + { + return( lineSize[ index > textOnly ? 0 : index ] ); + } + + uint getColumnSize( int index ) + { + return( columnSize[ index > textOnly ? 0 : index ] ); + } + + void setLineSize( int index, uint value ) + { + if( index <= textOnly ) { lineSize[ index ] = value; } + } + + void setColumnSize( int index, uint value ) + { + if( index <= textOnly ) { columnSize[ index ] = value; } + } + + uint lineSize[5]; + uint columnSize[5]; +}; + + +class SDisplayLayout +{ + public: + enum EViewMode + { + hexadecimal = 0, + decimal, + octal, + binary, + textOnly, + hide + }; + + SDisplayLayout( void ) + { + offsetMode = hexadecimal; + primaryMode = hexadecimal; + secondaryMode = textOnly; + offsetUpperCase = false; + primaryUpperCase = false; + offsetVisible = true; + lineSize = 16; + columnSize = 1; + lockLine = true; + lockColumn = true; + columnCharSpace = true; + columnSpacing = 5; + separatorMarginWidth = 5; + edgeMarginWidth = 5; + leftSeparatorWidth = 1; + rightSeparatorWidth = 1; + horzGridWidth = 0; + vertGridWidth = 0; + } + + void verify( void ) + { + if( lineSize < 1 ) { lineSize = 1; } + if( columnSize < 1 ) { columnSize = 1; } + if( columnSize > lineSize ) { columnSize = lineSize; } + if( primaryMode == textOnly ) { secondaryMode = hide; columnSpacing=0; } + if( columnSpacing == 0 ) { columnSize = lineSize; } + if( horzGridWidth > 1 ) { horzGridWidth = 1; } + if( vertGridWidth > 1 ) { vertGridWidth = 1; } + } + + bool showSecondary( void ) + { + if( primaryMode == textOnly || secondaryMode == hide ) + { + return( false ); + } + else + { + return( true ); + } + } + + QString modeStrings( uint index ) + { + if( index == hexadecimal ) + { + return( "hexadecimal" ); + } + else if( index == decimal ) + { + return( "decimal" ); + } + else if( index == octal ) + { + return( "octal" ); + } + else if( index == binary ) + { + return( "binary" ); + } + else if( index == textOnly ) + { + return( "textOnly" ); + } + else + { + return( "hide" ); + } + } + + + QString primaryModeString( void ) + { + return( modeStrings( primaryMode > textOnly ? + hexadecimal : primaryMode )); + } + + QString secondaryModeString( void ) + { + return( modeStrings( secondaryMode == textOnly ? textOnly : hide ) ); + } + + QString offsetModeString( void ) + { + return( modeStrings( offsetMode == hexadecimal ? hexadecimal : hide ) ); + } + + QString gridModeString( void ) + { + if( horzGridWidth == 0 && vertGridWidth == 0 ) + { + return( "none"); + } + else if( horzGridWidth != 0 && vertGridWidth != 0 ) + { + return( "both"); + } + else if( horzGridWidth != 0 ) + { + return( "horizontal"); + } + else + { + return( "vertical"); + } + } + + void setPrimaryMode( const QString & str ) + { + if( str.isNull() || str == "hexadecimal" ) + { + primaryMode = hexadecimal; + } + else if( str == "decimal" ) + { + primaryMode = decimal; + } + else if( str == "octal" ) + { + primaryMode = octal; + } + else if( str == "binary" ) + { + primaryMode = binary; + } + else if( str == "textOnly" ) + { + primaryMode = textOnly; + } + else + { + primaryMode = hexadecimal; + } + } + + void setSecondaryMode( const QString & str ) + { + if( str.isNull() || str == "textOnly" ) + { + secondaryMode = textOnly; + } + else + { + secondaryMode = hide; + } + } + + void setOffsetMode( const QString & str ) + { + if( str.isNull() || str == "hexadecimal" ) + { + offsetMode = hexadecimal; + } + else + { + offsetMode = decimal; + } + } + + void setGridMode( const QString & str ) + { + if( str.isNull() || str == "none" ) + { + horzGridWidth = vertGridWidth = 0; + } + else if( str == "vertical" ) + { + horzGridWidth = 0; + vertGridWidth = 1; + } + else if( str == "horizontal" ) + { + horzGridWidth = 1; + vertGridWidth = 0; + } + else if( str == "both" ) + { + horzGridWidth = vertGridWidth = 1; + } + else + { + horzGridWidth = vertGridWidth = 0; + } + } + + EViewMode offsetMode; + EViewMode primaryMode; + EViewMode secondaryMode; + bool offsetUpperCase; + bool primaryUpperCase; + bool offsetVisible; + bool lockLine; + bool lockColumn; + uint lineSize; + uint columnSize; + bool columnCharSpace; + uint columnSpacing; + uint separatorMarginWidth; + uint edgeMarginWidth; + uint leftSeparatorWidth; + uint rightSeparatorWidth; + uint horzGridWidth; + uint vertGridWidth; +}; + + + + +class SDisplayCursor +{ + public: + enum EFocusMode + { + stopBlinking = 0, + hide, + ignore + }; + + SDisplayCursor( void ) + { + focusMode = hide; + interval = 500; + alwaysVisible = false; + alwaysBlockShape = false; + thickInsertShape = true; + } + + QString modeStrings( uint index ) + { + if( index == hide ) + { + return( "hide" ); + } + else if( index == ignore ) + { + return( "ignore" ); + } + else + { + return( "stopBlinking" ); + } + } + + QString focusModeString( void ) + { + return( modeStrings( focusMode > ignore ? stopBlinking : focusMode )); + } + + void setFocusMode( const QString & str ) + { + if( str.isNull() || str == "hide" ) + { + focusMode = hide; + } + else if( str == "stopBlinking" ) + { + focusMode = stopBlinking; + } + else + { + focusMode = ignore; + } + } + + EFocusMode focusMode; + uint interval; + bool alwaysVisible; + bool alwaysBlockShape; + bool thickInsertShape; +}; + + +class SDisplayColor +{ + public: + + SDisplayColor( void ) + { + // + // Default colors. The selection colors will always be the one + // choses in Control Center. + // + useSystemColor = false; + offsetBg = Qt::white; + textBg = Qt::white; + secondTextBg = Qt::white; + inactiveBg = Qt::gray; + selectBg = kapp->palette().active().highlight(); + selectFg = kapp->palette().active().highlightedText(); + markBg = Qt::blue; + markFg = Qt::white; + primaryFg[0] = Qt::black; + primaryFg[1] = Qt::blue; + offsetFg = Qt::red; + secondaryFg = Qt::black; + nonPrintFg = Qt::red; + gridFg = Qt::darkCyan; + leftSeparatorFg = Qt::darkGreen; + rightSeparatorFg = Qt::darkGreen; + cursorBg = Qt::red; + cursorFg = Qt::black; + bookmarkBg = Qt::green; + bookmarkFg = Qt::black; + } + + bool useSystemColor; + QColor offsetBg; + QColor textBg; + QColor secondTextBg; + QColor inactiveBg; + QColor selectBg; + QColor selectFg; + QColor markBg; + QColor markFg; + QColor primaryFg[2]; + QColor offsetFg; + QColor secondaryFg; + QColor nonPrintFg; + QColor gridFg; + QColor leftSeparatorFg; + QColor rightSeparatorFg; + QColor cursorBg; + QColor cursorFg; + QColor bookmarkBg; + QColor bookmarkFg; +}; + + +class SDisplayFontInfo +{ + public: + + SDisplayFontInfo &init( void ) + { + font = KGlobalSettings::fixedFont(); + nonPrintChar = '.'; + return( *this ); + } + + QFont font; + QChar nonPrintChar; +}; + +class SDisplayFont +{ + public: + SDisplayFont( void ) + { + useSystemFont = false; + localFont = KGlobalSettings::fixedFont(); + nonPrintChar = '.'; + } + + bool useSystemFont; + QFont localFont; + QChar nonPrintChar; +}; + + +class SDisplayMisc +{ + public: + + enum EOpenFile + { + none = 0, + mostRecent, + allRecent + }; + + SDisplayMisc( void ) + { + undoLevel = 100; + openFile = none; + inputSound = false; + fatalSound = false; + autoCopyToClipboard = true; + insertMode = false; + writeProtect = false; + confirmWrap = true; + cursorJump = true; + makeBackup = false; + confirmThreshold = true; + thresholdValue = 30; + discardRecent = false; + gotoOnStartup = false; + gotoOnReload = true; + bookmarkOffsetColumn = true; + bookmarkEditor = true; + } + + + QString fileStrings( uint index ) + { + if( index == mostRecent ) + { + return( "mostRecent" ); + } + else if( index == allRecent ) + { + return( "allRecent" ); + } + else + { + return( "none" ); + } + } + + + QString openFileString( void ) + { + return( fileStrings( openFile > allRecent ? none : openFile )); + } + + void setOpenFile( const QString &str ) + { + if( str.isNull() == true || str == "none" ) + { + openFile = none; + } + else if( str == "mostRecent" ) + { + openFile = mostRecent; + } + else if( str == "allRecent" ) + { + openFile = allRecent; + } + else + { + openFile = none; + } + } + + uint undoLevel; + EOpenFile openFile; + bool inputSound; + bool fatalSound; + bool autoCopyToClipboard; + bool insertMode; + bool writeProtect; + bool confirmWrap; + bool cursorJump; + bool makeBackup; + bool confirmThreshold; + uint thresholdValue; + bool discardRecent; + bool gotoOnStartup; + bool gotoOnReload; + bool bookmarkOffsetColumn; + bool bookmarkEditor; +}; + + +class SDisplayInputMode +{ + public: + SDisplayInputMode( void ) + { + inputLock = false; + readOnly = false; + allowResize = true; + }; + + bool noInput( void ) + { + return( inputLock || readOnly ); + } + + bool inputLock; // Set by application only + bool readOnly; // Set by user + bool allowResize; +}; + + +class SDisplayState +{ + public: + SDisplayLine line; + SDisplayLayout layout; + SDisplayCursor cursor; + SDisplayColor color; + SDisplayFont font; + SDisplayMisc misc; + SDisplayInputMode input; +}; + + + + + +#endif + + + + + + + diff --git a/khexedit/hexerror.cc b/khexedit/hexerror.cc new file mode 100644 index 0000000..ac179e6 --- /dev/null +++ b/khexedit/hexerror.cc @@ -0,0 +1,69 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include "hexerror.h" + +static QString message; + + +const QString &hexError( int index ) +{ + static QString messages[ Err_MAXERROR - Err_NoData ] = + { + i18n("No data"), // Err_NoData + i18n("Insufficient memory"), // Err_NoMemory + i18n("List is full"), // Err_ListFull + i18n("Read operation failed"), // Err_ReadFailed + i18n("Write operation failed"), // Err_WriteFailed + i18n("Empty argument"), // Err_EmptyArgument + i18n("Illegal argument"), // Err_IllegalArgument + i18n("Null pointer argument"), // Err_NullArgument + i18n("Wrap buffer"), // Err_WrapBuffer + i18n("No match"), // Err_NoMatch + i18n("No data is selected"), // Err_NoSelection + i18n("Empty document"), // Err_EmptyDocument + i18n("No active document"), // Err_NoActiveDocument + i18n("No data is marked"), // Err_NoMark + i18n("Document is write protected"), // Err_WriteProtect + i18n("Document is resize protected"), // Err_NoResize + i18n("Operation was stopped"), // Err_Stop + i18n("Illegal mode"), // Err_IllegalMode + i18n("Program is busy, try again later"), // Err_Busy + i18n("Value is not within valid range"), // Err_IllegalRange + i18n("Operation was aborted"), // Err_OperationAborted + i18n("File could not be opened for writing"), // Err_OpenWriteFailed + i18n("File could not be opened for reading"), // Err_OpenReadFailed + }; + + + if( index < Err_NoData || index >= Err_MAXERROR ) + { + message = i18n("Unknown error"); + } + else + { + message = messages[ index - Err_NoData ]; + } + + return( message ); +} + diff --git a/khexedit/hexerror.h b/khexedit/hexerror.h new file mode 100644 index 0000000..d17d302 --- /dev/null +++ b/khexedit/hexerror.h @@ -0,0 +1,57 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_ERROR_H_ +#define _HEX_ERROR_H_ + +enum EHexError +{ + Err_NoErr = 0, + Err_Success = 0, + Err_NoData = -10000, // Must be the first + Err_NoMemory, + Err_ListFull, + Err_ReadFailed, + Err_WriteFailed, + Err_EmptyArgument, + Err_IllegalArgument, + Err_NullArgument, + Err_WrapBuffer, + Err_NoMatch, + Err_NoSelection, + Err_EmptyDocument, + Err_NoActiveDocument, + Err_NoMark, + Err_WriteProtect, + Err_NoResize, + Err_Stop, + Err_IllegalMode, + Err_Busy, + Err_IllegalRange, + Err_OperationAborted, + Err_OpenWriteFailed, + Err_OpenReadFailed, + Err_MAXERROR // Must be the last +}; + +const QString &hexError( int index ); + + +#endif diff --git a/khexedit/hexmanagerwidget.cc b/khexedit/hexmanagerwidget.cc new file mode 100644 index 0000000..1073b95 --- /dev/null +++ b/khexedit/hexmanagerwidget.cc @@ -0,0 +1,370 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include "hexmanagerwidget.h" +#include "searchbar.h" + +CHexManagerWidget::CHexManagerWidget( QWidget *parent, const char *name, + EConversionPosition conversionPosition, + EPosition tabBarPosition, + EPosition searchBarPosition ) + : QWidget( parent, name ) +{ + mValid = false; + + mEditor = new CHexEditorWidget( this ); + mTabBar = new CTabBar( this ); + mTabBar->hide(); + mSearchBar = 0; + + mConverter = new CHexToolWidget( this ); + + connect( mEditor->view(), SIGNAL(fileName(const QString &, bool)), + this, SLOT( addName(const QString &))); + connect( mEditor->view(), SIGNAL( fileClosed(const QString &)), + this, SLOT( removeName(const QString &))); + connect( mEditor->view(),SIGNAL(fileRename(const QString &,const QString &)), + this, SLOT(changeName(const QString &,const QString &))); + connect( mEditor->view(), SIGNAL( cursorChanged( SCursorState & ) ), + mConverter, SLOT( cursorChanged( SCursorState & ) ) ); + connect( mConverter, SIGNAL( closed(void) ), + this, SIGNAL( conversionClosed(void) ) ); + connect( mTabBar, SIGNAL(selected(const QString &)), + this, SLOT(open(const QString &))); + + mValid = true; + setConversionVisibility( conversionPosition ); + setTabBarPosition( tabBarPosition ); + setSearchBarPosition( searchBarPosition ); +} + + +CHexManagerWidget::~CHexManagerWidget( void ) +{ + delete mEditor; + delete mTabBar; + delete mConverter; +} + + +void CHexManagerWidget::updateLayout( void ) +{ + if( mValid == false ) { return; } + + delete layout(); + QVBoxLayout *vlay = new QVBoxLayout( this, 0, 0 ); + + if( mSearchBar && mSearchBarPosition == AboveEditor ) + { + vlay->addWidget( mSearchBar ); + } + + if( mTabPosition == AboveEditor ) + { + vlay->addWidget( mTabBar ); + vlay->addWidget( mEditor, 1 ); + } + else + { + vlay->addWidget( mEditor, 1 ); + vlay->addWidget( mTabBar ); + } + + if( mSearchBar && mSearchBarPosition == BelowEditor ) + { + vlay->addWidget( mSearchBar ); + } + + if( mConversionPosition == Embed ) + { + vlay->addWidget( mConverter ); + } + vlay->activate(); // Required in this case +} + + +void CHexManagerWidget::setConversionVisibility( EConversionPosition position ) +{ + if( mValid == false ) + { + return; + } + + if( mConversionPosition == position ) + { + if( mConversionPosition == Float ) + { + mConverter->raise(); + } + return; + } + + mConversionPosition = position; + if( mConversionPosition == Hide ) + { + mConverter->hide(); + } + else if( mConversionPosition == Float ) + { + QPoint point = mapToGlobal( QPoint(0,0) ); + QRect rect = geometry(); + QPoint p; + + p.setX(point.x() + rect.width()/2 - mConverter->minimumSize().width()/2); + p.setY(point.y() + rect.height()/2 - mConverter->minimumSize().height()/2); + mConverter->resize( mConverter->minimumSize() ); + mConverter->reparent( 0, WStyle_Customize | WStyle_DialogBorder, p, true ); + mConverter->setCaption(kapp->makeStdCaption(i18n("Conversion"))); + } + else + { + mConversionPosition = Embed; + uint utilHeight = mConverter->minimumSize().height(); + QPoint p( 0, height() - utilHeight ); + mConverter->reparent( this, 0, p, true ); + } + + updateLayout(); +} + + +void CHexManagerWidget::setTabBarPosition( EPosition position ) +{ + mTabPosition = position; + if( mTabPosition != HideItem && mTabBar->count() > 0 ) + { + if( mTabPosition == AboveEditor ) + { + mTabBar->setShape( QTabBar::RoundedAbove ); + } + else + { + mTabBar->setShape( QTabBar::RoundedBelow ); + } + mTabBar->show(); + } + else + { + mTabBar->hide(); + } + + updateLayout(); +} + + +void CHexManagerWidget::setSearchBarPosition( EPosition position ) +{ + mSearchBarPosition = position; + if( position != HideItem ) + { + if( mSearchBar == 0 ) + { + mSearchBar = new CSearchBar( this ); + connect( mSearchBar, SIGNAL(hidden()), this, SLOT(searchBarHidden()) ); + connect( mSearchBar, SIGNAL(findData(SSearchControl &, uint, bool)), + mEditor, SLOT(findData(SSearchControl &, uint, bool)) ); + connect( editor()->view(), SIGNAL( cursorChanged( SCursorState & ) ), + mSearchBar, SLOT( cursorMoved() ) ); + } + mSearchBar->show(); + } + else + { + if( mSearchBar != 0 ) + { + mSearchBar->hide(); + } + } + + updateLayout(); +} + + +void CHexManagerWidget::searchBarHidden( void ) +{ + updateLayout(); + mSearchBarPosition = HideItem; + emit searchBarClosed(); +} + + +void CHexManagerWidget::addName( const QString &name ) +{ + if( name.isEmpty() == true ) + { + return; + } + + mTabBar->addName( name ); + if( mTabBar->isVisible() == false && mTabPosition != HideItem ) + { + setTabBarPosition( mTabPosition ); + } +} + + +void CHexManagerWidget::removeName( const QString &name ) +{ + mTabBar->removeName( name ); + if( mTabBar->isVisible() == true && mTabBar->count() == 0 ) + { + setTabBarPosition( mTabPosition ); + } +} + + +void CHexManagerWidget::changeName( const QString &curName, + const QString &newName ) +{ + mTabBar->changeName( curName, newName ); +} + + +void CHexManagerWidget::open( const QString &name ) +{ + mEditor->open( name, false, 0 ); +} + + +int CHexManagerWidget::preferredWidth( void ) +{ + int w = mEditor->defaultTextWidth(); + if( mConversionPosition == Embed ) + { + int converterWidth = mConverter->sizeHint().width(); + w = QMAX( w, converterWidth ); + } + return( w ); +} + + + +CTabBar::CTabBar( QWidget *parent, char *name ) + :QTabBar( parent, name ) +{ + connect( this, SIGNAL(selected(int)), this, SLOT(slotSelected(int)) ); +} + + +void CTabBar::addName( const QString &name ) +{ + QString n( name.right(name.length()-name.findRev('/')-1) ); + + QTab *t = find( n ); + if( t == 0 ) + { + t = new QTab(); + t->setText( n); + int id = addTab( t ); + mFileList.append( CFileKey(name,id) ); + } + setCurrentTab(t); +} + + +void CTabBar::removeName( const QString &name ) +{ + QString n( name.right(name.length()-name.findRev('/')-1) ); + QTab *t = find(n); + if( t == 0 ) + { + return; + } + + QValueList::Iterator it; + for( it = mFileList.begin(); it != mFileList.end(); ++it ) + { + if( (*it).id() == t->identifier() ) + { + mFileList.remove(it); + removeTab(t); + layoutTabs(); + break; + } + } +} + + +void CTabBar::changeName( const QString &curName, const QString &newName ) +{ + QString n( curName.right(curName.length()-curName.findRev('/')-1) ); + QTab *t = find(n); + if( t == 0 ) + { + return; + } + + QValueList::Iterator it; + for( it = mFileList.begin(); it != mFileList.end(); ++it ) + { + if( (*it).id() == t->identifier() ) + { + QString m( newName.right(newName.length()-newName.findRev('/')-1) ); + t->setText(m); + + mFileList.remove(it); + mFileList.append( CFileKey(newName,t->identifier()) ); + layoutTabs(); + update(); // Seems to be necessary + break; + } + } +} + + +QTab *CTabBar::find( const QString &name ) +{ + QPtrList &list = *tabList(); + for( QTab *t = list.first(); t != 0; t = list.next() ) + { + if( t->text() == name ) + { + return( t ); + } + } + + return( 0 ); +} + + +int CTabBar::count( void ) +{ + return( tabList()->count() ); +} + + +void CTabBar::slotSelected( int id ) +{ + QValueList::Iterator it; + for( it = mFileList.begin(); it != mFileList.end(); ++it ) + { + if( (*it).id() == id ) + { + emit selected( (*it).filename() ); + } + } +} + + + + +#include "hexmanagerwidget.moc" diff --git a/khexedit/hexmanagerwidget.h b/khexedit/hexmanagerwidget.h new file mode 100644 index 0000000..08924da --- /dev/null +++ b/khexedit/hexmanagerwidget.h @@ -0,0 +1,202 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_MANAGER_WIDGET_H_ +#define _HEX_MANAGER_WIDGET_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "hexeditorwidget.h" +#include "hextoolwidget.h" + +class CSearchBar; + + +class CFileKey +{ + public: + CFileKey( const QString &fname, int fid ) + { + mFilename = fname; + mId = fid; + } + + CFileKey( const CFileKey & k ) + { + mFilename = k.mFilename; + mId = k.mId; + } + + CFileKey( void ) + { + } + + QString filename( void ) const + { + return( mFilename ); + } + + int id() const + { + return( mId ); + } + + private: + QString mFilename; + int mId; +}; + + + + +class CTabBar : public QTabBar +{ + Q_OBJECT + + public: + CTabBar( QWidget *parent=0, char *name=0 ); + void addName( const QString &name ); + void removeName( const QString &name ); + void changeName( const QString &curName, const QString &newName ); + int count( void ); + + protected slots: + void slotSelected( int id ); + + private: + QTab *find( const QString &name ); + + private: + QValueList mFileList; + + signals: + void selected( const QString &filename ); +}; + + +class CHexManagerWidget : public QWidget +{ + Q_OBJECT + + public: + enum EConversionPosition + { + Hide, + Float, + Embed + }; + + enum EPosition + { + HideItem = 0, + AboveEditor, + BelowEditor + }; + + public: + CHexManagerWidget( QWidget *parent = 0, const char *name = 0, + EConversionPosition state = Embed, + EPosition tabBarPosition = HideItem, + EPosition searchBarPosition = HideItem ); + ~CHexManagerWidget( void ); + + inline bool isValid( void ); + inline CHexEditorWidget *editor( void ); + inline CHexToolWidget *converter( void ); + inline EConversionPosition conversionPosition( void ); + inline EPosition tabBarPosition( void ); + inline EPosition searchBarPosition( void ); + + int preferredWidth( void ); + + public slots: + void setConversionVisibility( EConversionPosition position ); + void setTabBarPosition( EPosition position ); + void setSearchBarPosition( EPosition position ); + void addName( const QString &name ); + void removeName( const QString &name ); + void changeName( const QString &curName, const QString &newName ); + + protected slots: + void open( const QString &name ); + void searchBarHidden( void ); + + private: + void updateLayout( void ); + + signals: + void conversionClosed( void ); + void searchBarClosed( void ); + + private: + bool mValid; + bool mEnableTabBar; + EConversionPosition mConversionPosition; + EPosition mTabPosition; + EPosition mSearchBarPosition; + CHexEditorWidget *mEditor; + CTabBar *mTabBar; + CHexToolWidget *mConverter; + CSearchBar *mSearchBar; +}; + + +inline bool CHexManagerWidget::isValid( void ) +{ + return( mValid ); +} + +inline CHexEditorWidget *CHexManagerWidget::editor( void ) +{ + return( mEditor ); +} + +inline CHexToolWidget *CHexManagerWidget::converter( void ) +{ + return( mConverter ); +} + +inline CHexManagerWidget::EConversionPosition + CHexManagerWidget::conversionPosition( void ) +{ + return( mConversionPosition ); +} + +inline CHexManagerWidget::EPosition CHexManagerWidget::tabBarPosition( void ) +{ + return( mTabPosition ); +} + +inline CHexManagerWidget::EPosition CHexManagerWidget::searchBarPosition(void) +{ + return( mSearchBarPosition ); +} + + + + +#endif + diff --git a/khexedit/hexprinter.cc b/khexedit/hexprinter.cc new file mode 100644 index 0000000..0127751 --- /dev/null +++ b/khexedit/hexprinter.cc @@ -0,0 +1,168 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include "hexprinter.h" + + +CHexPrinter::CHexPrinter( void ) + : KPrinter() +{ +} + + +void CHexPrinter::setPageMarginMM( uint top, uint bottom, int right, int left ) +{ + mPageMargin.top = top; + mPageMargin.left = left; + mPageMargin.bottom = bottom; + mPageMargin.right = right; +} + +void CHexPrinter::setTopMarginMM( uint value ) +{ + mPageMargin.top = value; +} + +void CHexPrinter::setLeftMarginMM( uint value ) +{ + mPageMargin.left = value; +} + +void CHexPrinter::setBottomMarginMM( uint value ) +{ + mPageMargin.bottom = value; +} + +void CHexPrinter::setRightMarginMM( uint value ) +{ + mPageMargin.right = value; +} + + + +void CHexPrinter::setPageHeader( bool enable, uint left, uint center, + uint right, uint line ) +{ + if( left > SPageHeader::FileName ) { left = SPageHeader::NoString; } + if( center > SPageHeader::FileName ) { center = SPageHeader::NoString; } + if( right > SPageHeader::FileName ) { right = SPageHeader::NoString; } + if( line > SPageHeader::Rectangle ) { line = SPageHeader::NoLine; } + + mHeader.enable = enable; + mHeader.pos[0] = (SPageHeader::EHeaderString)left; + mHeader.pos[1] = (SPageHeader::EHeaderString)center; + mHeader.pos[2] = (SPageHeader::EHeaderString)right; + mHeader.line = (SPageHeader::EHeaderLine)line; + + if( mHeader.pos[0] == SPageHeader::NoString && + mHeader.pos[1] == SPageHeader::NoString && + mHeader.pos[2] == SPageHeader::NoString && + mHeader.line == SPageHeader::NoLine ) + { + mHeader.enable = false; + } +} + +void CHexPrinter::setPageFooter( bool enable, uint left, uint center, + uint right, uint line ) +{ + if( left > SPageHeader::FileName ) { left = SPageHeader::NoString; } + if( center > SPageHeader::FileName ) { center = SPageHeader::NoString; } + if( right > SPageHeader::FileName ) { right = SPageHeader::NoString; } + if( line > SPageHeader::Rectangle ) { line = SPageHeader::NoLine; } + + mFooter.enable = enable; + mFooter.pos[0] = (SPageHeader::EHeaderString)left; + mFooter.pos[1] = (SPageHeader::EHeaderString)center; + mFooter.pos[2] = (SPageHeader::EHeaderString)right; + mFooter.line = (SPageHeader::EHeaderLine)line; + + if( mFooter.pos[0] == SPageHeader::NoString && + mFooter.pos[1] == SPageHeader::NoString && + mFooter.pos[2] == SPageHeader::NoString && + mFooter.line == SPageHeader::NoLine ) + { + mFooter.enable = false; + } +} + + +SPageMargin CHexPrinter::pageMargin( void ) +{ + QPaintDeviceMetrics metric( this ); + float f = (float)metric.width()/(float)metric.widthMM(); + + SPageMargin margin; + margin.top = (uint) (f*(float)mPageMargin.top); + margin.right = (uint) (f*(float)mPageMargin.right); + margin.bottom = (uint) (f*(float)mPageMargin.bottom); + margin.left = (uint) (f*(float)mPageMargin.left); + + return( margin ); +} + + +SPageMargin CHexPrinter::pageMarginMM( void ) +{ + return( mPageMargin ); +} + + +SPageSize CHexPrinter::pageFullSize( void ) +{ + QPaintDeviceMetrics metric( this ); + SPageSize size; + size.width = metric.width(); + size.height = metric.height(); + + return( size ); +} + + +SPageSize CHexPrinter::pageUsableSize( void ) +{ + QPaintDeviceMetrics metric( this ); + SPageMargin margin = pageMargin(); + SPageSize size; + + uint mw = margin.left + margin.right; + if( metric.width() <= (int)mw ) + { + size.width = 1; + } + else + { + size.width = metric.width() - mw; + } + + uint mh = margin.top + margin.bottom; + if( metric.height() <= (int)mh ) + { + size.height = 1; + } + else + { + size.height = metric.height() - mh; + } + + return( size ); +} + diff --git a/khexedit/hexprinter.h b/khexedit/hexprinter.h new file mode 100644 index 0000000..2d6eeba --- /dev/null +++ b/khexedit/hexprinter.h @@ -0,0 +1,108 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_PRINTER_H_ +#define _HEX_PRINTER_H_ + +#include +#include + +struct SPageSize +{ + uint width; + uint height; +}; + +struct SPageMargin +{ + uint top; + uint right; + uint bottom; + uint left; +}; + + +struct SPageHeader +{ + enum EHeaderString + { + NoString = 0, + DateTime, + PageNumber, + FileName + }; + + enum EHeaderLine + { + NoLine = 0, + SingleLine, + Rectangle + }; + + bool enable; + EHeaderString pos[3]; // left, center, right + EHeaderLine line; +}; + + + + +class CHexPrinter : public KPrinter +{ + public: + CHexPrinter( void ); + + void setPageMarginMM( uint top, uint bottom, int right, int left ); + void setTopMarginMM( uint value ); + void setLeftMarginMM( uint value ); + void setBottomMarginMM( uint value ); + void setRightMarginMM( uint value ); + void setPageHeader( bool enable, uint left, uint center, uint right, + uint line ); + void setPageFooter( bool enable, uint left, uint center, uint right, + uint line ); + + inline SPageHeader pageHeader( void ); + inline SPageHeader pageFooter( void ); + SPageMargin pageMargin( void ); + SPageMargin pageMarginMM( void ); + SPageSize pageFullSize( void ); + SPageSize pageUsableSize( void ); + + private: + SPageMargin mPageMargin; + SPageHeader mHeader; + SPageHeader mFooter; + + +}; + + +inline SPageHeader CHexPrinter::pageHeader( void ) +{ + return( mHeader ); +} + +inline SPageHeader CHexPrinter::pageFooter( void ) +{ + return( mFooter ); +} + +#endif diff --git a/khexedit/hextoolwidget.cc b/khexedit/hextoolwidget.cc new file mode 100644 index 0000000..f0baf09 --- /dev/null +++ b/khexedit/hextoolwidget.cc @@ -0,0 +1,416 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include + +#include "hextoolwidget.h" +#include +#include +#include +#include +#include + + +CHexToolWidget::CHexToolWidget( QWidget *parent, const char *name ) + : QFrame( parent, name ) +{ + setFrameStyle( QFrame::Panel | QFrame::Raised ); + setLineWidth( 1 ); + + QString text; + mUtilBox = new QGridLayout( this, 5, 4, KDialog::marginHint(), KDialog::spacingHint() ); + mUtilBox->setColStretch( 3, 10 ); + + QString msg1[4] = + { + i18n("Signed 8 bit:"), i18n("Unsigned 8 bit:"), + i18n("Signed 16 bit:"), i18n("Unsigned 16 bit:") + }; + + QString msg2[4] = + { + i18n("Signed 32 bit:"), i18n("Unsigned 32 bit:"), + i18n("32 bit float:"), i18n("64 bit float:") + }; + + QString msg3[4] = + { + i18n("Hexadecimal:"), i18n("Octal:"), + i18n("Binary:"), i18n("Text:") + }; + + QGridLayout *ValuesBox = new QGridLayout( this, 4, 6, 0, KDialog::spacingHint() ); + ValuesBox->setColStretch( 2, 10 ); + ValuesBox->setColStretch( 5, 10 ); + + for( int i=0; i<4; i++ ) + { + QLabel *Label = new QLabel( msg1[i], this ); + Label->setAlignment( AlignRight|AlignVCenter ); + ValuesBox->addWidget( Label, i, 0 ); + + mText1[i] = new QLineEdit( this ); + mText1[i]->setReadOnly( true ); + mText1[i]->setAlignment( AlignRight ); + ValuesBox->addWidget( mText1[i], i, 1 ); + + Label = new QLabel( msg2[i], this ); + Label->setAlignment( AlignRight|AlignVCenter ); + ValuesBox->addWidget( Label, i, 3 ); + + mText2[i] = new QLineEdit( this ); + mText2[i]->setReadOnly( true ); + mText2[i]->setAlignment( AlignRight ); + ValuesBox->addWidget( mText2[i], i, 4 ); + + Label = new QLabel( msg3[i], this ); + Label->setAlignment( AlignRight|AlignVCenter ); + mUtilBox->addWidget( Label, i, 1 ); + + mText3[i] = new QLineEdit( this ); + mText3[i]->setReadOnly( true ); + mText3[i]->setAlignment( AlignRight ); + mUtilBox->addWidget( mText3[i], i, 2 ); + } + + QBoxLayout * SettingsBox = new QHBoxLayout( this, 0, KDialog::spacingHint() ); + + text = i18n("Show little endian decoding"); + mCheckIntelFormat = new QCheckBox( text, this ); + mCheckIntelFormat->setMinimumSize( mCheckIntelFormat->sizeHint() ); + connect( mCheckIntelFormat, SIGNAL(clicked()), this, SLOT(intelFormat()) ); + SettingsBox->addWidget( mCheckIntelFormat, 0, AlignVCenter ); + mCheckIntelFormat->setChecked( // default value to please endian system users +#ifdef WORDS_BIGENDIAN + false // Big Endian: SUN, Motorola machines (amongst others) +#else + true // Little Endian: Intel, Alpha +#endif + ); + // TODO: make this a pulldown box, adding PDP endianess + + text = i18n("Show unsigned as hexadecimal"); + mCheckHexadecimal = new QCheckBox( text, this ); + mCheckHexadecimal->setMinimumSize( mCheckHexadecimal->sizeHint() ); + connect( mCheckHexadecimal, SIGNAL(clicked()), this, SLOT(unsignedFormat()) ); + SettingsBox->addWidget( mCheckHexadecimal, 0, AlignVCenter ); + + mUtilBox->addMultiCellLayout( ValuesBox, 0, 3, 0, 0, AlignLeft|AlignVCenter ); + mUtilBox->addMultiCellLayout( SettingsBox, 4, 4, 0, 0, AlignLeft|AlignVCenter ); + + // + // Variable bitwidth. Based on Craig Graham's work. + // + QLabel *bitLabel = new QLabel( i18n("Stream length:"), this ); + bitLabel->setAlignment( AlignRight|AlignVCenter ); + mUtilBox->addWidget( bitLabel, 4, 1 ); + + mBitCombo = new QComboBox( false, this ); + text = i18n("Fixed 8 Bit" ); + mBitCombo->insertItem( text ); + for( int i=0; i<16; i++ ) + { + text.sprintf("%u ", i+1 ); + text += i==0 ? i18n("Bit Window") : i18n("Bits Window"); + mBitCombo->insertItem( text ); + } + mBitCombo->setMinimumSize( mBitCombo->sizeHint() ); + connect( mBitCombo, SIGNAL(activated(int)), SLOT(bitWidthChanged(int))); + mUtilBox->addWidget( mBitCombo, 4, 2 ); + + /* load font metrics */ + fontChanged(); + + mUtilBox->activate(); + + connect( kapp, SIGNAL( kdisplayFontChanged() ), + SLOT( fontChanged() ) ); + + mCursorState.valid = false; + mViewHexCaps = true; + + setMinimumSize( sizeHint() ); + show(); +} + + +CHexToolWidget::~CHexToolWidget( void ) +{ +} + + +void CHexToolWidget::writeConfiguration( KConfig &config ) +{ + config.setGroup("Conversion" ); + config.writeEntry("LittleEndian", mCheckIntelFormat->isChecked() ); + config.writeEntry("UnsignedAsHex", mCheckHexadecimal->isChecked() ); + config.writeEntry("StreamWindow", mBitCombo->currentItem() ); +} + +void CHexToolWidget::readConfiguration( KConfig &config ) +{ + config.setGroup("Conversion" ); + bool s1 = config.readBoolEntry( "LittleEndian", true ); + bool s2 = config.readBoolEntry( "UnsignedAsHex", false ); + int val = config.readNumEntry( "StreamWindow", 0 ); + + mCheckIntelFormat->setChecked( s1 ); + mCheckHexadecimal->setChecked( s2 ); + mBitCombo->setCurrentItem( val ); +} + +//++cg[6/7/1999]: handler for change signal from bit width combo +void CHexToolWidget::bitWidthChanged( int /*i*/ ) +{ + cursorChanged( mCursorState ); +} + + +// +// Variable bitwidth. Based on Craig Graham's work. +// +// ++cg[6/7/1999]: Read n bit's from a bitstream (allows N length bit +// values to cross byte boundarys). +// +unsigned long CHexToolWidget::bitValue( SCursorState &state, int n ) +{ + static const unsigned char bitmask[9] = + { + 0, 1<<7, 3<<6, 7<<5, 15<<4, 31<<3, 63<<2, 127<<1, 255 + }; + + unsigned long rtn = 0; + unsigned char *byte = state.data; + int bit = 7 - state.cell; + + while( n ) + { + // + // c hold's current byte, shifted to put remaining bits in + // high bits of byte + // + unsigned char c = *byte << bit; + + // + // if there are n bits or more remaining in this byte, we + // swallow n bits, otherwise we swallow as many + // bits as we can (8-bit) + // + int this_time = ((8-bit)>=n)?n:(8-bit); + + // + // mask to get only the bit's we're swallowing + // + c &= bitmask[this_time]; + + // + // shift down to get bit's in low part of byte + // + c >>= 8-this_time; + + // + // shift up previous results to make room and OR in the extracted bits. + // + rtn = (rtn<isChecked() ) + { + // take it as it is + memcpy( Data.b, state.data, 8 ); + P8Bit = P16Bit = P32Bit = P64Bit = Data.b; + } + else + { + // reverse order + for( int i=0,j=7; i<8; ++i,--j ) + Data.b[i] = state.data[j]; + + P8Bit = &Data.b[7]; + P16Bit = &Data.b[6]; + P32Bit = &Data.b[4]; + P64Bit = Data.b; + } + + bool NoHex = !mCheckHexadecimal->isChecked(); + + // unsigned 8 bit + buf.sprintf( NoHex?"%u":mViewHexCaps?"0x%02X":"0x%02x", *(unsigned char*)P8Bit ); + mText1[1]->setText( buf ); + // signed int 8 bit + buf.sprintf( "%d", *(signed char*)P8Bit ); + mText1[0]->setText( buf ); + + // unsigned int 16 bit + buf.sprintf( NoHex?"%u":mViewHexCaps?"0x%04X":"0x%04x", *(unsigned short*)P16Bit ); + mText1[3]->setText( buf ); + // signed int 16 bit + buf.sprintf( "%d", *(short*)P16Bit ); + mText1[2]->setText( buf ); + + // unsigned int 32 bit + buf.sprintf( NoHex?"%u":mViewHexCaps?"0x%08X":"0x%08x", *(unsigned int*)P32Bit ); + mText2[1]->setText( buf ); + // signed int 32 bit + buf.sprintf( "%d", *(int*)P32Bit ); + mText2[0]->setText( buf ); + + // float 32 bit + buf.sprintf( "%E", *(float*)P32Bit ); + mText2[2]->setText( buf ); + // float 64 bit + buf.sprintf( "%E", *(double*)P64Bit ); + mText2[3]->setText( buf ); + + int numBits = mBitCombo->currentItem(); + if( numBits == 0 ) + { + // + // This is the original stuff + // + unsigned char data = (unsigned char)state.data[0]; + buf.sprintf( mViewHexCaps?"%02X":"%02x", data ); + mText3[0]->setText( buf ); + buf.sprintf( "%03o", data ); + mText3[1]->setText( buf ); + + char bitBuf[32]; + for( int i = 0; i < 8; i++ ) + bitBuf[7-i] = (data&(1<setText( QString(bitBuf) ); + } + else + { + // + // Variable bitwidth. Based on Craig Graham's work. + // + unsigned long data = bitValue( state, numBits ); + buf.sprintf( mViewHexCaps?"%02lX %02lX":"%02lx %02lx", (data>>8)&0xFF, data&0xFF ); + mText3[0]->setText( buf ); + buf.sprintf( "%03lo %03lo", (data>>8)&0xFF, data&0xFF ); + mText3[1]->setText( buf ); + char bitBuf[32]; + for( int i = 0; isetText( QString(bitBuf) ); + } + + // Fix by Sergey A. Sukiyazov + unsigned char data[2] = { 0, 0 }; + data[0] = state.charValid == false ? '.' : + (char)((unsigned char)state.data[0]&0xff ); + buf = QString::fromLocal8Bit( (const char *)data ); + + mText3[3]->setText( buf ); + } + else + { + QString str; + for( int i=0; i<4; i++) + { + mText1[i]->setText( str ); + mText2[i]->setText( str ); + mText3[i]->setText( str ); + } + } + + mCursorState = state; +} + + +void CHexToolWidget::fontChanged( void ) +{ + QFontMetrics fm( mText1[0]->font() ); + int W1 = fm.width( "XXXXXXXX" ); + int W2 = fm.width( "XXXXXXXXXXXX" ); + int W3 = fm.width( "888888888888888888" ); + for( int i=0; i<4; i++ ) + { + mText1[i]->setFixedWidth( W1 ); + mText2[i]->setFixedWidth( W2 ); + mText3[i]->setFixedWidth( W3 ); + } +} + + +void CHexToolWidget::intelFormat( void ) +{ + cursorChanged( mCursorState ); +} + + +void CHexToolWidget::unsignedFormat( void ) +{ + cursorChanged( mCursorState ); +} + + +void CHexToolWidget::resizeEvent( QResizeEvent */*e*/ ) +{ +} + + + +void CHexToolWidget::closeEvent( QCloseEvent *e ) +{ + e->accept(); + emit closed(); +} + +#include "hextoolwidget.moc" diff --git a/khexedit/hextoolwidget.h b/khexedit/hextoolwidget.h new file mode 100644 index 0000000..d2ce892 --- /dev/null +++ b/khexedit/hextoolwidget.h @@ -0,0 +1,81 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_TOOL_WIDGET_H_ +#define _HEX_TOOL_WIDGET_H_ + +#include + +class QGridLayout; +class QComboBox; +class QLineEdit; +class QCheckBox; + +#include "hexbuffer.h" +#include + +class CHexToolWidget : public QFrame +{ + Q_OBJECT + + public: + CHexToolWidget( QWidget *parent = 0, const char *name = 0 ); + ~CHexToolWidget( void ); + + void writeConfiguration( KConfig &config ); + void readConfiguration( KConfig &config ); + unsigned long bitValue( SCursorState &state, int n ); + + protected: + void resizeEvent( QResizeEvent *e ); + void closeEvent( QCloseEvent *e ); + + public slots: + void cursorChanged( SCursorState &state ); + void fontChanged( void ); + void intelFormat( void ); + void unsignedFormat( void ); + void bitWidthChanged( int i ); + + signals: + void closed( void ); + + + private: + + private: + SCursorState mCursorState; + bool mViewHexCaps; + + QGridLayout *mUtilBox; + QLineEdit *mText1[4]; + QLineEdit *mText2[4]; + QLineEdit *mText3[4]; + QCheckBox *mCheckIntelFormat; + QCheckBox *mCheckHexadecimal; + QComboBox *mBitCombo; +}; + + + + + + +#endif diff --git a/khexedit/hexvalidator.cc b/khexedit/hexvalidator.cc new file mode 100644 index 0000000..e8c1731 --- /dev/null +++ b/khexedit/hexvalidator.cc @@ -0,0 +1,329 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include "hexvalidator.h" + +CHexValidator::CHexValidator( QWidget *parent, EState state, + const char *name ) + :QValidator( parent, name ) +{ + setState( state ); +} + +CHexValidator::~CHexValidator( void ) +{ +} + +QValidator::State CHexValidator::validate( QString &string, int &/*pos*/ ) const +{ + if( mState == hexadecimal ) + { + for( uint i=0; i < string.length(); i++ ) + { + int val = string[i].latin1(); + if( isxdigit( val ) == 0 && isspace( val ) == 0 ) + { + return( QValidator::Invalid ); + } + } + return( QValidator::Valid ); + } + if( mState == decimal ) + { + for( uint i=0; i < string.length(); i++ ) + { + int val = string[i].latin1(); + if( isdigit( val ) == 0 && isspace( val ) == 0 ) + { + return( QValidator::Invalid ); + } + } + return( QValidator::Valid ); + } + else if( mState == octal ) + { + for( uint i=0; i < string.length(); i++ ) + { + int val = string[i].latin1(); + if( (isdigit( val ) == 0 || val == '8' || val == '9') && + isspace( val ) == 0 ) + { + return( QValidator::Invalid ); + } + } + return( QValidator::Valid ); + } + else if( mState == binary ) + { + for( uint i=0; i < string.length(); i++ ) + { + int val = string[i].latin1(); + if( val != '0' && val != '1' && isspace( val ) == 0 ) + { + return( QValidator::Invalid ); + } + } + return( QValidator::Valid ); + } + else if( mState == regularText ) + { + return( QValidator::Valid ); + } + else + { + return( QValidator::Invalid ); + } + +} + + +void CHexValidator::setState( EState state ) +{ + mState = state; +} + + +void CHexValidator::convert( QByteArray &dest, const QString &src ) +{ + uint value; + uint k=0; + + if( mState == hexadecimal ) + { + dest.resize(0); + + char buf[3]; + for( uint i=0; i < src.length(); i++ ) + { + int val = src[i].latin1(); + if( isxdigit(val) ) + { + buf[k++] = val; + if( k == 2 ) + { + buf[k] = 0; + sscanf( buf, "%X", &value ); + + dest.resize( dest.size()+1 ); + dest[ dest.size()-1 ] = value; + k = 0; + } + } + } + + if( k == 1 ) + { + buf[1] = buf[0]; + buf[0] = '0'; + buf[2] = 0; + sscanf( buf, "%X", &value ); + + dest.resize( dest.size()+1 ); + dest[ dest.size()-1 ] = value; + } + + } + else if( mState == decimal ) + { + dest.resize(0); + + char buf[4]; + for( uint i=0; i < src.length(); i++ ) + { + int val = src[i].latin1(); + if( isdigit(val) ) + { + buf[k++] = val; + if( k == 3 ) + { + buf[k] = 0; + sscanf( buf, "%u", &value ); + + dest.resize( dest.size()+1 ); + dest[ dest.size()-1 ] = value; + k = 0; + } + } + } + + if( k == 1 || k == 2 ) + { + if( k == 1 ) + { + buf[2] = buf[0]; + buf[0] = buf[1] = '0'; + } + else + { + buf[2] = buf[1]; + buf[1] = buf[0]; + buf[0] = '0'; + } + buf[3] = 0; + sscanf( buf, "%u", &value ); + + dest.resize( dest.size()+1 ); + dest[ dest.size()-1 ] = value; + } + } + + else if( mState == octal ) + { + dest.resize(0); + + char buf[4]; + for( uint i=0; i < src.length(); i++ ) + { + int val = src[i].latin1(); + if( isdigit(val) ) + { + buf[k++] = val; + if( k == 3 ) + { + if( buf[0] > '3' ) { buf[0] = '3'; } + buf[k] = 0; + sscanf( buf, "%o", &value ); + + dest.resize( dest.size()+1 ); + dest[ dest.size()-1 ] = value; + k = 0; + } + } + } + + if( k == 1 || k == 2 ) + { + if( k == 1 ) + { + buf[2] = buf[0]; + buf[0] = buf[1] = '0'; + } + else + { + buf[2] = buf[1]; + buf[1] = buf[0]; + buf[0] = '0'; + } + buf[3] = 0; + sscanf( buf, "%o", &value ); + + dest.resize( dest.size()+1 ); + dest[ dest.size()-1 ] = value; + } + } + else if( mState == binary ) + { + dest.resize(0); + + char buf[9]; + for( uint i=0; i < src.length(); i++ ) + { + int val = src[i].latin1(); + if( isdigit(val) ) + { + buf[k++] = val; + if( k == 8 ) + { + value = 0; + for( uint j=0; j < 8; j++ ) + { + value |= (buf[8-j-1] == '1') ? 1< 0 ) + { + value = 0; + for( uint j=0; j < k; j++ ) + { + value |= (buf[k-j-1] == '1') ? 1<= destLen ) + return src; + + QString zeroes; + zeroes.fill( '0', destLen - src.length() ); + return zeroes + src; +} +#include "hexvalidator.moc" diff --git a/khexedit/hexvalidator.h b/khexedit/hexvalidator.h new file mode 100644 index 0000000..cfe9f95 --- /dev/null +++ b/khexedit/hexvalidator.h @@ -0,0 +1,63 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_VALIDATOR_H_ +#define _HEX_VALIDATOR_H_ + +#include + +class CHexValidator: public QValidator +{ + Q_OBJECT + + public: + enum EState + { + hexadecimal = 0, + decimal, + octal, + binary, + regularText + }; + + public: + CHexValidator( QWidget *parent, EState state, const char *name = 0 ); + ~CHexValidator( void ); + QValidator::State validate( QString &string, int &pos ) const; + void setState( EState state ); + void convert( QByteArray &dest, const QString &src ); + void format( QString &dest, const QByteArray &src ); + + private: + /** + * Returns a string that is at least as long as @p destLen number of characters, + * by adding zeroes to the left as necessary. + * + * e.g. zeroExtend( "32", 3 ) => "032" + */ + QString zeroExtend( const QString &src, unsigned destLen ) const; + + EState mState; + + +}; + + +#endif diff --git a/khexedit/hexviewwidget.cc b/khexedit/hexviewwidget.cc new file mode 100644 index 0000000..12226ed --- /dev/null +++ b/khexedit/hexviewwidget.cc @@ -0,0 +1,2286 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include +#include + + +#include +#include +#include +#include +#include + +#include "hexdrag.h" +#include "hexerror.h" +#include "hexviewwidget.h" + +// +// The usage of the WNorthWestGravity flag should make screen update +// faster (less paintEvents). I have had to add update() some places +// to ensure proper redrawing. Undefine if something goes wrong +// (i.e. not updated ) +// +#define USE_NORTHWEST_GRAVITY 1 + +// +// I don't want to decide what is best: Drag starts when mouse is moved or +// after a timeout. +// +#define USE_DRAG_MOVEMENT 1 + + + + + + +CDragManager::CDragManager( void ) +{ + mActivateMode = Movement; + mPending = false; + mTimerId = 0; +} + +void CDragManager::setActivateMode( EDragActivateMode mode ) +{ + clear(); + mActivateMode = mode; // Movement or Timer +} + +void CDragManager::setup( int x, int y ) +{ + if( mActivateMode == Movement ) + { + mOrigin.setX(x); + mOrigin.setY(y); + } + else + { + setupTimer(); + } + mPending = true; +} + +bool CDragManager::start( QMouseEvent *e ) +{ + if( mPending == false ) + { + return( false ); + } + + if( mActivateMode == Movement ) + { + if( (mOrigin - e->pos()).manhattanLength() > KGlobalSettings::dndEventDelay() ) + { + mPending = false; + emit startDrag( e->state() & ShiftButton ? true : false ); + } + return( true ); + } + else // Timer + { + if( mTimerId != 0 ) + { + removeTimer(); + mPending = false; + emit startDrag( e->state() & ShiftButton ? true : false ); + return( true ); + } + else + { + // Should never happen! + mPending = false; + return( false ); + } + } + +} + +bool CDragManager::clear( void ) +{ + if( mPending == false ) + { + return( false ); + } + + if( mActivateMode == Timer ) + { + removeTimer(); + } + + mPending = false; + return( true ); +} + +void CDragManager::timerEvent( QTimerEvent *e ) +{ + if( e->timerId() == mTimerId ) + { + removeTimer(); + if( mPending == true ) + { + mPending = false; + emit startDrag( ( kapp->keyboardModifiers() & KApplication::ShiftModifier ) ); + } + } +} + +void CDragManager::removeTimer( void ) +{ + if( mTimerId != 0 ) + { + killTimer( mTimerId ); + mTimerId = 0; + } +} + +void CDragManager::setupTimer( void ) +{ + if( mTimerId != 0 ) + { + killTimer( mTimerId ); + mTimerId = 0; + } + mTimerId = startTimer( 500 ); +} + + +// +// This widget will use the entire space of the parent widget +// +CHexViewWidget::CHexViewWidget( QWidget *parent, const char *name, + CHexBuffer *hexBuffer ) + : QFrame( parent, name, + #ifdef USE_NORTHWEST_GRAVITY + Qt::WStaticContents + #else + 0 + #endif + ), mScrollBarSize( 16 ) +{ + if( parent == 0 || hexBuffer == 0 ) { return; } + + // + // Qt 2.0: + // ------- + // I use the "CScrollBar" because sometimes (very seldom) when I + // do a mHorzScroll->hide() the mHorzScroll->isVisible() remains true + // in updateView() for a short while. I need the correct visibility + // because I have to redraw the area - due to the "WNorthWestGravity" usage. + // + // I tried to do a + // "while( mHorzScroll->isVisible() ) { mHorzScroll->hide(); }" + // but then the loop never ended. The "CScrollBar" emits a "hidden()" + // signal whenever is receives a QHideEvent. + // + + mVertScroll = new CScrollBar( QScrollBar::Vertical, this ); + if( mVertScroll == 0 ) { return; } + mHorzScroll = new CScrollBar( QScrollBar::Horizontal, this ); + if( mHorzScroll == 0 ) { return; } + mCorner = new QWidget( this ); + if( mCorner == 0 ) { return; } + connect( mHorzScroll, SIGNAL(valueChanged(int)), SLOT(changeXPos(int)) ); + connect( mVertScroll, SIGNAL(valueChanged(int)), SLOT(changeYPos(int)) ); + connect( mHorzScroll, SIGNAL(hidden()), SLOT(update()) ); + connect( mVertScroll, SIGNAL(hidden()), SLOT(update()) ); + mHorzScroll->hide(); + mVertScroll->hide(); + + mDragManager = new CDragManager(); + if( mDragManager == 0 ) { return; } + #ifdef USE_DRAG_MOVEMENT + mDragManager->setActivateMode( CDragManager::Movement ); + #else + mDragManager->setActivateMode( CDragManager::Timer ); + #endif + connect( mDragManager, SIGNAL(startDrag(bool)), SLOT(startDrag(bool)) ); + + setFrameStyle( QFrame::WinPanel|QFrame::Sunken ); + setWFlags( WResizeNoErase ); + setFocusPolicy( StrongFocus ); + + mHexBuffer = hexBuffer; + mHexBuffer->cursorReset(); + + mEditMode = mHexBuffer->editMode(); + mShowCursor = false; + mCursorTimerId = 0; + + mDocumentMenu = 0; + + setTextBufferSize(); // Make sure there is a pixmap buffer + setStartX(0); + setStartY(0); + + setAcceptDrops(true); + setDropHighlight(false); // Init state + frame shape + setBackgroundColor( mHexBuffer->backgroundColor() ); +} + + +CHexViewWidget::~CHexViewWidget( void ) +{ + delete mVertScroll; + delete mHorzScroll; + delete mCorner; + delete mDragManager; +} + + +int CHexViewWidget::readFile( QFile &file, const QString &url, CProgress &p ) +{ + int errCode = mHexBuffer->readFile( file, url, p ); + if( errCode != Err_Success ) + { + return( errCode ); + } + + initFile(); + return( Err_Success ); +} + + +int CHexViewWidget::insertFile( QFile &file, CProgress &p ) +{ + int errCode = mHexBuffer->insertFile( file, p ); + if( errCode != Err_Success ) + { + return( errCode ); + } + + updateWindow( true, true ); + + emit dataChanged(); + emit cursorChanged( mHexBuffer->cursorState() ); + emit layoutChanged( mLayout ); + return( Err_Success ); +} + + +int CHexViewWidget::newFile( const QString &url ) +{ + int errCode = mHexBuffer->newFile( url ); + if( errCode != Err_Success ) + { + return( errCode ); + } + + initFile(); + return( Err_Success ); +} + + +int CHexViewWidget::writeFile( QFile &file, CProgress &p ) +{ + int errCode = mHexBuffer->writeFile( file, p ); + if( errCode == Err_Success ) + { + emit fileState( mHexBuffer->fileState() ); + } + return( errCode ); +} + + +void CHexViewWidget::closeFile( void ) +{ + emit fileClosed( mHexBuffer->url() ); + mHexBuffer->closeFile(); + initFile(); +} + + + +void CHexViewWidget::initFile( void ) +{ + setStartX(0); + setStartY(0); + + mHexBuffer->cursorReset(); + mHexBuffer->setLayout( mLayout ); + mHexBuffer->setFont( mFontInfo ); + setEditMode( mEditMode ); + setColor( mColor, false ); + setCursor( mCursor, false ); + setMisc( mMisc ); + + setBackgroundColor( mHexBuffer->backgroundColor() ); + setBackgroundMode( NoBackground ); + + updateView( true, false ); + resizeEvent( 0 ); + + emit dataChanged(); + emit cursorChanged( mHexBuffer->cursorState() ); + emit fileState( mHexBuffer->fileState() ); + emit encodingChanged( mHexBuffer->encoding() ); + emit fileName( mHexBuffer->url(), mHexBuffer->hasFileName() ); + emit bookmarkChanged( mHexBuffer->bookmarkList() ); +} + + +void CHexViewWidget::setBuffer( CHexBuffer *hexBuffer ) +{ + if( hexBuffer == 0 || mHexBuffer == hexBuffer ) + { + return; + } + + unselect(); + unmark(); + + mHexBuffer = hexBuffer; + mHexBuffer->setLayout( mLayout ); + mHexBuffer->setFont( mFontInfo ); + setEditMode( mEditMode ); + setColor( mColor, false ); + setCursor( mCursor, false ); + setMisc( mMisc ); + + if( mLayout.lockLine == false ) + { + mHexBuffer->matchWidth( width() ); + } + + setBackgroundColor( hexBuffer->backgroundColor() ); + setBackgroundMode( NoBackground ); + + setEditMode( mEditMode ); + updateWindow(); + + emit dataChanged(); + emit cursorChanged( mHexBuffer->cursorState() ); + emit fileState( mHexBuffer->fileState() ); + emit encodingChanged( mHexBuffer->encoding() ); + emit layoutChanged( mLayout ); + emit inputModeChanged( mHexBuffer->inputMode() ); + emit fileName( mHexBuffer->url(), mHexBuffer->hasFileName() ); + emit bookmarkChanged( mHexBuffer->bookmarkList() ); +} + + + + +void CHexViewWidget::changeXPos( int p ) +{ + int dx = startX() - p; + setStartX(p); + + + if( QABS(dx) < width() ) + { + scroll( dx, 0, contentsRect() ); + } + else + { + QWidget::update(); + } + + // + // If the start position has become 0, then update the view. This + // will remove the scrollbar (if it is visible) if the textarea width + // is wider than the text. The scrollbar will then disappear under the + // mouse pointer. + // + if( startX() == 0 ) + { + updateView( false, false ); + } + +} + + +void CHexViewWidget::changeYPos( int p ) +{ + int dy = startY() - p; + setStartY(p); + + if( QABS( dy ) < height() ) + { + scroll( 0, dy, contentsRect() ); + } + else + { + QWidget::update(); + } + + // + // If the start position has become 0, then update the view. This + // will remove the scrollbar (if it is visible) if the textarea height + // is taller than the text. The scrollbar will then disappear under the + // mouse pointer. + // + if( startY() == 0 ) + { + updateView( false, false ); + } +} + + +void CHexViewWidget::clipboardChanged( void ) +{ + disconnect(QApplication::clipboard(),SIGNAL(dataChanged()), + this,SLOT(clipboardChanged())); + unselect(); +} + +void CHexViewWidget::paletteChanged( void ) +{ + setColor( mColor, true ); +} + + +void CHexViewWidget::fontChanged( void ) +{ + //setFont( kapp->fixedFont, true ); +} + +void CHexViewWidget::filter( SFilterControl &fc ) +{ + int errCode = mHexBuffer->filter( fc ); + if( errCode == Err_Success ) + { + repaint(); + emit dataChanged(); + emit cursorChanged( mHexBuffer->cursorState() ); + } +} + + + +void CHexViewWidget::insert( SInsertData &id ) +{ + if( id.onCursor == false ) + { + mHexBuffer->cursorGoto( id.offset, 7 ); + } + SCursorConfig cc; + updateCursor( cc, true ); + + if( id.size == 0 ) + { + return; + } + + QByteArray buf( id.size ); + if( buf.isNull() == true ) + { + return; + } + buf.fill( 0 ); + + if( id.pattern.size() > 0 ) + { + uint size = id.pattern.size()>buf.size() ? buf.size() : id.pattern.size(); + if( id.repeatPattern == false ) + { + memcpy( &buf[0], &id.pattern[0], size ); + if( size < buf.size() ) + { + memset( &buf[size], id.pattern[id.pattern.size()-1], buf.size()-size ); + } + } + else + { + for( uint i=0; i < buf.size(); i+= size ) + { + uint s = i+size > buf.size() ? buf.size()-i : size; + memcpy( &buf[i], &id.pattern[0], s ); + } + } + } + + insert( buf ); +} + + +void CHexViewWidget::insert( const QByteArray &buf ) +{ + if( mHexBuffer->documentPresent() == false ) + { + emit pleaseOpenNewFile(); + if( mHexBuffer->documentPresent() == false ) + { + return; + } + } + + uint offset = mHexBuffer->cursorOffset(); + int errCode = mHexBuffer->inputAtCursor( buf, 0 ); + if( errCode == Err_Success ) + { + updateWindow( offset, true ); + emit dataChanged(); + } +} + + +void CHexViewWidget::append( const QByteArray &buf ) +{ + if( mHexBuffer->documentPresent() == false ) + { + insert( buf ); + } + else + { + SCursorConfig cc; + cc.emulateControlButton( true ); + cursorEnd( cc ); + + int errCode = mHexBuffer->inputAtCursor( buf, 0 ); + if( errCode == Err_Success ) + { + updateWindow( true, true ); + emit dataChanged(); + } + } +} + + +void CHexViewWidget::valueOnCursor( QByteArray &buf, uint size ) +{ + mHexBuffer->valueOnCursor( buf, size ); +} + + + +void CHexViewWidget::updateView( bool redraw, bool fixCursor ) +{ + int f2 = frameWidth() * 2; + int scrollBarCount = 0; // Number of visible scrollbars + int editWidth = 0; + int editHeight = 0; + + for( uint i=0; i < 2; i++ ) + { + editWidth = width() - f2; // Total available width + editHeight = height() - f2; // Total available height + int textWidth = dataWidth(); + int textHeight = mHexBuffer->totalHeight(); + + // + // This will move the start position of the horizontal scrollbar + // to the left (if possible) if the text width is smaller than the + // edit width. + // + if( startX() > 0 ) + { + int size = mVertScroll->isVisible() == true ? mScrollBarSize : 0; + if( startX() + editWidth - size > textWidth ) + { + int position = textWidth - editWidth + size; + setStartX( position > 0 ? position : 0 ); + #ifdef USE_NORTHWEST_GRAVITY + redraw = true; + #endif + } + } + + int tooMuchX = textWidth - editWidth; + bool horzScrollbarVisible = startX() > 0 || tooMuchX > 0 ? true : false; + if( horzScrollbarVisible == true ) + { + editHeight -= mScrollBarSize; + } + + + // + // This will move the start position of the vertical scrollbar + // to the top (if possible) if the text height is smaller than the + // edit height. + // + if( startY() > 0 ) + { + if( startY() + editHeight > textHeight ) + { + int position = textHeight - editHeight; + setStartY( position > 0 ? position : 0 ); + #ifdef USE_NORTHWEST_GRAVITY + redraw = true; + #endif + } + } + + int tooMuchY = textHeight - editHeight; + int startLine = startY() / textHeight; + + if( startLine > 0 || tooMuchY > 0 ) + { + editWidth -= mScrollBarSize; + tooMuchX += mScrollBarSize; + if( horzScrollbarVisible == false && tooMuchX > 0 ) + { + // Horizontal scrollbar will be visible after all. + editHeight -= mScrollBarSize; + tooMuchY += mScrollBarSize; + } + } + + if( tooMuchX < startX() ) { tooMuchX = startX(); } + if( tooMuchY < startY() ) { tooMuchY = startY(); } + + scrollBarCount = 0; + if( tooMuchX > 0 && documentPresent() == true ) + { + mHorzScroll->blockSignals( true ); + mHorzScroll->setGeometry( 0, editHeight+f2, editWidth+f2,mScrollBarSize); + mHorzScroll->setRange( 0, tooMuchX ); + mHorzScroll->setValue( startX() ); + mHorzScroll->setSteps(mHexBuffer->lineHeight(),editWidth-mScrollBarSize); + mHorzScroll->blockSignals( false ); + if( mHorzScroll->isVisible() == false ) { mHorzScroll->show(); } + scrollBarCount ++; + } + else + { + if( mHorzScroll->isVisible() == true ) { mHorzScroll->hide(); } + } + + if( tooMuchY > 0 && documentPresent() == true ) + { + mVertScroll->blockSignals( true ); + mVertScroll->setGeometry( editWidth+f2, 0, mScrollBarSize,editHeight+f2); + mVertScroll->setRange( 0, tooMuchY ); + mVertScroll->setValue( startY() ); + mVertScroll->setSteps(mHexBuffer->lineHeight(), + editHeight-mScrollBarSize ); + mVertScroll->blockSignals( false ); + if( mVertScroll->isVisible() == false ) { mVertScroll->show(); } + scrollBarCount ++; + } + else + { + if( mVertScroll->isVisible() == true ) { mVertScroll->hide(); } + } + + if( fixCursor == true ) + { + int position = mHexBuffer->cursorFixedPosition( startY(), height() ); + if( position != startY() ) + { + setStartY( position ); + fixCursor = false; + continue; + } + } + break; + } + + + if( scrollBarCount == 2 ) + { + mCorner->setGeometry( editWidth+f2, editHeight+f2, mScrollBarSize, + mScrollBarSize ); + mCorner->show(); + } + else + { + mCorner->hide(); + } + + + updateFrameSize(); + + if( redraw == true ) + { + QWidget::update(); + } +} + + +void CHexViewWidget::setPalette( const QPalette &p ) +{ + QWidget::setPalette( p ); + mCorner->setPalette( p ); + mVertScroll->setPalette( p ); + mHorzScroll->setPalette( p ); +} + + +void CHexViewWidget::setLayout( SDisplayLayout &layout ) +{ + mLayout = layout; + mHexBuffer->setLayout( mLayout ); + updateWindow(); + + emit layoutChanged( mLayout ); + emit cursorChanged( mHexBuffer->cursorState() ); + emit textWidth( defaultWidth() ); +} + + +void CHexViewWidget::setInputMode( SDisplayInputMode &input ) +{ + mHexBuffer->setInputMode( input ); + emit inputModeChanged( mHexBuffer->inputMode() ); +} + + +void CHexViewWidget::setCursor( const SDisplayCursor &cursor, + bool /*updateDisplay*/ ) +{ + mCursor = cursor; + mHexBuffer->setCursorShapeModifier( cursor.alwaysBlockShape, + cursor.thickInsertShape ); + setupCursorTimer(); + redrawFromOffset( mHexBuffer->cursorOffset(), false ); +} + +void CHexViewWidget::setColor( const SDisplayColor &color, + bool updateDisplay ) +{ + mColor = color; + mHexBuffer->setColor( mColor ); + if( updateDisplay == true ) + { + repaint(); + } +} + +void CHexViewWidget::setFont( const SDisplayFontInfo &fontInfo, + bool updateDisplay ) +{ + mFontInfo = fontInfo; + mHexBuffer->setFont( mFontInfo ); + emit textWidth( defaultWidth() ); + if( updateDisplay == true ) + { + updateWindow(); + } +} + + + +void CHexViewWidget::setMisc( SDisplayMisc &misc ) +{ + mMisc = misc; + mHexBuffer->setUndoLevel( misc.undoLevel ); + mHexBuffer->setSoundState( misc.inputSound, misc.fatalSound ); + mHexBuffer->setBookmarkVisibility( misc.bookmarkOffsetColumn, + misc.bookmarkEditor ); + if( mHexBuffer->documentPresent() == true ) + { + QWidget::update(); + } +} + + +void CHexViewWidget::setInsertMode( bool insertMode ) +{ + setEditMode( insertMode == true ? CHexBuffer::EditInsert : + CHexBuffer::EditReplace ); +} + + +int CHexViewWidget::setEncoding( CConversion::EMode mode, CProgress &p ) +{ + int errCode = mHexBuffer->setEncoding( mode, p ); + if( errCode == Err_Success ) + { + repaint(); + emit cursorChanged( mHexBuffer->cursorState() ); + emit encodingChanged( mHexBuffer->encoding() ); + } + return( errCode ); +} + + +void CHexViewWidget::reportEncoding( void ) +{ + emit encodingChanged( mHexBuffer->encoding() ); +} + + +void CHexViewWidget::selectAll( void ) +{ + setSelection( 0, true ); + setSelection( mHexBuffer->documentSize(), false ); + autoCopy(); + emit cursorChanged( mHexBuffer->cursorState() ); +} + +void CHexViewWidget::unselect( void ) +{ + setSelection( 0, true ); + emit cursorChanged( mHexBuffer->cursorState() ); +} + +void CHexViewWidget::unmark( void ) +{ + setMark( 0, 0, false ); +} + + +int CHexViewWidget::findFirst( SSearchControl &sc ) +{ + int errCode = mHexBuffer->findFirst( sc ); + if( errCode == Err_Success ) { updateWindow( true, false ); } + return( errCode ); +} + +int CHexViewWidget::findNext( SSearchControl &sc ) +{ + int errCode = mHexBuffer->findNext( sc ); + if( errCode == Err_Success ) { updateWindow( true, false ); } + return( errCode ); +} + +int CHexViewWidget::findWrap( SSearchControl &sc ) +{ + int errCode = mHexBuffer->findWrap( sc ); + if( errCode == Err_Success ) { updateWindow( true, false ); } + return( errCode ); +} + +int CHexViewWidget::replaceAll( SSearchControl &sc, bool init ) +{ + int errCode = mHexBuffer->replaceAll( sc, init ); + if( errCode == Err_Success ) + { + updateWindow( true, false ); + emit dataChanged(); + } + return( errCode ); +} + +int CHexViewWidget::replaceMarked( SSearchControl &sc ) +{ + int errCode = mHexBuffer->replaceMarked( sc ); + if( errCode == Err_Success ) + { + updateWindow( true, false ); + emit dataChanged(); + } + return( errCode ); +} + +int CHexViewWidget::collectStrings( CStringCollectControl &sc ) +{ + int errCode = mHexBuffer->collectStrings( sc ); + return( errCode ); +} + + +int CHexViewWidget::collectStatistic( SStatisticControl &sc, CProgress &p ) +{ + int errCode = mHexBuffer->collectStatistic( sc, p ); + return( errCode ); +} + + +void CHexViewWidget::gotoOffset( uint offset, uint bit, bool fromCursor, + bool forward ) +{ + bool reverse = forward == true ? false : true; + mHexBuffer->cursorGoto( offset, bit, reverse, fromCursor ); + updateWindow( true, false ); +} + + +void CHexViewWidget::gotoOffset( uint offset ) +{ + gotoOffset( offset, 7, true, true ); +} + + +int CHexViewWidget::print( CHexPrinter &printer, CProgress &p ) +{ + return( mHexBuffer->print( printer, p ) ); +} + + +uint CHexViewWidget::numPage( CHexPrinter &printer ) +{ + return( mHexBuffer->numPage( printer ) ); +} + + +int CHexViewWidget::exportText( const SExportText &ex, CProgress &p ) +{ + return( mHexBuffer->exportText( ex, p ) ); +} + + +int CHexViewWidget::exportHtml( const SExportHtml &ex, CProgress &p ) +{ + return( mHexBuffer->exportHtml( ex, p ) ); +} + + +int CHexViewWidget::exportCArray( const SExportCArray &ex, CProgress &p ) +{ + return( mHexBuffer->exportCArray( ex, p ) ); +} + + +void CHexViewWidget::startDrag( bool asText ) +{ + QByteArray buf; + if( asText == true ) + { + if( mHexBuffer->copySelectedText( buf ) != Err_Success ) + { + return; + } + QDragObject *d = new QTextDrag( buf.data(), this ); + d->dragCopy(); + } + else + { + if( mHexBuffer->copySelectedData( buf ) != Err_Success ) + { + return; + } + QDragObject *d = new CHexDrag( buf, this ); + d->dragCopy(); + } +} + + + +void CHexViewWidget::copy( void ) +{ + QByteArray buf; + if( mHexBuffer->copySelectedData( buf ) != Err_Success ) + { + return; + } + disconnect(QApplication::clipboard(),SIGNAL(dataChanged()), + this,SLOT(clipboardChanged())); + // + // Note: Do no give the CHexDrag a parent != 0. The clipboard + // owns the current dragdata and will destroy it on exit or + // when it receives a new object. If the CHexDrag has a parent + // != 0, the CHexDrag object will be destroyed when the parent + // is destroyed. We will then have a double destroy situation + // when the app. is closed (=> segfault). + // + QApplication::clipboard()->setData(new CHexDrag( buf )); + connect(QApplication::clipboard(),SIGNAL(dataChanged()), + this,SLOT(clipboardChanged())); +} + + +void CHexViewWidget::copyText( int columnSegment ) +{ + QByteArray buf; + if( mHexBuffer->copySelectedText( buf, columnSegment ) != Err_Success ) + { + return; + } + + disconnect(QApplication::clipboard(),SIGNAL(dataChanged()), + this,SLOT(clipboardChanged())); + QApplication::clipboard()->setText( buf.data() ); + connect(QApplication::clipboard(),SIGNAL(dataChanged()), + this,SLOT(clipboardChanged())); +} + + + +void CHexViewWidget::paste( void ) +{ + QMimeSource *data = QApplication::clipboard()->data(); + if( data != 0 ) + { + QByteArray buf; + if( CHexDrag::decode( data, buf ) == true ) + { + insert( buf ); + return; + } + + QString text; + if( QTextDrag::decode( data, text ) == true ) + { + QByteArray buf; + if( mClipConvert.decode( buf, text ) == true ) + { + insert( buf ); + } + return; + } + } + +} + + +void CHexViewWidget::cut( void ) +{ + copy(); // Always make a copy to the clipboard of what we remove. + bool success = mHexBuffer->cutSelection(); + if( success == false ) + { + return; + } + + updateWindow( false, true ); + emit dataChanged(); +} + + +void CHexViewWidget::undo( void ) +{ + bool success = mHexBuffer->undo(); + if( success == false ) + { + return; + } + + updateWindow( true, true ); + emit dataChanged(); +} + + +void CHexViewWidget::redo( void ) +{ + bool success = mHexBuffer->redo(); + if( success == false ) + { + return; + } + + updateWindow( true, true ); + emit dataChanged(); +} + + +void CHexViewWidget::addBookmark( int position ) +{ + int errCode = mHexBuffer->addBookmark( position ); + if( errCode != Err_Success ) + { + if( errCode == Err_ListFull ) + { + replaceBookmark(); + } + return; + } + redrawFromOffset( mHexBuffer->cursorOffset(), false ); + + emit bookmarkChanged( mHexBuffer->bookmarkList() ); +} + + + +int CHexViewWidget::bookmarkMenu( const QString &title ) +{ + QPtrList &list = mHexBuffer->bookmarkList(); + if( list.count() == 0 ) + { + return( -1 ); + } + + QString text; + KPopupMenu *popup = new KPopupMenu( 0 ); + popup->insertTitle( title ); + for( uint i=0; i < list.count(); i++ ) + { + const SCursorOffset *p = list.at( i ); + if( p == 0 ) { continue; } + + text.sprintf("%04X:%04X", p->offset>>16, p->offset&0x0000FFFF ); + text.prepend( QString("[%1] %2: ").arg(i+1).arg(i18n("Offset")) ); + popup->insertItem( text, i ); + } + + QSize s(popup->sizeHint()); + QPoint center( (width()-s.width())/2, (height()-s.height())/2 ); + int position = popup->exec( mapToGlobal(center) ); + delete popup; + + return( position ); +} + + +void CHexViewWidget::removeBookmark( bool all ) +{ + if( all == true ) + { + bool success = mHexBuffer->removeBookmark( -1 ); + if( success == false ) + { + return; + } + QWidget::update(); // Redraw visisble area. + } + else + { + int position = bookmarkMenu( i18n("Remove Bookmark") ); + if( position < 0 ) + { + return; + } + + const SCursorOffset *p = mHexBuffer->bookmarkList().at(position); + uint offset = p ? p->offset : 0; + + bool success = mHexBuffer->removeBookmark( position ); + if( success == false ) + { + return; + } + + redrawFromOffset( offset, false ); + } + + emit bookmarkChanged( mHexBuffer->bookmarkList() ); +} + + +void CHexViewWidget::replaceBookmark( void ) +{ + QPtrList &list = mHexBuffer->bookmarkList(); + if( list.count() == 0 ) + { + return; + } + + int position = bookmarkMenu( i18n("Replace Bookmark") ); + if( position < 0 ) + { + return; + } + addBookmark( position ); +} + + +void CHexViewWidget::gotoBookmark( uint position ) +{ + QPtrList &list = mHexBuffer->bookmarkList(); + if( position >= list.count() ) + { + return; + } + + SCursorOffset *p = list.at( position ); + if( p == 0 ) + { + return; + } + + mHexBuffer->cursorGoto( p->offset, p->bit ); + updateWindow(); +} + + + +void CHexViewWidget::gotoNextBookmark( bool next ) +{ + QPtrList &list = mHexBuffer->bookmarkList(); + uint offset = mHexBuffer->cursorOffset(); + uint diff = ~0; + + SCursorOffset *match = 0; + + // + // Note: the list is unsorted. + // + if( next == true ) + { + for( SCursorOffset *co = list.first(); co != 0; co = list.next() ) + { + if( co->offset > offset ) + { + if( co->offset-offset < diff ) + { + diff = co->offset-offset; + match = co; + } + } + } + } + else + { + for( SCursorOffset *co = list.first(); co != 0; co = list.next() ) + { + if( co->offset < offset ) + { + if( offset-co->offset < diff ) + { + diff = offset-co->offset; + match = co; + } + } + } + } + + + if( match == 0 ) + { + if( next == true ) + { + // Wrap: Locate entry with smallest offset. + offset = ~0; + for( SCursorOffset *co = list.first(); co != 0; co = list.next() ) + { + if( co->offset < offset ) + { + offset = co->offset; + match = co; + } + } + } + else + { + // Wrap: Locate entry with largest offset. + offset=0; + for( SCursorOffset *co = list.first(); co != 0; co = list.next() ) + { + if( co->offset > offset ) + { + offset = co->offset; + match = co; + } + } + } + } + + if( match != 0 ) + { + mHexBuffer->cursorGoto( match->offset, match->bit ); + updateWindow(); + } +} + + + + + + +// +// Used to test the speed of drawing +// +#include +#include +void CHexViewWidget::benchmark( void ) +{ + struct timeval t1, t2; + uint loop = 10; + + gettimeofday( &t1, 0 ); + for( uint i=0; i< loop; i++ ) + { + paintText( contentsRect(), false ); + } + gettimeofday( &t2, 0 ); + + + uint area = width() * height(); + uint last = (t2.tv_sec-t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec); + + kdDebug(1501) << "Duration: " << (float)last/ 1000000.0 << endl; + kdDebug(1501) << "Duration/loop: " << (float)last/ (1000000.0*(float)loop) << endl; + kdDebug(1501) << "Area: " << area << endl; + kdDebug(1501) << "Loop: " << loop << endl; +} + + + + + +void CHexViewWidget::resizeEvent( QResizeEvent * ) +{ + setTextBufferSize(); + + if( mLayout.lockLine == true ) + { + updateView( false, false ); + #ifdef USE_NORTHWEST_GRAVITY + paintFrame(); + #endif + } + else + { + bool state = mVertScroll->isVisible(); + int size = (state == true ? mScrollBarSize : 0) + frameWidth()*2; + #ifdef USE_NORTHWEST_GRAVITY + int w = dataWidth(); + #endif + + bool bufferChanged = mHexBuffer->matchWidth( width() - size ); + updateView( false, bufferChanged ); + + if( mVertScroll->isVisible() != state ) + { + size = (mVertScroll->isVisible() ? mScrollBarSize : 0) + frameWidth()*2; + bufferChanged = mHexBuffer->matchWidth( width() - size ); + updateView( false, bufferChanged ); + } + + #ifdef USE_NORTHWEST_GRAVITY + if( w != dataWidth() ) + { + QWidget::update(); + } + else + { + paintFrame(); + } + #endif + } +} + + + +void CHexViewWidget::paintEvent( QPaintEvent *e ) +{ + paintText( e->rect(), true ); +} + + + +void CHexViewWidget::updateFrameSize( void ) +{ + int w = width() - (mVertScroll->isVisible() ? mScrollBarSize : 0); + if( w < 0 ) { w = 0; } + int h = height() - (mHorzScroll->isVisible() ? mScrollBarSize : 0); + if( h < 0 ) { h = 0; } + + setFrameRect( QRect(0,0,w,h) ); +} + + + +void CHexViewWidget::paintFrame( void ) +{ + QPainter paint; + paint.begin( this ); + drawFrame( &paint ); + paint.end(); +} + + + +void CHexViewWidget::drawFrame( QPainter *p ) +{ + // + // 2000-01-10 Espen Sand + // I want to display the frame with a custom color whenever the widget + // accepts a drop. The setPalette() function causes quite a bit of flicker + // in the scrollbars (even when PropagationMode is NoChildren), so I + // draw the frame manually when it can accept a drop. Note that the + // code below is for the frame shape "QFrame::WinPanel|QFrame::Plain" + // + if( mDropHighlight == true ) + { + qDrawPlainRect( p, frameRect(), QColor("SteelBlue2"), lineWidth() ); + } + else + { + QFrame::drawFrame(p); // Use standard drawFrame + } +} + + + +void CHexViewWidget::keyPressEvent( QKeyEvent *e ) +{ + SCursorConfig cc; + cc.state = e->state(); + + // + // Some special actions that we have to trap here + // + if( e->state() & ControlButton ) + { + switch( e->key() ) + { + case Key_Space: + e->accept(); + toggleEditor(); + return; + break; + + case Key_1: + e->accept(); + cursorStep( cc, 1 ); + return; + break; + + case Key_2: + e->accept(); + cursorStep( cc, 2 ); + return; + break; + + case Key_4: + e->accept(); + cursorStep( cc, 4 ); + return; + break; + + case Key_8: + e->accept(); + cursorStep( cc, 8 ); + return; + break; + } + } + + if( e->state() & AltButton ) + { + if( e->key() == Key_Left || e->key() == Key_Right ) + { + emit pleaseStepFile( e->key() == Key_Left ? true : false ); + e->accept(); + } + else if( e->key() == Key_Up || e->key() == Key_Down ) + { + gotoNextBookmark( e->key() == Key_Down ? true : false ); + e->accept(); + } + else + { + e->ignore(); + } + return; + } + + switch ( e->key() ) + { + case Key_Left: + cursorLeft( cc ); + break; + + case Key_Right: + cursorRight( cc ); + break; + + case Key_Up: + cursorUp( cc ); + break; + + case Key_Down: + cursorDown( cc ); + break; + + case Key_Home: + cursorHome( cc ); + break; + + case Key_End: + cursorEnd( cc ); + break; + + case Key_Next: + cursorPageDown( cc ); + break; + + case Key_Prior: + cursorPageUp( cc ); + break; + + case Key_Insert: + cursorInsert( cc ); + break; + + case Key_Delete: + cursorDelete( cc ); + break; + + case Key_Backspace: + cursorBackspace( cc ); + break; + + default: + if( (e->text()[0]).isPrint() == true ) + { + cursorInput( e->text()[0] ); + } + break; + } + + e->accept(); +} + + +void CHexViewWidget::keyReleaseEvent( QKeyEvent *e ) +{ + if( ( e->state() & ShiftButton ) && shiftButtonState() == false ) + { + // + // The shift button was pressed when event was triggered, but is + // now released. I use this as a sign to copy selected data to the + // clipboard. + // + autoCopy(); + } +} + + +void CHexViewWidget::mousePressEvent( QMouseEvent *e ) +{ + // + // The RMB popup menu is managed by the KContextMenuManager + // + + if( e->button() == LeftButton ) + { + if( e->state() & ControlButton ) + { + if( KContextMenuManager::showOnButtonPress() == true + && mDocumentMenu != 0 ) + { + mDocumentMenu->popup( e->globalPos() ); + } + } + else + { + bool cellLevel = mMisc.cursorJump == false; + setCursorPosition( e->x(), e->y(), true, cellLevel ); + } + } + else if( e->button() == MidButton ) + { + paste(); + } + +} + +void CHexViewWidget::mouseMoveEvent( QMouseEvent *e ) +{ + if( e->state() & LeftButton ) + { + if( mDragManager->start( e ) == false ) + { + bool cellLevel = mMisc.cursorJump == false||e->state() & ControlButton; + setCursorPosition( e->x(), e->y(), false, cellLevel ); + } + } +} + +void CHexViewWidget::mouseReleaseEvent( QMouseEvent *e ) +{ + // + // The RMB popup menu is managed by the KContextMenuManager + // + + if( e->button() == LeftButton ) + { + if( e->state() & ControlButton ) + { + if( KContextMenuManager::showOnButtonPress() == false + && mDocumentMenu != 0 ) + { + mDocumentMenu->popup( e->globalPos() ); + } + } + else + { + if( mDragManager->clear() == true ) + { + // Remove any selection + SCursorConfig cc; + cc.setKeepSelection( false ); + updateCursor( cc, true ); + } + else + { + mHexBuffer->cursorResetEditArea(); + autoCopy(); + } + } + } + +} + + + +void CHexViewWidget::wheelEvent( QWheelEvent *e ) +{ + if( mVertScroll->isVisible() == true ) + { + QApplication::sendEvent( mVertScroll, e ); + } +} + + +void CHexViewWidget::dragEnterEvent( QDragEnterEvent *e ) +{ + if( QTextDrag::canDecode(e) || CHexDrag::canDecode(e) || + KURLDrag::canDecode(e)) + { + e->accept(); + setDropHighlight( true ); + } +} + + +void CHexViewWidget::dragLeaveEvent( QDragLeaveEvent * ) +{ + setDropHighlight( false ); +} + + +void CHexViewWidget::dragMoveEvent( QDragMoveEvent *e ) +{ + // + // Move the cursor if we are dragging (readable) text or binary + // data. Note: the QTextDrag::canDecode() will return true if we + // are dragging a file so we have to test for KURLDrag::canDecode() + // first. + // + + if( KURLDrag::canDecode(e) == true ) + { + return; + } + + if( QTextDrag::canDecode(e) == true || CHexDrag::canDecode(e) == true ) + { + int x = startX() + e->pos().x(); + int y = startY() + e->pos().y(); + if( mHexBuffer->setCursorPosition( x, y, false, false ) == true ) + { + SCursorConfig cc; + cc.setKeepSelection( true ); + updateCursor( cc, false, false ); + } + } +} + + +void CHexViewWidget::dropEvent( QDropEvent *e ) +{ + QMimeSource &m = *(QDropEvent*)e; + setDropHighlight( false ); + + KURL::List list; + if( KURLDrag::decode( &m, list ) == true ) + { + // + // This widget can not itself open a file so it will simply pass + // the request to a parent that can (hopefully) do this + // + for( KURL::List::ConstIterator it = list.begin(); it != list.end(); it++ ) + { + emit pleaseOpenFile( (*it).url(), true, 0 ); + } + return; + } + + QByteArray buf; + if( CHexDrag::decode( &m, buf ) == true ) + { + insert( buf ); + return; + } + + QString text; + if( QTextDrag::decode( &m, text ) == true ) + { + bool success = mClipConvert.decode( buf, text ); + if( success == true ) + { + insert( buf ); + } + return; + } + +} + + +void CHexViewWidget::showEvent( QShowEvent * ) +{ + // Currently we do nothing here. +} + + + + +void CHexViewWidget::timerEvent( QTimerEvent *e ) +{ + if( e->timerId() == mCursorTimerId ) + { + if( hasFocus() == true ) + { + if( mCursor.alwaysVisible == true ) + { + mShowCursor = true; + } + else + { + mShowCursor = mShowCursor == true ? false : true; + } + } + else if( mCursor.focusMode == SDisplayCursor::hide ) + { + mShowCursor = false; + } + else if( mCursor.focusMode == SDisplayCursor::stopBlinking ) + { + mShowCursor = true; + } + else + { + mShowCursor = mShowCursor == true ? false : true; + } + mHexBuffer->setShowCursor( mShowCursor ); + paintCursor( CHexBuffer::cursor_curr ); + } +} + +void CHexViewWidget::focusInEvent( QFocusEvent * ) +{ + setupCursorTimer(); + paintCursor( CHexBuffer::cursor_curr ); +} + +void CHexViewWidget::focusOutEvent( QFocusEvent * ) +{ + if( mCursor.focusMode != SDisplayCursor::ignore ) + { + setupCursorTimer(); + paintCursor( CHexBuffer::cursor_curr ); + } +} + + +void CHexViewWidget::setSelection( uint offset, bool init ) +{ + bool selectionChanged = mHexBuffer->selectionSet( offset, init ); + if( selectionChanged == true ) + { + uint off1, off2; + mHexBuffer->selectionStartChange( off1, off2 ); + if( off1 != off2 ) + { + redrawInterval( off1, off2 ); + } + mHexBuffer->selectionStopChange( off1, off2 ); + if( off1 != off2 ) + { + redrawInterval( off1, off2 ); + } + } + mHexBuffer->selectionSyncronize(); +} + + + +void CHexViewWidget::setMark( uint offset, uint size, bool moveCursor ) +{ + bool changed; + if( size == 0 ) + { + changed = mHexBuffer->markRemove(); + } + else + { + mHexBuffer->markSet( offset, size ); + if( moveCursor == true ) + { + changed = false; + gotoOffset( offset, 7, false, true ); + } + else + { + changed = true; + } + } + + if( changed == true ) + { + uint off1, off2; + mHexBuffer->markStartChange( off1, off2 ); + if( off1 != off2 ) + { + redrawInterval( off1, off2 ); + } + + mHexBuffer->markStopChange( off1, off2 ); + if( off1 != off2 ) + { + redrawInterval( off1, off2 ); + } + } + mHexBuffer->markSyncronize(); +} + + + +void CHexViewWidget::setCursorPosition(int x, int y, bool init, bool cellLevel) +{ + x += startX(); + y += startY(); + + if( mHexBuffer->setCursorPosition( x, y, init, cellLevel ) == false ) + { + if( init == true ) + { + unselect(); + unmark(); + } + } + else if( init == false ) + { + SCursorConfig cc; + cc.setKeepSelection( true ); + updateCursor( cc, false ); + } + else + { + SCursorConfig cc; + if( mHexBuffer->cursorInsideSelection() == true ) + { + mDragManager->setup( x - startX(), y - startY() ); + cc.setKeepSelection( true ); + updateCursor( cc, true, false ); + } + else + { + cc.setKeepSelection( false ); + updateCursor( cc, true ); + } + } +} + + + +void CHexViewWidget::redrawInterval( uint startOffset, uint stopOffset ) +{ + // + // Can be improved, I repaint the entire line even if the offsets + // only specify one byte. + // + uint lineStart = mHexBuffer->calculateLine( startOffset ); + uint lineStop = mHexBuffer->calculateLine( stopOffset ); + if( lineStart <= lineStop ) + { + redrawLines( lineStart, lineStop - lineStart + 1 ); + } + else + { + redrawLines( lineStop, lineStart - lineStop + 1 ); + } +} + + + +void CHexViewWidget::redrawLines( uint docLine, int numLine ) +{ + int lineHeight = mHexBuffer->lineHeight(); + int lineOffset = startY() / lineHeight; + + // FIXME: startY() should return uint + if( (uint)lineOffset > docLine ) + { + numLine -= (lineOffset-docLine); + if( numLine <= 0 ) { return; } + docLine = lineOffset; + } + + int t = docLine * lineHeight - startY() + frameWidth(); + if( mEditMode == CHexBuffer::EditInsert ) + { + QRect r = contentsRect(); + r.setTop( t ); + paintText( contentsRect().intersect( r ), false ); + } + else + { + int h = (numLine + (startY() % lineHeight ? 1 : 0)) * lineHeight; + QRect r( contentsRect().left(), t, contentsRect().width(), h ); + paintText( contentsRect().intersect( r ), false ); + } +} + + + +void CHexViewWidget::redrawFromOffset( uint offset, bool finishWindow ) +{ + int lineHeight = mHexBuffer->lineHeight(); + uint docLine = mHexBuffer->calculateLine( offset ); + + int t = docLine * lineHeight - startY() + frameWidth(); + if( finishWindow == true ) + { + QRect r = contentsRect(); + r.setTop( t ); + paintText( contentsRect().intersect( r ), false ); + } + else + { + int h = t + lineHeight; + QRect r( contentsRect().left(), t, contentsRect().width(), h ); + paintText( contentsRect().intersect( r ), false ); + } +} + + + + +void CHexViewWidget::paintText( const QRect &rect, bool expand ) +{ + QRect r = rect; + + if( expand == true ) + { + #ifdef USE_NORTHWEST_GRAVITY + r.setLeft( r.left() - frameWidth() ); + r.setTop( r.top() - frameWidth() ); + #endif + } + + if( contentsRect().contains( r ) == false ) + { + paintFrame(); + if( r.left() < frameWidth() ) { r.setLeft( frameWidth() ); } + if( r.top() < frameWidth() ) { r.setTop( frameWidth() ); } + } + + int maxX = width() - frameWidth() - 1 - + (mVertScroll->isVisible() ? mScrollBarSize : 0); + int maxY = height() - frameWidth() - 1 - + (mHorzScroll->isVisible() ? mScrollBarSize : 0); + + if( r.right() > maxX ) { r.setRight( maxX ); } + if( r.bottom() > maxY ) { r.setBottom( maxY ); } + + QPainter paint( &mTextBuffer ); + paint.setFont( mHexBuffer->font() ); + + int lineHeight = mHexBuffer->lineHeight(); + int docLine = (startY() + r.y() - frameWidth()) / lineHeight; + if( docLine < 0 ) { docLine = 0; } + int y = docLine * lineHeight - startY(); + int yMax = r.height(); + int xMax = r.x() + r.width(); + + y += frameWidth(); + + int s = 0; + int d = r.y()-y; + int h; + while( yMax > 0 ) + { + mHexBuffer->drawText( paint, docLine, startX()-frameWidth(), r.x(), xMax ); + + if( d != 0 ) + { + h = lineHeight - d; + if( h > yMax ) { h = yMax; } + } + else + { + h = yMax > lineHeight ? lineHeight : yMax; + } + bitBlt( this, r.x(), r.y()+s, &mTextBuffer, r.x(), d, r.width(), h ); + + s += h; + yMax -= h; + docLine += 1; + d = 0; + } + paint.end(); +} + + + +void CHexViewWidget::paintCursor( int cursorMode ) +{ + QPainter paint; + paint.begin( &mTextBuffer ); + paint.setFont( mHexBuffer->font() ); + + int f = frameWidth(); + + if( cursorMode == CHexBuffer::cursor_prev ) + { + int line = mHexBuffer->prevCursorLine(); + SCursorPosition p; + + mHexBuffer->prevCursor( CHexBuffer::edit_primary, p ); + mHexBuffer->drawText( paint, line, startX(), p.x, p.x + p.w ); + if( p.y + p.h + f > contentsRect().bottom() ) + p.h = contentsRect().bottom() - p.y - f + 1; + bitBlt( this, p.x+f, p.y+f, &mTextBuffer, p.x, 0, p.w, p.h ); + + mHexBuffer->prevCursor( CHexBuffer::edit_secondary, p ); + mHexBuffer->drawText( paint, line, startX(), p.x, p.x + p.w ); + if( p.y + p.h + f > contentsRect().bottom() ) + p.h = contentsRect().bottom() - p.y - f + 1; + bitBlt( this, p.x+f, p.y+f, &mTextBuffer, p.x, 0, p.w, p.h ); + } + else + { + int line = mHexBuffer->cursorLine(); + SCursorPosition p; + + mHexBuffer->currCursor( CHexBuffer::edit_primary, p ); + mHexBuffer->drawText( paint, line, startX(), p.x, p.x + p.w ); + if( p.y + p.h + f > contentsRect().bottom() ) + p.h = contentsRect().bottom() - p.y - f + 1; + bitBlt( this, p.x+f, p.y+f, &mTextBuffer, p.x, 0, p.w, p.h ); + + mHexBuffer->currCursor( CHexBuffer::edit_secondary, p ); + mHexBuffer->drawText( paint, line, startX(), p.x, p.x + p.w ); + if( p.y + p.h + f > contentsRect().bottom() ) + p.h = contentsRect().bottom() - p.y - f + 1; + bitBlt( this, p.x+f, p.y+f, &mTextBuffer, p.x, 0, p.w, p.h ); + } + + paint.end(); +} + + + + + +void CHexViewWidget::updateCursor( SCursorConfig &cc, bool always, + bool touchSelection ) +{ + if( mHexBuffer->cursorChanged() == false && always == false ) + { + return; + } + + // + // Make blinking (and perhaps invisible) cursor visible + // + setupCursorTimer(); + + // + // Clear cursor at old location + // + paintCursor( CHexBuffer::cursor_prev ); + + // + // Compute the new position of the vertical scroll bar. + // + int position, h; + if( cc.controlButton() == true ) + { + // + // The cursor should stay fixed (if possible) in the window while + // the text is scrolled (e.g., PageUp/Down behavior). The position + // of the vertical scrollbar must change just as much as the cursor + // has changed in the vertical direction. + // + h = frameWidth()*2; + h += mHorzScroll->isVisible() == false ? 0 : mScrollBarSize; + position = mHexBuffer->cursorFixedPosition( startY(), height()-h ); + changeYPos( position ); + } + else + { + h = frameWidth()*2; + h += mHorzScroll->isVisible() == false ? 0 : mScrollBarSize; + position = mHexBuffer->cursorChangePosition( startY(), height()-h ); + changeYPos( position ); + } + + // + // Paint cursor at new location and update the vertical scroll bar. + // + paintCursor( CHexBuffer::cursor_curr ); + mVertScroll->blockSignals( true ); + mVertScroll->setValue( position ); + mVertScroll->blockSignals( false ); + + if( touchSelection == true ) + { + setSelection( mHexBuffer->cursorOffset(), cc.removeSelection() ); + unmark(); + } + emit cursorChanged( mHexBuffer->cursorState() ); +} + + + +void CHexViewWidget::toggleEditor( void ) +{ + bool success = mHexBuffer->toggleEditor(); + if( success == false ) + { + return; + } + + SCursorConfig cc; + updateCursor( cc, true ); + redrawFromOffset( mHexBuffer->cursorOffset(), false ); +} + + +void CHexViewWidget::cursorStep( SCursorConfig &cc, uint stepSize ) +{ + mHexBuffer->cursorStep( stepSize, cc.altButton() ? false : true, true ); + cc.emulateControlButton( false ); + updateCursor( cc ); +} + + + +void CHexViewWidget::cursorLeft( SCursorConfig &cc ) +{ + bool cellLevel = mMisc.cursorJump == false || cc.controlButton(); + cc.emulateControlButton( false ); + mHexBuffer->cursorLeft( cellLevel ); + updateCursor( cc, cellLevel ); +} + + +void CHexViewWidget::cursorRight( SCursorConfig &cc ) +{ + bool cellLevel = mMisc.cursorJump == false || cc.controlButton(); + cc.emulateControlButton( false ); + mHexBuffer->cursorRight( cellLevel ); + updateCursor( cc, cellLevel ); +} + + + +void CHexViewWidget::cursorUp( SCursorConfig &cc ) +{ + mHexBuffer->cursorUp( 1 ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorDown( SCursorConfig &cc ) +{ + mHexBuffer->cursorDown( 1 ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorHome( SCursorConfig &cc ) +{ + mHexBuffer->cursorHome( cc.controlButton() ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorEnd( SCursorConfig &cc ) +{ + mHexBuffer->cursorEnd( cc.controlButton() ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorPageDown( SCursorConfig &cc ) +{ + mHexBuffer->cursorDown( height() / mHexBuffer->lineHeight() ); + cc.emulateControlButton( true ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorPageUp( SCursorConfig &cc ) +{ + mHexBuffer->cursorUp( height() / mHexBuffer->lineHeight() ); + cc.emulateControlButton( true ); + updateCursor( cc ); +} + + +void CHexViewWidget::cursorInsert( SCursorConfig &/*cc*/ ) +{ + // Toggle mode + setEditMode( mEditMode == CHexBuffer::EditInsert ? + CHexBuffer::EditReplace : CHexBuffer::EditInsert ); +} + + + +void CHexViewWidget::cursorDelete( SCursorConfig &/*cc*/ ) +{ + int numLine = mHexBuffer->numLines(); + + bool success = mHexBuffer->removeAtCursor( false ); + if( success == false ) + { + return; + } + + updateWindow( numLine == mHexBuffer->numLines() ? false : true, true ); + emit dataChanged(); +} + + +void CHexViewWidget::cursorBackspace( SCursorConfig &/*cc*/ ) +{ + int numLine = mHexBuffer->numLines(); + + bool success = mHexBuffer->removeAtCursor( true ); + if( success == false ) + { + return; + } + + updateWindow( numLine == mHexBuffer->numLines() ? false : true, true ); + emit dataChanged(); +} + + +void CHexViewWidget::cursorInput( QChar c ) +{ + uint cursorLine = mHexBuffer->cursorLine(); + bool success = mHexBuffer->inputAtCursor( c ); + if( success == false ) + { + return; + } + + updateWindow( cursorLine ); + emit dataChanged(); +} + + +void CHexViewWidget::setEditMode( CHexBuffer::EEditMode mode ) +{ + mEditMode = mode; + mHexBuffer->setEditMode( mEditMode, mCursor.alwaysBlockShape, + mCursor.thickInsertShape ); + setupCursorTimer(); + + // + // This will redraw the current line (which contains the cursor) + // + redrawFromOffset( mHexBuffer->cursorOffset(), false ); + emit editMode( mEditMode ); +} + + +void CHexViewWidget::setDropHighlight( bool dropHighlight ) +{ + mDropHighlight = dropHighlight; + if( mDropHighlight == true ) + { + // + // 2000-01-10 Espen Sand + // Highlight. I have reimplemented QFrame::drawFrame(QPainter *) + // to support a custom frame color. I assume the frame shape is + // "QFrame::WinPanel|QFrame::Plain" in that function. + // + setFrameStyle( QFrame::WinPanel|QFrame::Plain ); + } + else + { + setFrameStyle( QFrame::WinPanel|QFrame::Sunken ); + } +} + + + +#include "hexviewwidget.moc" diff --git a/khexedit/hexviewwidget.h b/khexedit/hexviewwidget.h new file mode 100644 index 0000000..9dc55e4 --- /dev/null +++ b/khexedit/hexviewwidget.h @@ -0,0 +1,584 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _HEX_VIEW_WIDGET_H_ +#define _HEX_VIEW_WIDGET_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#include +#include +#include +#include + +#include +#include + +#include "hexclipboard.h" +#include "hexbuffer.h" + +class CScrollBar : public QScrollBar +{ + Q_OBJECT + + public: + CScrollBar( Orientation o, QWidget *parent, const char *name = 0 ) + : QScrollBar( o, parent, name ) + { + } + + signals: + void hidden( void ); + + protected: + virtual void hideEvent( QHideEvent * ) + { + emit hidden(); + } +}; + + +class CDragManager : public QWidget +{ + Q_OBJECT + + public: + enum EDragActivateMode + { + Movement = 0, + Timer = 1 + }; + + public: + CDragManager( void ); + void setActivateMode( EDragActivateMode mode ); + void setup( int x, int y ); + bool start( QMouseEvent *e ); + bool clear( void ); + + protected: + virtual void timerEvent( QTimerEvent *e ); + + private: + void removeTimer( void ); + void setupTimer( void ); + + signals: + void startDrag( bool asText ); + + private: + EDragActivateMode mActivateMode; + bool mPending; + int mTimerId; + QPoint mOrigin; +}; + + + +class CHexViewWidget : public QFrame +{ + Q_OBJECT + + public: + CHexViewWidget( QWidget *parent, const char *name, CHexBuffer *hexBuffer ); + ~CHexViewWidget( void ); + inline bool widgetValid( void ); + + int readFile( QFile &file, const QString &url, CProgress &p ); + int insertFile( QFile &file, CProgress &p ); + int writeFile( QFile &file, CProgress &p ); + int newFile( const QString &url ); + void closeFile( void ); + void initFile( void ); + void setBuffer( CHexBuffer *hexBuffer ); + void updateView( bool redraw, bool fixCursor ); + + void selectAll( void ); + void unselect( void ); + void unmark( void ); + uint numPage( CHexPrinter &printer ); + int print( CHexPrinter &printer, CProgress &p ); + int exportText( const SExportText &ex, CProgress &p ); + int exportHtml( const SExportHtml &ex, CProgress &p ); + int exportCArray( const SExportCArray &ex, CProgress &p ); + + void copy( void ); + void copyText( int columnSegment=CHexBuffer::VisibleColumn ); + void paste( void ); + void cut( void ); + void undo( void ); + void redo( void ); + void addBookmark( int position ); + void removeBookmark( bool all ); + void replaceBookmark( void ); + void gotoBookmark( uint position ); + void gotoNextBookmark( bool next ); + void benchmark( void ); + + virtual void setPalette( const QPalette & ); + void setInputMode( SDisplayInputMode &mode ); + void setLayout( SDisplayLayout &layout ); + void setCursor( const SDisplayCursor &cursor, bool updateDisplay ); + void setColor( const SDisplayColor &color, bool updateDisplay ); + void setFont( const SDisplayFontInfo &fontInfo, bool updateDisplay ); + void setMisc( SDisplayMisc &misc ); + void setInsertMode( bool insertMode ); + int setEncoding( CConversion::EMode mode, CProgress &p ); + void reportEncoding( void ); + + int findFirst( SSearchControl &sc ); + int findNext( SSearchControl &sc ); + int findWrap( SSearchControl &sc ); + int replaceAll( SSearchControl &sc, bool init ); + int replaceMarked( SSearchControl &sc ); + int collectStrings( CStringCollectControl &sc ); + int collectStatistic( SStatisticControl &sc, CProgress &p ); + + + inline void setPopupMenu( QPopupMenu *popupMenu ); + inline void setDocumentMenu( QPopupMenu *popupMenu ); + inline bool insertMode( void ); + inline int scrollBarWidth( void ); + inline int dataWidth( void ); + inline int defaultWidth( void ); + inline uint offset( void ); + inline uint bookmarkCount( void ); + inline bool modified( void ); + inline void setModified( bool modified ); + inline const QDateTime &diskModifyTime( void ); + inline bool losslessEncoding( CConversion::EMode mode ); + inline const SEncodeState &encoding( void ); + inline bool documentPresent( void ); + inline bool urlValid( void ); + inline QString &url( void ); + inline void setUrl( QString &url ); + inline const CHexBuffer *hexBuffer( void ); + + public slots: + void filter( SFilterControl &fc ); + void insert( SInsertData &id ); + void insert( const QByteArray &buf ); + void append( const QByteArray &buf ); + void valueOnCursor( QByteArray &buf, uint size ); + void paletteChanged( void ); + void fontChanged( void ); + void gotoOffset( uint offset, uint bit, bool fromCursor, bool forward ); + void gotoOffset( uint offset ); + void setMark( uint offset, uint size, bool moveCursor ); + void setDropHighlight( bool mode ); + + protected: + virtual void drawFrame( QPainter *p ); + virtual void paintEvent( QPaintEvent *e ); + virtual void resizeEvent( QResizeEvent *e ); + virtual void keyPressEvent( QKeyEvent *e ); + virtual void keyReleaseEvent( QKeyEvent *e ); + virtual void mousePressEvent( QMouseEvent *e ); + virtual void mouseMoveEvent( QMouseEvent *e ); + virtual void wheelEvent( QWheelEvent * ); + virtual void mouseReleaseEvent( QMouseEvent *e ); + virtual void dragEnterEvent( QDragEnterEvent *e ); + virtual void dragLeaveEvent( QDragLeaveEvent *e ); + virtual void dragMoveEvent( QDragMoveEvent *e ); + virtual void dropEvent( QDropEvent *e ); + virtual void showEvent( QShowEvent * ); + virtual void timerEvent( QTimerEvent *e ); + virtual void focusInEvent( QFocusEvent *e ); + virtual void focusOutEvent( QFocusEvent *e ); + + protected slots: + void changeXPos( int pos ); + void changeYPos( int pos ); + void clipboardChanged( void ); + + signals: + void cursorChanged( SCursorState &state ); + void fileState( SFileState &state ); + void dataChanged( void ); + void layoutChanged( const SDisplayLayout &layout ); + void inputModeChanged( const SDisplayInputMode &mode ); + void bookmarkChanged( QPtrList &list ); + void editMode( CHexBuffer::EEditMode editMode ); + void encodingChanged( const SEncodeState &state ); + void textWidth( uint width ); + void fileName( const QString &url, bool onDisk ); + void fileRename( const QString &curName, const QString &newName ); + void fileClosed( const QString &url ); + + void pleaseOpenNewFile( void ); + void pleaseStepFile( bool next ); + void pleaseOpenFile(const QString &url,bool reloadWhenChanged,uint offset); + + private: + void setSelection( uint offset, bool init ); + void setCursorPosition( int x, int y, bool init, bool cellLevel ); + void updateCursor( SCursorConfig &cc, bool always = false, + bool touchSelection = true ); + void setEditMode( CHexBuffer::EEditMode mode ); + + void paintFrame( void ); + void updateFrameSize( void ); + + void redrawInterval( uint start, uint stop ); + void redrawLines( uint docLine, int numLine ); + void redrawFromOffset( uint offset, bool finishWindow ); + void paintText( const QRect &r, bool expand ); + void paintCursor( int cursorMode ); + + + void toggleEditor( void ); + void cursorStep( SCursorConfig &cc, uint stepSize ); + void cursorLeft( SCursorConfig &cc ); + void cursorRight( SCursorConfig &cc ); + void cursorHome( SCursorConfig &cc ); + void cursorEnd( SCursorConfig &cc ); + void cursorUp( SCursorConfig &cc ); + void cursorDown( SCursorConfig &cc ); + void cursorPageUp( SCursorConfig &cc ); + void cursorPageDown( SCursorConfig &cc ); + void cursorInsert( SCursorConfig &cc ); + void cursorDelete( SCursorConfig &cc ); + void cursorBackspace( SCursorConfig &cc ); + void cursorInput( QChar c ); + + int bookmarkMenu( const QString &title ); + + static inline bool shiftButtonState( void ); + + inline void setupCursorTimer( void ); + inline int startX( void ); + inline int startY( void ); + inline void setStartX( int val ); + inline void setStartY( int val ); + inline void updateWindow( bool completeRedraw, bool touchSelection ); + inline void updateWindow( uint line ); + inline void updateWindow( uint fromOffset, bool finishWindow ); + inline void updateWindow( void ); + inline void setTextBufferSize( void ); + inline void autoCopy( void ); + + private slots: + void startDrag( bool asText ); + + private: + CScrollBar *mVertScroll; + CScrollBar *mHorzScroll; + QWidget *mCorner; + + CHexBuffer *mHexBuffer; + QPixmap mTextBuffer; + SDisplayLayout mLayout; + SDisplayCursor mCursor; + SDisplayColor mColor; + SDisplayFontInfo mFontInfo; + SDisplayMisc mMisc; + + QPopupMenu *mDocumentMenu; + + int mScrollBarSize; + CHexBuffer::EEditMode mEditMode; + bool mShowCursor; + bool mDropHighlight; + + int mCursorTimerId; + + CDragManager *mDragManager; + CHexClipboard mClipConvert; +}; + + +inline bool CHexViewWidget::shiftButtonState( void ) +{ + return kapp->keyboardModifiers() & KApplication::ShiftModifier; +} + + + +inline bool CHexViewWidget::widgetValid( void ) +{ + if( mVertScroll == 0 || mHorzScroll == 0 || mHexBuffer == 0 ) + { + return( false ); + } + else + { + return( true ); + + } +} + +inline void CHexViewWidget::setupCursorTimer( void ) +{ + if( mCursorTimerId != 0 ) + { + killTimer( mCursorTimerId ); + mCursorTimerId = 0; + } + + if( hasFocus() == true ) + { + if( mCursor.alwaysVisible == false ) + { + mCursorTimerId = startTimer( mCursor.interval ); + } + mShowCursor = true; + mHexBuffer->setDisableCursor( false ); + } + else + { + if( mCursor.alwaysVisible == false ) + { + if( mCursor.focusMode == SDisplayCursor::ignore ) + { + mCursorTimerId = startTimer( mCursor.interval ); + } + } + if( mCursor.focusMode != SDisplayCursor::hide ) + { + mShowCursor = true; + } + else + { + mShowCursor = false; + mHexBuffer->setDisableCursor( true ); + } + } + + mHexBuffer->setShowCursor( mShowCursor ); +} + +inline void CHexViewWidget::setPopupMenu( QPopupMenu *popupMenu ) +{ + KContextMenuManager::insert( this, popupMenu ); +} + + +inline void CHexViewWidget::setDocumentMenu( QPopupMenu *popupMenu ) +{ + mDocumentMenu = popupMenu; +} + + +inline int CHexViewWidget::startX( void ) +{ + return( mHexBuffer->startX() ); +} + +inline int CHexViewWidget::startY( void ) +{ + return( mHexBuffer->startY() ); +} + +inline void CHexViewWidget::setStartX( int val ) +{ + mHexBuffer->setStartX( val ); +} + +inline void CHexViewWidget::setStartY( int val ) +{ + mHexBuffer->setStartY( val ); +} + + +inline void CHexViewWidget::updateWindow( bool completeRedraw, + bool touchSelection ) +{ + if( completeRedraw == true ) + { + SCursorConfig cc; + updateCursor( cc, true, touchSelection ); + updateView( true, false ); + } + else + { + SCursorConfig cc; + updateCursor( cc, false, touchSelection ); + redrawFromOffset( mHexBuffer->cursorOffset(), true ); + updateView( false, false ); + } + + emit fileState( mHexBuffer->fileState() ); +} + + + +inline void CHexViewWidget::updateWindow( uint line ) +{ + SCursorConfig cc; + updateCursor( cc, false, true ); + if( line == mHexBuffer->cursorLine() ) + { + redrawLines( line, 1 ); + } + else if( line < mHexBuffer->cursorLine() ) + { + redrawLines( line, mHexBuffer->cursorLine() - line ); + } + else + { + redrawLines( line, line - mHexBuffer->cursorLine() ); + } + emit fileState( mHexBuffer->fileState() ); +} + + +inline void CHexViewWidget::updateWindow( uint fromOffset, bool finishWindow ) +{ + SCursorConfig cc; + updateCursor( cc, true, true ); + updateView( false, false ); + redrawFromOffset( fromOffset, finishWindow ); + + emit fileState( mHexBuffer->fileState() ); +} + + +inline void CHexViewWidget::updateWindow( void ) +{ + setTextBufferSize(); + mHexBuffer->cursorUp(0); // Makes sure cursor is visible + + SCursorConfig cc; + cc.emulateControlButton( true ); + updateCursor( cc, true, false ); + updateView( true, false ); + + emit fileState( mHexBuffer->fileState() ); +} + + +inline void CHexViewWidget::setTextBufferSize( void ) +{ + int w = width(); + int h = mHexBuffer->lineHeight(); + + if( w != mTextBuffer.width() || h != mTextBuffer.height() ) + { + mTextBuffer.resize( w, h ); + } +} + + +inline void CHexViewWidget::autoCopy( void ) +{ + if( mMisc.autoCopyToClipboard == true ) + { + copy(); + } +} + + +inline bool CHexViewWidget::insertMode( void ) +{ + return mEditMode == CHexBuffer::EditInsert; +} + + +inline int CHexViewWidget::scrollBarWidth( void ) +{ + return( mScrollBarSize ); +} + +inline int CHexViewWidget::dataWidth( void ) +{ + return( mHexBuffer->lineWidth() ); +} + +inline int CHexViewWidget::defaultWidth( void ) +{ + return( dataWidth() + scrollBarWidth() + frameWidth()*2 ); +} + + +inline uint CHexViewWidget::offset( void ) +{ + return( mHexBuffer->cursorOffset() ); +} + +inline uint CHexViewWidget::bookmarkCount( void ) +{ + const QPtrList &list = mHexBuffer->bookmarkList(); + return( list.count() ); +} + +inline bool CHexViewWidget::modified( void ) +{ + return( mHexBuffer->modified() ); +} + +inline void CHexViewWidget::setModified( bool modified ) +{ + mHexBuffer->setModified( modified ); + emit fileState( mHexBuffer->fileState() ); +} + +inline const QDateTime &CHexViewWidget::diskModifyTime( void ) +{ + return( mHexBuffer->diskModifyTime() ); +} + +inline bool CHexViewWidget::losslessEncoding( CConversion::EMode mode ) +{ + return( mHexBuffer->losslessEncoding(mode) ); +} + +inline const SEncodeState &CHexViewWidget::encoding( void ) +{ + return( mHexBuffer->encoding() ); +} + +inline bool CHexViewWidget::documentPresent( void ) +{ + return( mHexBuffer->documentPresent() ); +} + +inline bool CHexViewWidget::urlValid( void ) +{ + return( mHexBuffer->hasFileName() ); +} + +inline QString &CHexViewWidget::url( void ) +{ + return( mHexBuffer->url() ); +} + +inline void CHexViewWidget::setUrl( QString &url ) +{ + if( mHexBuffer->url() != url ) + { + emit fileRename( mHexBuffer->url(), url ); + mHexBuffer->setUrl( url ); + } +} + +inline const CHexBuffer *CHexViewWidget::hexBuffer( void ) +{ + return( mHexBuffer ); +} + + +#endif + + + + diff --git a/khexedit/hi16-app-khexedit.png b/khexedit/hi16-app-khexedit.png new file mode 100644 index 0000000..9b23931 Binary files /dev/null and b/khexedit/hi16-app-khexedit.png differ diff --git a/khexedit/hi32-app-khexedit.png b/khexedit/hi32-app-khexedit.png new file mode 100644 index 0000000..cc64da0 Binary files /dev/null and b/khexedit/hi32-app-khexedit.png differ diff --git a/khexedit/hi48-app-khexedit.png b/khexedit/hi48-app-khexedit.png new file mode 100644 index 0000000..429c424 Binary files /dev/null and b/khexedit/hi48-app-khexedit.png differ diff --git a/khexedit/khexedit.desktop b/khexedit/khexedit.desktop new file mode 100644 index 0000000..befa3d7 --- /dev/null +++ b/khexedit/khexedit.desktop @@ -0,0 +1,86 @@ +[Desktop Entry] +GenericName=Binary Editor +GenericName[af]=Binêre Redigeerder +GenericName[ar]=محرر ثنائى +GenericName[bg]=Двоичен редактор +GenericName[br]=Aozer binarel +GenericName[bs]=Binarni editor +GenericName[ca]=Editor binari +GenericName[cs]=Binární editor +GenericName[cy]=Golygydd Deuaidd +GenericName[da]=Binær editor +GenericName[de]=Binäreditor +GenericName[el]=Επεξεργαστής δυαδικών αρχείων +GenericName[eo]=Deksesuma redaktilo +GenericName[es]=Editor binario +GenericName[et]=Binaarfailide redaktor +GenericName[eu]=Editore Binarioa +GenericName[fa]=ویرایشگر دوگانی +GenericName[fi]=Binäärieditori +GenericName[fr]=Éditeur hexadécimal +GenericName[ga]=Eagarthóir Dénártha +GenericName[he]=עורך בינרי +GenericName[hi]=द्विचर संपादक +GenericName[hr]=Binarni uređivač +GenericName[hu]=Hexaszerkesztő +GenericName[is]=Tvíunda-ritill +GenericName[it]=Editor binario +GenericName[ja]=バイナリエディタ +GenericName[ka]=ბინარული რედაქტორი +GenericName[kk]=Бинарлық редактор +GenericName[km]=កម្មវិធី​និពន្ធ​គោលពីរ +GenericName[lt]=Dvejetainio kodo redaktorius +GenericName[lv]=Binārais Redaktors +GenericName[mk]=Бинарен уредувач +GenericName[ms]=Penyunting Binari +GenericName[mt]=Editur binarju +GenericName[nb]=Binærredigerer +GenericName[nds]=Hexeditor +GenericName[ne]=बाइनरी सम्पादक +GenericName[nl]=Binaire bestanden bewerken +GenericName[nn]=Program for binærredingerig +GenericName[pa]=ਬਾਈਨਰੀ ਸੰਪਾਦਕ +GenericName[pl]=Editor Binarny +GenericName[pt]=Editor Binário +GenericName[pt_BR]=Editor de Binários +GenericName[ro]=Editor date binare +GenericName[ru]=Двоичный редактор +GenericName[sk]=Binárny editor +GenericName[sl]=Binarni urejevalnik +GenericName[sr]=Уређивач бинарних фајлова +GenericName[sr@Latn]=Uređivač binarnih fajlova +GenericName[sv]=Binäreditor +GenericName[ta]=இருநிலை தொகுப்பான் +GenericName[tg]=Муҳаррири Дуӣ +GenericName[th]=เครื่องมือแก้ไขเลขฐาน +GenericName[tr]=İkili dosya düzenleyici +GenericName[uk]=Двійковий редактор +GenericName[ven]=Musengulusi kavhili +GenericName[vi]=Trình biên tập nhị phân +GenericName[wa]=Aspougneu binaire +GenericName[xh]=Umphathi Webhetri +GenericName[zh_CN]=二进制编辑器 +GenericName[zh_TW]=二進位編輯器 +GenericName[zu]=Umhleli Ohambisana ngambili +Name=KHexEdit +Name[af]=Khex-redigeerder +Name[eo]=Deksesuma redaktilo +Name[hi]=के-हेक्स-एडिट +Name[pl]=Edytor binarny +Name[pt_BR]=Editor Hexadecimal +Name[sv]=Khexedit +Name[ta]=KHexதொகுப்பு +Name[th]=แก้ไขเลขฐาน +Name[tr]=Onaltılı Düzenleyici +Name[ven]=U sengulusa ha KHex +Name[zh_TW]=KHex 編輯器 +Exec=khexedit -caption "%c" %i %m %U +Icon=khexedit +Path= +Type=Application +DocPath=khexedit/index.html +Terminal=false +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Utility;X-KDE-Utilities-File; + diff --git a/khexedit/khexeditui.rc b/khexedit/khexeditui.rc new file mode 100644 index 0000000..5be593a --- /dev/null +++ b/khexedit/khexeditui.rc @@ -0,0 +1,137 @@ + + + + + + + + + + Permissions + + + + + + + + + Spec&ial + + + + + + + + + + + + + + + + + + + + + + + Document &Encoding + + + + + + + + + + + + + + + + + + + + + + + + + &Documents + + + + + + &Document Tabs + + + + + Conversion &Field + + + + + Searc&hbar + + + + + + + + + +Main Toolbar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &Bookmarks + + + + + + + + + + + + + + diff --git a/khexedit/lib/Makefile.am b/khexedit/lib/Makefile.am new file mode 100644 index 0000000..c0c92cc --- /dev/null +++ b/khexedit/lib/Makefile.am @@ -0,0 +1,39 @@ +SUBDIRS = controller codecs + +INCLUDES = $(all_includes) + +METASOURCES = AUTO + +# this library is used by the kbytesedit part and the khepart part +lib_LTLIBRARIES = libkhexeditcommon.la +libkhexeditcommon_la_LDFLAGS = $(all_libraries) -no-undefined +libkhexeditcommon_la_LIBADD = controller/libkcontroller.la codecs/libkhecodecs.la $(LIB_KDECORE) +libkhexeditcommon_la_SOURCES = kcolumn.cpp kbordercolumn.cpp koffsetcolumn.cpp \ + kbuffercolumn.cpp kvaluecolumn.cpp kcharcolumn.cpp \ + kcolumnsview.cpp khexedit.cpp kbytesedit.cpp \ + koffsetformat.cpp \ + kdatabuffer.cpp kwrappingrobuffer.cpp \ + kplainbuffer.cpp kfixedsizebuffer.cpp kbigbuffer.cpp \ + kbuffercursor.cpp kbufferlayout.cpp kbufferranges.cpp \ + kcursor.cpp kbufferdrag.cpp \ + kwordbufferservice.cpp \ + ksectionlist.cpp kcoordrangelist.cpp \ + kbordercoltextexport.cpp koffsetcoltextexport.cpp \ + kbuffercoltextexport.cpp kvaluecoltextexport.cpp kcharcoltextexport.cpp + +# no public API for a direct use by now +noinst_HEADERS = kcolumn.h kbordercolumn.h koffsetcolumn.h \ + kbuffercolumn.h kvaluecolumn.h kcharcolumn.h \ + kbytecodec.h koffsetformat.h khexedit_export.h \ + kbuffercursor.h kbufferlayout.h kbufferranges.h \ + kbuffercoord.h kselection.h \ + kcursor.h kbufferdrag.h \ + kcoordrange.h ksectionlist.h kcoordrangelist.h \ + khechar.h kcharcodec.h \ + kcoltextexport.h kbordercoltextexport.h koffsetcoltextexport.h \ + kbuffercoltextexport.h kvaluecoltextexport.h kcharcoltextexport.h \ + kadds.h khe.h krange.h ksection.h \ + kwordbufferservice.h \ + kcolumnsview.h khexedit.h kbytesedit.h \ + kplainbuffer.h kfixedsizebuffer.h kbigbuffer.h \ + kdatabuffer.h kreadonlybuffer.h kwrappingrobuffer.h diff --git a/khexedit/lib/README b/khexedit/lib/README new file mode 100644 index 0000000..ad5f346 --- /dev/null +++ b/khexedit/lib/README @@ -0,0 +1,36 @@ +hex editor library +================== +part of the KHexEdit 2 project (kdenonbeta/khexedit2) +Author/Maintainer: Friedrich W. H. Kossebau + + +description: +----------- +The lib is the main work of KHexEdit2. It offers +a general usable hex edit widget "KHexEdit" +that interacts with an abstract data buffer +interface called "KDataBuffer". This interface can +be subclassed to offer access to different data buffers +like paged gigabyte big files, video memory or whatever +you can imagine (hopefully). + +For those simply needing a widget for a plain array of bytes +there is the widget subclass "KBytesEdit", which hides the +databuffer interface and publically simply interacts with +arrays (like "char Array[25];"). + + +installing: +----------- +As these widgets and the databuffer interface have not got +much testing the API might not be finished. Because of that +it won't be made public available, i.e. there will be no headers +installed. + + +usage: +------ +This lib is by now only used by the KBytesEdit part, to be found +in "../parts/kbytesedit". +It is _not_ used by the current KHexEdit 1 app. This will change once +the successor app from KHexEdit2 is done. \ No newline at end of file diff --git a/khexedit/lib/codecs/Makefile.am b/khexedit/lib/codecs/Makefile.am new file mode 100644 index 0000000..0c208b7 --- /dev/null +++ b/khexedit/lib/codecs/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I$(srcdir)/.. $(all_includes) + +METASOURCES = AUTO + +# +noinst_LTLIBRARIES = libkhecodecs.la +libkhecodecs_la_SOURCES = kcharcodec.cpp kbytecodec.cpp \ + ktextcharcodec.cpp kebcdic1047charcodec.cpp \ + kbinarybytecodec.cpp koctalbytecodec.cpp \ + kdecimalbytecodec.cpp khexadecimalbytecodec.cpp + +# no public API +noinst_HEADERS = ktextcharcodec.h kebcdic1047charcodec.h \ + kbinarybytecodec.h koctalbytecodec.h \ + kdecimalbytecodec.h khexadecimalbytecodec.h \ No newline at end of file diff --git a/khexedit/lib/codecs/README b/khexedit/lib/codecs/README new file mode 100644 index 0000000..b4a0e52 --- /dev/null +++ b/khexedit/lib/codecs/README @@ -0,0 +1 @@ +This directory holds all the char codecs. All it exports is the call "createCodec()", the rest in hidden. diff --git a/khexedit/lib/codecs/kbinarybytecodec.cpp b/khexedit/lib/codecs/kbinarybytecodec.cpp new file mode 100644 index 0000000..d665a05 --- /dev/null +++ b/khexedit/lib/codecs/kbinarybytecodec.cpp @@ -0,0 +1,80 @@ +/*************************************************************************** + kbinarybytecodec.cpp - description + ------------------- + begin : Mo Nov 29 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "kbinarybytecodec.h" + +using namespace KHE; + + +void KBinaryByteCodec::encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const +{ + for( unsigned char M=1<<7; M>0; M>>=1 ) + Digits.at(Pos++) = (Char & M) ? '1' : '0'; +} + +void KBinaryByteCodec::encodeShort( QString &Digits, unsigned int Pos, unsigned char Char ) const +{ + unsigned char M = 1<<7; + // find first set bit + for( ; M>0; M>>=1 ) + if( Char & M ) + break; + // now set the + for( ; M>0; M>>=1 ) + Digits.at(Pos++) = (Char & M) ? '1' : '0'; +} + + +bool KBinaryByteCodec::isValidDigit( unsigned char Digit ) const +{ + return Digit == '0' || Digit == '1'; +} + + +bool KBinaryByteCodec::turnToValue( unsigned char *Digit ) const +{ + if( isValidDigit(*Digit) ) + { + *Digit -= '0'; + return true; + } + return false; +} + + +bool KBinaryByteCodec::appendDigit( unsigned char *Byte, unsigned char Digit ) const +{ + if( turnToValue(&Digit) ) + { + unsigned char B = *Byte; + if( B < 128 ) + { + B <<= 1; + B += Digit; + *Byte = B; + return true; + } + } + return false; +} + + +void KBinaryByteCodec::removeLastDigit( unsigned char *Byte ) const +{ + *Byte >>= 1; +} diff --git a/khexedit/lib/codecs/kbinarybytecodec.h b/khexedit/lib/codecs/kbinarybytecodec.h new file mode 100644 index 0000000..d0354fa --- /dev/null +++ b/khexedit/lib/codecs/kbinarybytecodec.h @@ -0,0 +1,59 @@ +/*************************************************************************** + kbinarybytecodec.h - description + ------------------- + begin : Mo Nov 29 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBINARYBYTECODEC_H +#define KHE_KBINARYBYTECODEC_H + +// lib specific +#include "kbytecodec.h" + +namespace KHE +{ + +/** class that is able to convert codings to and from binary + * + * the buffer will be always filled up to CodingWidth, if not using shortCodingFunction + * a closing '\0' will be always added + * + *@author Friedrich W. H. Kossebau + */ + +class KBinaryByteCodec : public KByteCodec +{ + public: // API to be implemented + /** */ + virtual unsigned int encodingWidth() const { return 8; } + /** */ + virtual unsigned char digitsFilledLimit() const { return 128; } + + /** encodes the Char and writes the result to */ + virtual void encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const; + /** */ + virtual void encodeShort( QString &Digits, unsigned int Pos, const unsigned char Char ) const; + /** */ + virtual bool appendDigit( unsigned char *Byte, const unsigned char Digit ) const; + /** */ + virtual void removeLastDigit( unsigned char *Byte ) const; + /** */ + virtual bool isValidDigit( const unsigned char Digit ) const; + /** */ + virtual bool turnToValue( unsigned char *Digit ) const; +}; + +} + +#endif diff --git a/khexedit/lib/codecs/kbytecodec.cpp b/khexedit/lib/codecs/kbytecodec.cpp new file mode 100644 index 0000000..dc5137f --- /dev/null +++ b/khexedit/lib/codecs/kbytecodec.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + kbytecodec.cpp - description + ------------------- + begin : Mo Nov 29 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "kbinarybytecodec.h" +#include "koctalbytecodec.h" +#include "kdecimalbytecodec.h" +#include "khexadecimalbytecodec.h" + +using namespace KHE; + + +KByteCodec *KByteCodec::createCodec( KCoding C ) +{ + KByteCodec *Codec; + switch( C ) + { + case DecimalCoding: Codec = new KDecimalByteCodec(); break; + case OctalCoding: Codec = new KOctalByteCodec(); break; + case BinaryCoding: Codec = new KBinaryByteCodec(); break; + case HexadecimalCoding: + default: Codec = new KHexadecimalByteCodec(); + } + return Codec; +} + +unsigned int KByteCodec::decode( unsigned char *Char, const QString &Digits, uint Pos ) const +{ + //kdDebug() << QString("KByteCodec::decode(%1,%2)").arg(Digits).arg(Pos) << endl; + const uint P = Pos; + + // remove leading 0s + while( Digits.at(Pos) == '0' ) { ++Pos; } + + unsigned char C = 0; + unsigned int d = encodingWidth(); + do + { + if( !appendDigit(&C,Digits.at(Pos)) ) + break; + + ++Pos; + --d; + } + while( d > 0 ); + + *Char = C; + return Pos - P; +} diff --git a/khexedit/lib/codecs/kcharcodec.cpp b/khexedit/lib/codecs/kcharcodec.cpp new file mode 100644 index 0000000..5a58320 --- /dev/null +++ b/khexedit/lib/codecs/kcharcodec.cpp @@ -0,0 +1,74 @@ +/*************************************************************************** + kcharcodec.cpp - description + ------------------- + begin : Do Nov 25 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "kcharcodec.h" +#include "ktextcharcodec.h" +#include "kebcdic1047charcodec.h" + +using namespace KHE; + + +QStringList KCharCodec::CodecNames; + +const QStringList &KCharCodec::codecNames() +{ + // first call? + if( CodecNames.isEmpty() ) + { + CodecNames = KTextCharCodec::codecNames(); + CodecNames.append( KEBCDIC1047CharCodec::codecName() ); + } + + return CodecNames; +} + + +KCharCodec *KCharCodec::createCodec( const QString &Name ) +{ + KCharCodec *Codec = 0; + + if( KTextCharCodec::codecNames().findIndex(Name) != -1 ) + Codec = KTextCharCodec::createCodec( Name ); + else if( KEBCDIC1047CharCodec::codecName() == Name ) + Codec = KEBCDIC1047CharCodec::create(); + + // ensure at least a codec + if( Codec == 0 ) + Codec = KTextCharCodec::createLocalCodec(); + + return Codec; +} + + +KCharCodec *KCharCodec::createCodec( KEncoding C ) +{ + KCharCodec *Codec; + if( C == EBCDIC1047Encoding ) + Codec = KEBCDIC1047CharCodec::create(); + else if( C == ISO8859_1Encoding ) + Codec = KTextCharCodec::createCodec( "ISO 8859-1" ); + // LocalEncoding + else + Codec = 0; + + // ensure at least a codec + if( Codec == 0 ) + Codec = KTextCharCodec::createLocalCodec(); + + return Codec; +} diff --git a/khexedit/lib/codecs/kdecimalbytecodec.cpp b/khexedit/lib/codecs/kdecimalbytecodec.cpp new file mode 100644 index 0000000..9470382 --- /dev/null +++ b/khexedit/lib/codecs/kdecimalbytecodec.cpp @@ -0,0 +1,92 @@ +/*************************************************************************** + kdecimalbytecodec.cpp - description + ------------------- + begin : Mo Nov 29 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "kdecimalbytecodec.h" + +using namespace KHE; + + +void KDecimalByteCodec::encode( QString &Digits, unsigned int Pos, unsigned char Char ) const +{ + unsigned char C = Char / 100; + Digits.at(Pos++) = '0'+C; + Char -= C * 100; + C = Char / 10; + Digits.at(Pos++) = '0'+C; + Char -= C * 10; + Digits.at(Pos) = '0'+Char; +} + + +void KDecimalByteCodec::encodeShort( QString &Digits, unsigned int Pos, unsigned char Char ) const +{ + unsigned char C; + if( (C = Char / 100) ) + { + Digits.at(Pos++) = '0'+C; + Char -= C * 100; + } + if( (C = Char / 10) ) + { + Digits.at(Pos++) = '0'+C; + Char -= C * 10; + } + Digits.at(Pos) = '0'+Char; +} + + + +bool KDecimalByteCodec::isValidDigit( unsigned char Digit ) const +{ + return Digit >= '0' && Digit <= '9'; +} + +bool KDecimalByteCodec::turnToValue( unsigned char *Digit ) const +{ + if( isValidDigit(*Digit) ) + { + *Digit -= '0'; + return true; + } + return false; +} + + +bool KDecimalByteCodec::appendDigit( unsigned char *Byte, unsigned char Digit ) const +{ + if( turnToValue(&Digit) ) + { + unsigned char B = *Byte; + if( B < 26 ) + { + B *= 10; + if( Digit <= 255-B ) + { + B += Digit; + *Byte = B; + return true; + } + } + } + return false; +} + +void KDecimalByteCodec::removeLastDigit( unsigned char *Byte ) const +{ + *Byte /= 10; +} diff --git a/khexedit/lib/codecs/kdecimalbytecodec.h b/khexedit/lib/codecs/kdecimalbytecodec.h new file mode 100644 index 0000000..31f61d0 --- /dev/null +++ b/khexedit/lib/codecs/kdecimalbytecodec.h @@ -0,0 +1,59 @@ +/*************************************************************************** + kdecimalbytecodec.h - description + ------------------- + begin : Mo Nov 29 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KDECIMALBYTECODEC_H +#define KHE_KDECIMALBYTECODEC_H + +// lib specific +#include "kbytecodec.h" + +namespace KHE +{ + +/** class that is able to convert codings to and from binary + * + * the buffer will be always filled up to CodingWidth, if not using shortCodingFunction + * a closing '\0' will be always added + * + *@author Friedrich W. H. Kossebau + */ + +class KDecimalByteCodec : public KByteCodec +{ + public: // API to be implemented + /** */ + virtual unsigned int encodingWidth() const { return 3; } + /** */ + virtual unsigned char digitsFilledLimit() const { return 26; } + + /** encodes the Char and writes the result to */ + virtual void encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const; + /** */ + virtual void encodeShort( QString &Digits, unsigned int Pos, const unsigned char Char ) const; + /** */ + virtual bool appendDigit( unsigned char *Byte, const unsigned char Digit ) const; + /** */ + virtual void removeLastDigit( unsigned char *Byte ) const; + /** */ + virtual bool isValidDigit( const unsigned char Digit ) const; + /** */ + virtual bool turnToValue( unsigned char *Digit ) const; +}; + +} + +#endif diff --git a/khexedit/lib/codecs/kebcdic1047charcodec.cpp b/khexedit/lib/codecs/kebcdic1047charcodec.cpp new file mode 100644 index 0000000..f26da37 --- /dev/null +++ b/khexedit/lib/codecs/kebcdic1047charcodec.cpp @@ -0,0 +1,124 @@ +/*************************************************************************** + kebcdic1047charcodec.cpp - description + ------------------- + begin : Sa Nov 27 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "kebcdic1047charcodec.h" + + +using namespace KHE; + +static Q_UINT16 UnicodeChars[256] = +{ + 0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F, + 0x0097, 0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087, + 0x0018, 0x0019, 0x0092, 0x008F, 0x001C, 0x001D, 0x001E, 0x001F, + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x000A, 0x0017, 0x001B, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0005, 0x0006, 0x0007, + 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095, 0x0096, 0x0004, + 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E, 0x001A, + 0x0020, 0x00A0, 0x00E2, 0x00E4, 0x00E0, 0x00E1, 0x00E3, 0x00E5, + 0x00E7, 0x00F1, 0x00A2, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C, + 0x0026, 0x00E9, 0x00EA, 0x00EB, 0x00E8, 0x00ED, 0x00EE, 0x00EF, + 0x00EC, 0x00DF, 0x0021, 0x0024, 0x002A, 0x0029, 0x003B, 0x005E, + 0x002D, 0x002F, 0x00C2, 0x00C4, 0x00C0, 0x00C1, 0x00C3, 0x00C5, + 0x00C7, 0x00D1, 0x00A6, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F, + 0x00F8, 0x00C9, 0x00CA, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, + 0x00CC, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022, + 0x00D8, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x00AB, 0x00BB, 0x00F0, 0x00FD, 0x00FE, 0x00B1, + 0x00B0, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, + 0x0071, 0x0072, 0x00AA, 0x00BA, 0x00E6, 0x00B8, 0x00C6, 0x00A4, + 0x00B5, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, + 0x0079, 0x007A, 0x00A1, 0x00BF, 0x00D0, 0x005B, 0x00DE, 0x00AE, + 0x00AC, 0x00A3, 0x00A5, 0x00B7, 0x00A9, 0x00A7, 0x00B6, 0x00BC, + 0x00BD, 0x00BE, 0x00DD, 0x00A8, 0x00AF, 0x005D, 0x00B4, 0x00D7, + 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x00AD, 0x00F4, 0x00F6, 0x00F2, 0x00F3, 0x00F5, + 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, + 0x0051, 0x0052, 0x00B9, 0x00FB, 0x00FC, 0x00F9, 0x00FA, 0x00FF, + 0x005C, 0x00F7, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, + 0x0059, 0x005A, 0x00B2, 0x00D4, 0x00D6, 0x00D2, 0x00D3, 0x00D5, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x00B3, 0x00DB, 0x00DC, 0x00D9, 0x00DA, 0x009F +}; + +static unsigned char EBCDICChars[256] = +{ + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, + 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, + 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, + 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, + 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, + 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, + 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, + 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, + 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, + 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, + 0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC, + 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, + 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, + 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, + 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, + 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, + 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59, + 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, + 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, + 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, + 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF +}; + +static const char KEBCDIC1047CharCodecName[] = "EBCDIC 1047"; + + +bool KEBCDIC1047CharCodec::encode( char *D, const QChar &C ) const +{ + int I = C.unicode(); + // not in range? + if( 0x00FF < I ) + return false; + + *D = EBCDICChars[I]; + return true; +} + +KHEChar KEBCDIC1047CharCodec::decode( char Byte ) const +{ + return QChar(UnicodeChars[(unsigned char)Byte]); +} + +const QString& KEBCDIC1047CharCodec::name() const +{ + return codecName(); +} + +const QString& KEBCDIC1047CharCodec::codecName() +{ + static const QString Name( QString::fromLatin1(KEBCDIC1047CharCodecName) ); + return Name; +} diff --git a/khexedit/lib/codecs/kebcdic1047charcodec.h b/khexedit/lib/codecs/kebcdic1047charcodec.h new file mode 100644 index 0000000..7c30956 --- /dev/null +++ b/khexedit/lib/codecs/kebcdic1047charcodec.h @@ -0,0 +1,50 @@ +/*************************************************************************** + kebcdic1047charcodec.h - description + ------------------- + begin : Sa Nov 27 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KEBCDIC1047CHARCODEC_H +#define KHE_KEBCDIC1047CHARCODEC_H + + +#include "kcharcodec.h" + +namespace KHE +{ + +// +class KEBCDIC1047CharCodec : public KCharCodec +{ + protected: + KEBCDIC1047CharCodec(); + + public: // KCharCodec API + virtual KHEChar decode( char Byte ) const; + virtual bool encode( char *D, const QChar &C ) const; + virtual const QString& name() const; + + public: + static KEBCDIC1047CharCodec *create(); + static const QString& codecName(); +}; + + +inline KEBCDIC1047CharCodec::KEBCDIC1047CharCodec() {} + +inline KEBCDIC1047CharCodec *KEBCDIC1047CharCodec::create() { return new KEBCDIC1047CharCodec(); } + +} + +#endif diff --git a/khexedit/lib/codecs/khexadecimalbytecodec.cpp b/khexedit/lib/codecs/khexadecimalbytecodec.cpp new file mode 100644 index 0000000..7072464 --- /dev/null +++ b/khexedit/lib/codecs/khexadecimalbytecodec.cpp @@ -0,0 +1,113 @@ +/*************************************************************************** + khexadecimalbytecodec.cpp - description + ------------------- + begin : Mo Nov 29 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "khexadecimalbytecodec.h" + +using namespace KHE; + + +static const QChar BigDigit[16] = +{ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; +static const QChar SmallDigit[16] = +{ '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; + + +KHexadecimalByteCodec::KHexadecimalByteCodec( bool S ) : Digit( S?SmallDigit:BigDigit ) {} + +bool KHexadecimalByteCodec::setSmallDigits( bool S ) +{ + bool Change = ( S && Digit == BigDigit ); + Digit = S?SmallDigit:BigDigit; + return Change; +} + +bool KHexadecimalByteCodec::smallDigits() const { return Digit != BigDigit; } + + +void KHexadecimalByteCodec::encode( QString &Digits, unsigned int Pos, unsigned char Char ) const +{ + Digits.at(Pos++) = Digit[Char>>4]; + Digits.at(Pos) = Digit[Char&0x0F]; +} + +void KHexadecimalByteCodec::encodeShort( QString &Digits, unsigned int Pos, unsigned char Char ) const +{ + unsigned char C; + if( (C = (Char>>4)) ) + Digits.at(Pos++) = Digit[C]; + Digits.at(Pos) = Digit[Char&0x0F]; +} + + +static inline bool isValidBigDigit( unsigned char Digit ) +{ + return (Digit >= 'A' && Digit <= 'F'); +} + +static inline bool isValidSmallDigit( unsigned char Digit ) +{ + return (Digit >= 'a' && Digit <= 'f'); +} + +static inline bool isValidDecimalDigit( unsigned char Digit ) +{ + return Digit >= '0' && Digit <= '9'; +} + + +bool KHexadecimalByteCodec::isValidDigit( unsigned char Digit ) const +{ + return isValidDecimalDigit(Digit) || isValidBigDigit(Digit) || isValidSmallDigit(Digit); +} + +bool KHexadecimalByteCodec::turnToValue( unsigned char *Digit ) const +{ + if( isValidDecimalDigit(*Digit) ) + *Digit -= '0'; + else if( isValidBigDigit(*Digit) ) + *Digit -= 'A' - 10; + else if( isValidSmallDigit(*Digit) ) + *Digit -= 'a' - 10; + else + return false; + + return true; +} + +bool KHexadecimalByteCodec::appendDigit( unsigned char *Byte, unsigned char Digit ) const +{ + if( turnToValue(&Digit) ) + { + unsigned char B = *Byte; + if( B < 16 ) + { + B <<= 4; + B += Digit; + *Byte = B; + return true; + } + } + return false; +} + + + +void KHexadecimalByteCodec::removeLastDigit( unsigned char *Byte ) const +{ + *Byte >>= 4; +} diff --git a/khexedit/lib/codecs/khexadecimalbytecodec.h b/khexedit/lib/codecs/khexadecimalbytecodec.h new file mode 100644 index 0000000..9bb1969 --- /dev/null +++ b/khexedit/lib/codecs/khexadecimalbytecodec.h @@ -0,0 +1,69 @@ +/*************************************************************************** + khexadecimalbytecodec.h - description + ------------------- + begin : Mo Nov 29 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KHEXADECIMALBYTECODEC_H +#define KHE_KHEXADECIMALBYTECODEC_H + +// lib specific +#include "kbytecodec.h" + +namespace KHE +{ + +/** class that is able to convert codings to and from hexadecimal + * + * the buffer will be always filled up to CodingWidth, if not using shortCodingFunction + * a closing '\0' will be always added + * + *@author Friedrich W. H. Kossebau + */ + +class KHexadecimalByteCodec : public KByteCodec +{ + public: + KHexadecimalByteCodec( bool S = false ); + + public: + bool setSmallDigits( bool S ); + bool smallDigits() const; + + public: // API to be implemented + /** */ + virtual unsigned int encodingWidth() const { return 2; } + /** */ + virtual unsigned char digitsFilledLimit() const { return 16; } + + /** encodes the Char and writes the result to */ + virtual void encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const; + /** */ + virtual void encodeShort( QString &Digits, unsigned int Pos, const unsigned char Char ) const; + /** */ + virtual bool appendDigit( unsigned char *Byte, const unsigned char Digit ) const; + /** */ + virtual void removeLastDigit( unsigned char *Byte ) const; + /** */ + virtual bool isValidDigit( const unsigned char Digit ) const; + /** */ + virtual bool turnToValue( unsigned char *Digit ) const; + + protected: + const QChar* Digit; +}; + +} + +#endif diff --git a/khexedit/lib/codecs/koctalbytecodec.cpp b/khexedit/lib/codecs/koctalbytecodec.cpp new file mode 100644 index 0000000..1167941 --- /dev/null +++ b/khexedit/lib/codecs/koctalbytecodec.cpp @@ -0,0 +1,80 @@ +/*************************************************************************** + koctalbytecodec.cpp - description + ------------------- + begin : Mo Nov 29 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "koctalbytecodec.h" + +using namespace KHE; + + +void KOctalByteCodec::encode( QString &Digits, unsigned int Pos, unsigned char Char ) const +{ + Digits.at(Pos++) = '0'+(Char>>6); + Digits.at(Pos++) = '0'+((Char>>3)&0x07); + Digits.at(Pos) = '0'+((Char) &0x07); +} + + +void KOctalByteCodec::encodeShort( QString &Digits, unsigned int Pos, unsigned char Char ) const +{ + unsigned char C; + if( (C = (Char>>6)&0x07) ) + Digits.at(Pos++) = '0'+C; + if( (C = (Char>>3)&0x07) ) + Digits.at(Pos++) = '0'+C; + Digits.at(Pos) = '0'+((Char)&0x07); +} + + +bool KOctalByteCodec::isValidDigit( unsigned char Digit ) const +{ + return Digit >= '0' && Digit <= '7'; +} + + +bool KOctalByteCodec::turnToValue( unsigned char *Digit ) const +{ + if( isValidDigit(*Digit) ) + { + *Digit -= '0'; + return true; + } + return false; +} + + +bool KOctalByteCodec::appendDigit( unsigned char *Byte, unsigned char Digit ) const +{ + if( turnToValue(&Digit) ) + { + unsigned char B = *Byte; + if( B < 64 ) + { + B <<= 3; + B += Digit; + *Byte = B; + return true; + } + } + return false; +} + + +void KOctalByteCodec::removeLastDigit( unsigned char *Byte ) const +{ + *Byte >>= 3; +} diff --git a/khexedit/lib/codecs/koctalbytecodec.h b/khexedit/lib/codecs/koctalbytecodec.h new file mode 100644 index 0000000..e05ca66 --- /dev/null +++ b/khexedit/lib/codecs/koctalbytecodec.h @@ -0,0 +1,59 @@ +/*************************************************************************** + koctalbytecodec.h - description + ------------------- + begin : Mo Nov 29 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KOCTALBYTECODEC_H +#define KHE_KOCTALBYTECODEC_H + +// lib specific +#include "kbytecodec.h" + +namespace KHE +{ + +/** class that is able to convert codings to and from binary + * + * the buffer will be always filled up to CodingWidth, if not using shortCodingFunction + * a closing '\0' will be always added + * + *@author Friedrich W. H. Kossebau + */ + +class KOctalByteCodec : public KByteCodec +{ + public: // API to be implemented + /** */ + virtual unsigned int encodingWidth() const { return 3; } + /** */ + virtual unsigned char digitsFilledLimit() const { return 64; } + + /** encodes the Char and writes the result to */ + virtual void encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const; + /** */ + virtual void encodeShort( QString &Digits, unsigned int Pos, const unsigned char Char ) const; + /** */ + virtual bool appendDigit( unsigned char *Byte, const unsigned char Digit ) const; + /** */ + virtual void removeLastDigit( unsigned char *Byte ) const; + /** */ + virtual bool isValidDigit( const unsigned char Digit ) const; + /** */ + virtual bool turnToValue( unsigned char *Digit ) const; +}; + +} + +#endif diff --git a/khexedit/lib/codecs/ktextcharcodec.cpp b/khexedit/lib/codecs/ktextcharcodec.cpp new file mode 100644 index 0000000..613dedd --- /dev/null +++ b/khexedit/lib/codecs/ktextcharcodec.cpp @@ -0,0 +1,236 @@ +/*************************************************************************** + ktextcharcodec.cpp - description + ------------------- + begin : Sa Nov 27 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include "qtextcodec.h" +// kde specific +#include +#include +#include +// lib specific +#include "ktextcharcodec.h" + + +using namespace KHE; + +static const char QTextCodecWhiteSpace = 63; + +static struct KEncodingNames { + KEncoding Encoding; + const char *Name; +} +const EncodingNames[] = { +{ ISO8859_1Encoding, "ISO 8859-1" }, +{ ISO8859_2Encoding, "ISO 8859-2" }, +{ ISO8859_3Encoding, "ISO 8859-3" }, +{ ISO8859_4Encoding, "ISO 8859-4" }, +{ ISO8859_5Encoding, "ISO 8859-5" }, +{ ISO8859_6Encoding, "ISO 8859-6" }, +{ ISO8859_7Encoding, "ISO 8859-7" }, +{ ISO8859_8Encoding, "ISO 8859-8" }, +{ ISO8859_8_IEncoding, "ISO 8859-8-I" }, +{ ISO8859_9Encoding, "ISO 8859-9" }, +{ ISO8859_11Encoding, "ISO 8859-11" }, +{ ISO8859_13Encoding, "ISO 8859-13" }, +{ ISO8859_15Encoding, "ISO 8859-15" }, +{ CP1250Encoding, "CP 1250" }, +{ CP1251Encoding, "CP 1251" }, +{ CP1252Encoding, "CP 1252" }, +{ CP1253Encoding, "CP 1253" }, +{ CP1254Encoding, "CP 1254" }, +{ CP1255Encoding, "CP 1255" }, +{ CP1256Encoding, "CP 1256" }, +{ CP1257Encoding, "CP 1257" }, +{ CP1258Encoding, "CP 1258" }, +{ IBM850Encoding, "IBM 850" }, +{ IBM866Encoding, "IBM 866" }, +{ KOI8_REncoding, "KOI8-R" }, +{ KOI8_UEncoding, "KOI8-U" } }; +//TODO: WS2 +static const unsigned int NoOfEncodings = 26; + +static bool is8Bit( QTextCodec *Codec ) +{ + bool Found = false; + for( unsigned int i=0; iname(),EncodingNames[i].Name) == 0 ) + { + Found = true; + break; + } + } + return Found; +} + +static QTextCodec *createLatin1() +{ + return KGlobal::charsets()->codecForName( EncodingNames[0].Name ); +} + +/** heuristic seems to be doomed :( +static bool is8Bit( QTextCodec *Codec ) +{ + bool Result = true; + + // first test different for 0 + unsigned char c[4]; + c[0] = 0; + c[1] = c[2] = c[3] = 230; + QString S = Codec->toUnicode( (const char*)&c,4 ); + int Length = 1; + QCString CS = Codec->fromUnicode( S, Length ); + //kdDebug() << Codec->name() << " "< 0 ) + Result = false; + // test if all chars survive the recoding + else + do + { + ++c[0]; + S = Codec->toUnicode( (const char*)&c,4 ); + Length = 1; + CS = Codec->fromUnicode( S, Length ); + //kdDebug() << Codec->name() << " "<"<availableEncodingNames(); + + for( QStringList::ConstIterator it = CharSets.begin(); it != CharSets.end(); ++it ) +{ + bool Found = true; + QTextCodec* Codec = KGlobal::charsets()->codecForName( *it, Found ); + if( Found && is8Bit(Codec) ) + CodecNames.append( QString::fromLatin1(Codec->name()) ); +} +} + + return CodecNames; +} + +QString KTextCharCodec::nameOfEncoding( KEncoding C ) +{ + KTextCharCodec *Codec = 0; + + const char* N = 0; + for( unsigned int i=0; icodecForEncoding(); + if( !is8Bit(Codec) ) + Codec = createLatin1(); + return new KTextCharCodec( Codec ); +} + + +KTextCharCodec *KTextCharCodec::createCodec( const QString &CodeName ) +{ + bool Ok; + QTextCodec *Codec = KGlobal::charsets()->codecForName( CodeName, Ok ); + if( Ok ) + Ok = is8Bit( Codec ); + return Ok ? new KTextCharCodec( Codec ) : 0; +} + + +const QStringList &KTextCharCodec::codecNames() +{ + // first call? + if( CodecNames.isEmpty() ) + { + for( unsigned int i=0; icodecForName( Name, Found ); + if( Found ) + CodecNames.append( QString::fromLatin1(Codec->name()) ); + } + } + + return CodecNames; +} + + +KTextCharCodec::KTextCharCodec( QTextCodec *C ) + : Codec( C ), + Decoder( C->makeDecoder() ), + Encoder( C->makeEncoder() ) +{} + +KTextCharCodec::~KTextCharCodec() +{ + delete Decoder; + delete Encoder; +} + +bool KTextCharCodec::encode( char *D, const QChar &C ) const +{ + if( !Codec->canEncode(C) ) // TODO: do we really need the codec? + return false; + int dummy; + char T = Encoder->fromUnicode( C, dummy )[0]; + + *D = T; + return true; +} + + +KHEChar KTextCharCodec::decode( char Byte ) const +{ + QString S( Decoder->toUnicode(&Byte,1) ); + return KHEChar(S.at(0)); +} + + +const QString& KTextCharCodec::name() const +{ + if( Name.isNull() ) + Name = QString::fromLatin1( Codec->name() ); + return Name; +} diff --git a/khexedit/lib/codecs/ktextcharcodec.h b/khexedit/lib/codecs/ktextcharcodec.h new file mode 100644 index 0000000..683919c --- /dev/null +++ b/khexedit/lib/codecs/ktextcharcodec.h @@ -0,0 +1,66 @@ +/*************************************************************************** + ktextcharcodec.h - description + ------------------- + begin : Sa Nov 27 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KTEXTCHARCODEC_H +#define KHE_KTEXTCHARCODEC_H + + +#include "kcharcodec.h" + +class QTextCodec; +class QTextDecoder; +class QTextEncoder; + +namespace KHE +{ + +// used by all codecs with full char coping, i.e. there are no undefined chars +class KTextCharCodec : public KCharCodec +{ + public: + static KTextCharCodec *createCodec( const QString &CodeName ); + static KTextCharCodec *createCodec( KEncoding C ); + static KTextCharCodec *createLocalCodec(); + + static const QStringList &codecNames(); + + protected: + KTextCharCodec( QTextCodec *C ); + public: + virtual ~KTextCharCodec(); + + public: // KCharCodec API + virtual bool encode( char *D, const QChar &C ) const; + virtual KHEChar decode( char Byte ) const; + virtual const QString& name() const; + + + protected: + QTextCodec *Codec; + /** decodes the chars to unicode */ + QTextDecoder *Decoder; + /** encodes the chars from unicode */ + QTextEncoder *Encoder; + /** */ + mutable QString Name; + + static QStringList CodecNames; +}; + +} + +#endif diff --git a/khexedit/lib/controller/Makefile.am b/khexedit/lib/controller/Makefile.am new file mode 100644 index 0000000..5fd894b --- /dev/null +++ b/khexedit/lib/controller/Makefile.am @@ -0,0 +1,12 @@ +INCLUDES = -I$(srcdir)/.. $(all_includes) + +METASOURCES = AUTO + +# +noinst_LTLIBRARIES = libkcontroller.la +libkcontroller_la_SOURCES = kcontroller.cpp ktabcontroller.cpp knavigator.cpp \ + keditor.cpp kvalueeditor.cpp kchareditor.cpp + +# no public API +noinst_HEADERS = kcontroller.h ktabcontroller.h knavigator.h \ + keditor.h kvalueeditor.h kchareditor.h diff --git a/khexedit/lib/controller/kchareditor.cpp b/khexedit/lib/controller/kchareditor.cpp new file mode 100644 index 0000000..5b48fc6 --- /dev/null +++ b/khexedit/lib/controller/kchareditor.cpp @@ -0,0 +1,58 @@ +/*************************************************************************** + kchareditor.cpp - description + ------------------- + begin : Sa Dez 4 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +// lib specific +#include "kcharcolumn.h" +#include "kcharcodec.h" +#include "khexedit.h" +#include "kchareditor.h" + + +using namespace KHE; + + +KCharEditor::KCharEditor( KCharColumn *CC, KBufferCursor *BC, KHexEdit *HE, KController *P ) + : KEditor( BC, HE, P ), + CharColumn( CC ) +{ +} + + +bool KCharEditor::handleKeyPress( QKeyEvent *KeyEvent ) +{ + bool KeyUsed = false; + // some input that should be inserted? + if( KeyEvent->text().length() > 0 + && !(KeyEvent->state()&( Qt::ControlButton | Qt::AltButton | Qt::MetaButton )) ) + { + QChar C = KeyEvent->text()[0]; + if( C.isPrint() ) + { + QByteArray D( 1 ); + if( CharColumn->codec()->encode(&D[0],C) ) + { + // clearUndoRedoInfo = false; + HexEdit->insert( D ); + KeyUsed = true; + } + } + } + + return KeyUsed ? true : KEditor::handleKeyPress(KeyEvent); +} diff --git a/khexedit/lib/controller/kchareditor.h b/khexedit/lib/controller/kchareditor.h new file mode 100644 index 0000000..74c3d8d --- /dev/null +++ b/khexedit/lib/controller/kchareditor.h @@ -0,0 +1,43 @@ +/*************************************************************************** + kchareditor.h - description + ------------------- + begin : Sa Dez 4 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCHAREDITOR_H +#define KHE_KCHAREDITOR_H + +// lib specific +#include "keditor.h" + +namespace KHE +{ + +class KCharColumn; + +class KCharEditor : public KEditor +{ + public: + KCharEditor( KCharColumn *CC, KBufferCursor *BC, KHexEdit *HE, KController *P ); + + public: // KEditor API + virtual bool handleKeyPress( QKeyEvent *KeyEvent ); + + protected: + KCharColumn *CharColumn; +}; + +} + +#endif diff --git a/khexedit/lib/controller/kcontroller.cpp b/khexedit/lib/controller/kcontroller.cpp new file mode 100644 index 0000000..490da93 --- /dev/null +++ b/khexedit/lib/controller/kcontroller.cpp @@ -0,0 +1,34 @@ +/*************************************************************************** + kcontroller.cpp - description + ------------------- + begin : Sa Dez 4 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + + +// lib specific +#include "khexedit.h" +#include "kcontroller.h" + + +using namespace KHE; + +KController::KController( KHexEdit* HE, KController *P ) + : Parent( P ), HexEdit( HE ) +{ +} + +bool KController::handleKeyPress( QKeyEvent *KeyEvent ) +{ + return Parent ? Parent->handleKeyPress( KeyEvent ) : false; +} diff --git a/khexedit/lib/controller/kcontroller.h b/khexedit/lib/controller/kcontroller.h new file mode 100644 index 0000000..daeb0d5 --- /dev/null +++ b/khexedit/lib/controller/kcontroller.h @@ -0,0 +1,44 @@ +/*************************************************************************** + kcontroller.h - description + ------------------- + begin : Sa Dez 4 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCONTROLLER_H +#define KHE_KCONTROLLER_H + + +class QKeyEvent; + +namespace KHE +{ + +class KHexEdit; + +class KController +{ + protected: + KController( KHexEdit *HE, KController *P ); + + public: // KController API + virtual bool handleKeyPress( QKeyEvent *KeyEvent ); + + protected: + KController *Parent; + KHexEdit *HexEdit; +}; + +} + +#endif diff --git a/khexedit/lib/controller/keditor.cpp b/khexedit/lib/controller/keditor.cpp new file mode 100644 index 0000000..7d4e92f --- /dev/null +++ b/khexedit/lib/controller/keditor.cpp @@ -0,0 +1,197 @@ +/*************************************************************************** + keditor.cpp - description + ------------------- + begin : Sa Dez 4 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + + +// lib specific +#include "kdatabuffer.h" +#include "kbufferranges.h" +#include "kbufferlayout.h" +#include "kbuffercursor.h" +#include "kwordbufferservice.h" +#include "khexedit.h" +#include "keditor.h" + + +using namespace KHE; + +KEditor::KEditor( KBufferCursor *BC, KHexEdit* HE, KController *P ) + : KController( HE, P ), + BufferCursor( BC ) +{ +} + + +bool KEditor::handleKeyPress( QKeyEvent *KeyEvent ) +{ + bool clearUndoRedoInfo = true; + bool ShiftPressed = KeyEvent->state() & Qt::ShiftButton; + bool ControlPressed = KeyEvent->state() & Qt::ControlButton; + bool AltPressed = KeyEvent->state() & Qt::AltButton; + + bool KeyUsed = true; + // we only care for cursor keys and the like, won't hardcode any other keys + // we also don't check whether the commands are allowed + // as the commands are also available as API so the check has to be done + // in each command anyway + switch( KeyEvent->key() ) + { + case Qt::Key_Delete: + if( ShiftPressed ) + HexEdit->cut(); + else if( HexEdit->BufferRanges->hasSelection() ) + HexEdit->removeSelectedData(); + else + { + doEditAction( ControlPressed ? WordDelete : CharDelete ); + clearUndoRedoInfo = false; + } + break; + + case Qt::Key_Insert: + if( ShiftPressed ) + HexEdit->paste(); + else if( ControlPressed ) + HexEdit->copy(); + else + HexEdit->setOverwriteMode( !HexEdit->OverWrite ); + break; + + case Qt::Key_Backspace: + if( AltPressed ) + { + if( ControlPressed ) + break; + else if( ShiftPressed ) + { +// HexEdit->redo(); + break; + } + else + { +// HexEdit->undo(); + break; + } + } + else if( HexEdit->BufferRanges->hasSelection() ) + { + HexEdit->removeSelectedData(); + break; + } + + doEditAction( ControlPressed ? WordBackspace : CharBackspace ); + clearUndoRedoInfo = false; + break; + case Qt::Key_F16: // "Copy" key on Sun keyboards + HexEdit->copy(); + break; + case Qt::Key_F18: // "Paste" key on Sun keyboards + HexEdit->paste(); + break; + case Qt::Key_F20: // "Cut" key on Sun keyboards + HexEdit->cut(); + break; + + default: + KeyUsed = false; + } + +// if( clearUndoRedoInfo ) +// clearUndoRedo(); +// changeIntervalTimer->start( 100, true ); + + return KeyUsed ? true : KController::handleKeyPress(KeyEvent); +} + + + +void KEditor::doEditAction( KEditAction Action ) +{ + KSection ChangedRange; + + HexEdit->pauseCursor( true ); + + switch( Action ) + { + case CharDelete: + if( !HexEdit->OverWrite ) + { + int Index = BufferCursor->realIndex(); + if( Index < HexEdit->BufferLayout->length() ) + { + ChangedRange = HexEdit->removeData( KSection(Index,1,false) ); + if( Index == HexEdit->BufferLayout->length() ) + BufferCursor->gotoEnd(); + } + } + break; + + case WordDelete: // kills data until the start of the next word + if( !HexEdit->OverWrite ) + { + int Index = BufferCursor->realIndex(); + if( Index < HexEdit->BufferLayout->length() ) + { + KWordBufferService WBS( HexEdit->DataBuffer, HexEdit->Codec ); + int End = WBS.indexOfBeforeNextWordStart( Index ); + ChangedRange = HexEdit->removeData( KSection(Index,End) ); + if( Index == HexEdit->BufferLayout->length() ) + BufferCursor->gotoEnd(); + } + } + break; + + case CharBackspace: + if( HexEdit->OverWrite ) + BufferCursor->gotoPreviousByte(); + else + { + int DeleteIndex = BufferCursor->realIndex() - 1; + if( DeleteIndex >= 0 ) + { + ChangedRange = HexEdit->removeData( KSection(DeleteIndex,1,false) ); + if( DeleteIndex == HexEdit->BufferLayout->length() ) + BufferCursor->gotoEnd(); + else + BufferCursor->gotoPreviousByte(); + } + } + break; + case WordBackspace: + { + int LeftIndex = BufferCursor->realIndex() - 1; + if( LeftIndex >= 0 ) + { + KWordBufferService WBS( HexEdit->DataBuffer, HexEdit->Codec ); + int WordStart = WBS.indexOfPreviousWordStart( LeftIndex ); + if( !HexEdit->OverWrite ) + ChangedRange = HexEdit->removeData( KSection(WordStart,LeftIndex) ); + if( WordStart == HexEdit->BufferLayout->length() ) + BufferCursor->gotoEnd(); + else + BufferCursor->gotoIndex(WordStart); + } + } + } + + HexEdit->repaintChanged(); + HexEdit->ensureCursorVisible(); + + HexEdit->unpauseCursor(); + + emit HexEdit->cursorPositionChanged( BufferCursor->index() ); + if( ChangedRange.isValid() ) emit HexEdit->bufferChanged( ChangedRange.start(), ChangedRange.end() ); +} diff --git a/khexedit/lib/controller/keditor.h b/khexedit/lib/controller/keditor.h new file mode 100644 index 0000000..dc2b0fd --- /dev/null +++ b/khexedit/lib/controller/keditor.h @@ -0,0 +1,52 @@ +/*************************************************************************** + keditor.h - description + ------------------- + begin : Sa Dez 4 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KEDITOR_H +#define KHE_KEDITOR_H + + +// lib specific +#include "kcontroller.h" + + +namespace KHE +{ + +class KBufferCursor; + +class KEditor : public KController +{ + protected: + enum KEditAction { CharDelete, WordDelete, CharBackspace, WordBackspace }; + + protected: + KEditor( KBufferCursor *BC, KHexEdit *HE, KController *P ); + + public: // API + virtual bool handleKeyPress( QKeyEvent *KeyEvent ); + + protected: + /** executes keyboard Action \a Action. This is normally called by a key event handler. */ + void doEditAction( KEditAction Action ); + + protected: + KBufferCursor *BufferCursor; +}; + +} + +#endif diff --git a/khexedit/lib/controller/knavigator.cpp b/khexedit/lib/controller/knavigator.cpp new file mode 100644 index 0000000..51c8048 --- /dev/null +++ b/khexedit/lib/controller/knavigator.cpp @@ -0,0 +1,142 @@ +/*************************************************************************** + knavigator.cpp - description + ------------------- + begin : Sa Dez 4 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + + +// qt specific +#include +// lib specific +#include "kdatabuffer.h" +#include "kbufferranges.h" +#include "kbuffercursor.h" +#include "kwordbufferservice.h" +#include "khexedit.h" +#include "knavigator.h" + + +using namespace KHE; + +KNavigator::KNavigator( KHexEdit* HE, KController *P ) + : KController( HE, P ) +{ +} + +bool KNavigator::handleKeyPress( QKeyEvent *KeyEvent ) +{ + bool KeyUsed = true; + + //bool clearUndoRedoInfo = true; + bool ShiftPressed = KeyEvent->state() & Qt::ShiftButton; + bool ControlPressed = KeyEvent->state() & Qt::ControlButton; + //bool AltPressed = KeyEvent->state() & AltButton; + + // we only care for cursor keys and the like, won't hardcode any other keys + // we also don't check whether the commands are allowed + // as the commands are also available as API so the check has to be done + // in each command anyway + switch( KeyEvent->key() ) + { + case Qt::Key_Left: + moveCursor( ControlPressed ? MoveWordBackward : MoveBackward, ShiftPressed ); + break; + case Qt::Key_Right: + moveCursor( ControlPressed ? MoveWordForward : MoveForward, ShiftPressed ); + break; + case Qt::Key_Up: + moveCursor( ControlPressed ? MovePgUp : MoveUp, ShiftPressed ); + break; + case Qt::Key_Down: + moveCursor( ControlPressed ? MovePgDown : MoveDown, ShiftPressed ); + break; + case Qt::Key_Home: + moveCursor( ControlPressed ? MoveHome : MoveLineStart, ShiftPressed ); + break; + case Qt::Key_End: + moveCursor( ControlPressed ? MoveEnd : MoveLineEnd, ShiftPressed ); + break; + case Qt::Key_Prior: + moveCursor( MovePgUp, ShiftPressed ); + break; + case Qt::Key_Next: + moveCursor( MovePgDown, ShiftPressed ); + break; + + default: + KeyUsed = false; + } + + return KeyUsed ? true : KController::handleKeyPress(KeyEvent); +} + + +void KNavigator::moveCursor( KMoveAction Action, bool Select ) +{ + HexEdit->pauseCursor( true ); + + KBufferCursor *BufferCursor = HexEdit->BufferCursor; + KBufferRanges *BufferRanges = HexEdit->BufferRanges; + + if( Select ) + { + if( !BufferRanges->selectionStarted() ) + BufferRanges->setSelectionStart( BufferCursor->realIndex() ); + } + else + BufferRanges->removeSelection(); + + HexEdit->resetInputContext(); + switch( Action ) + { + case MoveBackward: BufferCursor->gotoPreviousByte(); break; + case MoveWordBackward: { + KWordBufferService WBS( HexEdit->DataBuffer, HexEdit->Codec ); + int NewIndex = WBS.indexOfPreviousWordStart( BufferCursor->realIndex() ); + BufferCursor->gotoIndex( NewIndex ); + } + break; + case MoveForward: BufferCursor->gotoNextByte(); break; + case MoveWordForward: { + KWordBufferService WBS( HexEdit->DataBuffer, HexEdit->Codec ); + int NewIndex = WBS.indexOfNextWordStart( BufferCursor->realIndex() ); + BufferCursor->gotoCIndex( NewIndex ); + } + break; + case MoveUp: BufferCursor->gotoUp(); break; + case MovePgUp: BufferCursor->gotoPageUp(); break; + case MoveDown: BufferCursor->gotoDown(); break; + case MovePgDown: BufferCursor->gotoPageDown(); break; + case MoveLineStart: BufferCursor->gotoLineStart(); break; + case MoveHome: BufferCursor->gotoStart(); break; + case MoveLineEnd: BufferCursor->gotoLineEnd(); break; + case MoveEnd: BufferCursor->gotoEnd(); break; + } + + if( Select ) + BufferRanges->setSelectionEnd( BufferCursor->realIndex() ); + + HexEdit->repaintChanged(); + HexEdit->ensureCursorVisible(); + + HexEdit->unpauseCursor(); + + if( BufferRanges->isModified() ) + { + if( !HexEdit->isOverwriteMode() ) emit HexEdit->cutAvailable( BufferRanges->hasSelection() ); + emit HexEdit->copyAvailable( BufferRanges->hasSelection() ); + KSection Selection = BufferRanges->selection(); + emit HexEdit->selectionChanged( Selection.start(), Selection.end() ); + } +} diff --git a/khexedit/lib/controller/knavigator.h b/khexedit/lib/controller/knavigator.h new file mode 100644 index 0000000..4615419 --- /dev/null +++ b/khexedit/lib/controller/knavigator.h @@ -0,0 +1,46 @@ +/*************************************************************************** + knavigator.h - description + ------------------- + begin : Sa Dez 4 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KNAVIGATOR_H +#define KHE_KNAVIGATOR_H + +// lib specific +#include "kcontroller.h" + +namespace KHE +{ + +class KNavigator : public KController +{ + protected: + enum KMoveAction { MoveBackward, MoveWordBackward, MoveForward, MoveWordForward, + MoveUp, MovePgUp, MoveDown, MovePgDown, + MoveLineStart, MoveHome, MoveLineEnd, MoveEnd }; + public: + KNavigator( KHexEdit *HE, KController *P ); + + public: // KEditor API + virtual bool handleKeyPress( QKeyEvent *KeyEvent ); + + protected: + /** moves the cursor according to the action, handles all drawing */ + void moveCursor( KMoveAction Action, bool Select ); +}; + +} + +#endif diff --git a/khexedit/lib/controller/ktabcontroller.cpp b/khexedit/lib/controller/ktabcontroller.cpp new file mode 100644 index 0000000..76c3051 --- /dev/null +++ b/khexedit/lib/controller/ktabcontroller.cpp @@ -0,0 +1,70 @@ +/*************************************************************************** + ktabcontroller.cpp - description + ------------------- + begin : So Dez 5 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +// lib specific +#include "kvaluecolumn.h" +#include "kcharcolumn.h" +#include "khexedit.h" +#include "ktabcontroller.h" + + +using namespace KHE; + +KTabController::KTabController( KHexEdit* HE, KController *P ) + : KController( HE, P ), + TabChangesFocus( false ) +{ +} + + +bool KTabController::handleKeyPress( QKeyEvent *KeyEvent ) +{ + bool KeyUsed = false; + + bool ShiftPressed = KeyEvent->state() & Qt::ShiftButton; + + if( KeyEvent->key() == Qt::Key_Tab ) + { + // are we in the char column? + if( HexEdit->cursorColumn() == KHexEdit::CharColumnId ) + { + // in last column we care about tab changes focus + if( HexEdit->ValueColumn->isVisible() && (!TabChangesFocus || ShiftPressed) ) + { + HexEdit->setCursorColumn( KHexEdit::ValueColumnId ); + KeyUsed = true; + } + } + // value column then + else + { + if( HexEdit->CharColumn->isVisible() ) + { + // in last column we care about tab changes focus + if( HexEdit->CharColumn->isVisible() && (!TabChangesFocus || !ShiftPressed) ) + { + HexEdit->setCursorColumn( KHexEdit::CharColumnId ); + KeyUsed = true; + } + } + } + } + + return KeyUsed ? true : KController::handleKeyPress(KeyEvent); +} diff --git a/khexedit/lib/controller/ktabcontroller.h b/khexedit/lib/controller/ktabcontroller.h new file mode 100644 index 0000000..e1898b4 --- /dev/null +++ b/khexedit/lib/controller/ktabcontroller.h @@ -0,0 +1,52 @@ +/*************************************************************************** + ktabcontroller.h - description + ------------------- + begin : So Dez 5 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KTABCONTROLLER_H +#define KHE_KTABCONTROLLER_H + + +// lib specific +#include "kcontroller.h" + + +namespace KHE +{ + +class KTabController : public KController +{ + public: + KTabController( KHexEdit *HE, KController *P ); + + public: // API + virtual bool handleKeyPress( QKeyEvent *KeyEvent ); + + public: + bool tabChangesFocus() const; + void setTabChangesFocus( bool TCF ); + + protected: + /** flag if tab key should be ignored */ + bool TabChangesFocus:1; +}; + + +inline bool KTabController::tabChangesFocus() const { return TabChangesFocus; } +inline void KTabController::setTabChangesFocus( bool TCF ) { TabChangesFocus = TCF; } + +} + +#endif diff --git a/khexedit/lib/controller/kvalueeditor.cpp b/khexedit/lib/controller/kvalueeditor.cpp new file mode 100644 index 0000000..ebfb589 --- /dev/null +++ b/khexedit/lib/controller/kvalueeditor.cpp @@ -0,0 +1,226 @@ +/*************************************************************************** + kvalueeditor.cpp - description + ------------------- + begin : Sa Dez 4 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +// lib specific +#include "kvaluecolumn.h" +#include "kbufferranges.h" +#include "kbuffercursor.h" +#include "khexedit.h" +#include "kvalueeditor.h" + + +using namespace KHE; + +KValueEditor::KValueEditor( KValueColumn *VC, KBufferCursor *BC, KHexEdit* HE, KController *P ) + : KEditor( BC, HE, P ), + ValueColumn( VC ), + InEditMode( false ), + EditModeByInsert( false ) +{ +} + + +bool KValueEditor::handleKeyPress( QKeyEvent *KeyEvent ) +{ + bool KeyUsed = true; + + // TODO: for now we don't touch it if there are selections + if( !HexEdit->BufferRanges->hasSelection() ) + { + // + switch( KeyEvent->key() ) + { + case Qt::Key_Plus: + doValueEditAction( IncValue ); + break; + case Qt::Key_Minus: + doValueEditAction( DecValue ); + break; + case Qt::Key_Space: + if( !InEditMode ) + { + KeyUsed = false; + break; + } + case Qt::Key_Enter: + case Qt::Key_Return: + doValueEditAction( InEditMode?LeaveValue:EnterValue ); + break; + case Qt::Key_Escape: + if( InEditMode ) + doValueEditAction( CancelValue ); + else + KeyUsed = false; + break; + case Qt::Key_Backspace: + if( InEditMode ) + doValueEditAction( ValueBackspace ); + else + KeyUsed = false; + break; + default: + // is plain char? + if( KeyEvent->text().length() > 0 + && ( !(KeyEvent->state()&( Qt::ControlButton | Qt::AltButton | Qt::MetaButton )) ) ) + { + QChar C = KeyEvent->text()[0]; + // no usable char? + if( !C.isLetterOrNumber() ) + { + KeyUsed = false; + break; + } + int Input = C.latin1(); + + if( InEditMode ) + doValueEditAction( ValueAppend, Input ); + else + { + unsigned char InputValue = 0; + const KByteCodec *ByteCodec = ValueColumn->byteCodec(); + // valid digit? + if( ByteCodec->appendDigit(&InputValue,Input) ) + { + if( HexEdit->OverWrite ) + doValueEditAction( ValueEdit, InputValue ); + else + { + int Index = BufferCursor->realIndex(); + if( HexEdit->DataBuffer->insert(Index,(char*)&InputValue,1) > 0 ) + { + HexEdit->pauseCursor(); + HexEdit->updateLength(); + + InEditMode = true; + EditModeByInsert = true; + OldValue = EditValue = InputValue; + ByteCodec->encode( ByteBuffer, 0, EditValue ); + + BufferCursor->gotoRealIndex(); + KSection ChangedRange( Index,HexEdit->DataBuffer->size()-1 ); + HexEdit->BufferRanges->addChangedRange( ChangedRange ); + HexEdit->repaintChanged(); + HexEdit->ensureCursorVisible(); + HexEdit->unpauseCursor(); + HexEdit->updateCursor(); + emit HexEdit->bufferChanged( ChangedRange.start(), ChangedRange.end() ); + } + } + } + } + } + else + KeyUsed = false; + } + } + else + KeyUsed = false; + + return KeyUsed ? true : KEditor::handleKeyPress(KeyEvent); +} + + +void KValueEditor::doValueEditAction( KValueEditAction Action, int Input ) +{ + // we are not yet in edit mode? + if( !InEditMode ) + { + int ValidIndex = BufferCursor->validIndex(); + // no valid cursor position? + if( ValidIndex == -1 || (!HexEdit->OverWrite && Input == -1) || BufferCursor->isBehind() ) + return; + + InEditMode = true; + EditModeByInsert = false; // default, to be overwritten if so + + // save old value + OldValue = EditValue = (unsigned char)HexEdit->DataBuffer->datum(ValidIndex); + } + + const KByteCodec *ByteCodec = ValueColumn->byteCodec(); + // + unsigned char NewValue = EditValue; + bool StayInEditMode = true; + bool MoveToNext = false; + + switch( Action ) + { + case ValueEdit: + NewValue = Input; + EditValue = NewValue^255; // force update + EditModeByInsert = true; + break; + case ValueBackspace: + if( NewValue > 0 ) + ByteCodec->removeLastDigit( &NewValue ); + break; + case EnterValue: + EditValue ^= 255; // force update + break; + case IncValue: + if( NewValue < 255 ) + ++NewValue; + break; + case DecValue: + if( NewValue > 0 ) + --NewValue; + break; + case ValueAppend: + if( ByteCodec->appendDigit(&NewValue,Input) ) + if( EditModeByInsert && NewValue >= ByteCodec->digitsFilledLimit() ) + { + StayInEditMode = false; + MoveToNext = true; + } + break; + case LeaveValue: + StayInEditMode = false; + MoveToNext = EditModeByInsert; + break; + case CancelValue: + NewValue = OldValue; + StayInEditMode = false; + break; + } + + bool Changed = (NewValue != EditValue); + int Index = BufferCursor->index(); + if( Changed ) + { + // sync value + EditValue = NewValue; + ByteCodec->encode( ByteBuffer, 0, EditValue ); + + HexEdit->DataBuffer->replace( Index, 1, (char*)&EditValue, 1 ); + } + + HexEdit->updateCursor(); + + if( !StayInEditMode ) + { + HexEdit->pauseCursor(); + InEditMode = false; + if( MoveToNext ) + BufferCursor->gotoNextByte(); + HexEdit->unpauseCursor(); + } + + if( Changed ) + if( Action != EnterValue ) emit HexEdit->bufferChanged( Index, Index ); +} diff --git a/khexedit/lib/controller/kvalueeditor.h b/khexedit/lib/controller/kvalueeditor.h new file mode 100644 index 0000000..496bcde --- /dev/null +++ b/khexedit/lib/controller/kvalueeditor.h @@ -0,0 +1,75 @@ +/*************************************************************************** + kvalueeditor.h - description + ------------------- + begin : Sa Dez 4 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KVALUEEDITOR_H +#define KHE_KVALUEEDITOR_H + + +// lib specific +#include "keditor.h" + +namespace KHE +{ + +class KValueColumn; + + +class KValueEditor: public KEditor +{ + protected: + enum KValueEditAction + { EnterValue, IncValue, DecValue, ValueAppend, ValueEdit, LeaveValue, CancelValue, ValueBackspace }; + + public: + KValueEditor( KValueColumn *VC, KBufferCursor *BC, KHexEdit *HE, KController *P ); + virtual ~KValueEditor(); + + public: // KEditor API + virtual bool handleKeyPress( QKeyEvent *KeyEvent ); + + public: + void reset(); + + public: + bool isInEditMode() const; + + protected: + /** executes keyboard Action \a Action. This is normally called by a key event handler. */ + void doValueEditAction( KValueEditAction Action, int Input = -1 ); + + public://protected: + KValueColumn *ValueColumn; + /** flag whether we are in editing mode */ + bool InEditMode:1; + /** flag whether byte edit mode was reached by inserting */ + bool EditModeByInsert:1; + /** */ + unsigned char EditValue; + /** stores the old byte value */ + unsigned char OldValue; + /** buffer with the */ + QString ByteBuffer; +}; + +inline KValueEditor::~KValueEditor() {} + +inline bool KValueEditor::isInEditMode() const { return InEditMode; } +inline void KValueEditor::reset() { InEditMode = false; } + +} + +#endif diff --git a/khexedit/lib/helper.h b/khexedit/lib/helper.h new file mode 100644 index 0000000..600ac5b --- /dev/null +++ b/khexedit/lib/helper.h @@ -0,0 +1,31 @@ +/*************************************************************************** + helper.h - description + ------------------- + begin : Fri Oct 03 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + +#ifndef KHEXEDIT_HELPER +#define KHEXEDIT_HELPER + +// qt specific +#include +// lib specific +#include + +// temporary solution until syntax highlighting is implemented +static inline QColor colorForChar( const KHE::KHEChar Byte ) +{ + return Byte.isUndefined() ? Qt::yellow : Byte.isPunct() ? Qt::red : Byte.isPrint() ? Qt::black : Qt::blue; +} + +#endif diff --git a/khexedit/lib/kadds.h b/khexedit/lib/kadds.h new file mode 100644 index 0000000..77c86f5 --- /dev/null +++ b/khexedit/lib/kadds.h @@ -0,0 +1,36 @@ +/*************************************************************************** + kadds.h - description + ------------------- + begin : Die Mai 20 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KADDS_H +#define KHE_KADDS_H + +namespace KHE +{ +// some possibly usefull aditions to KDE + +// these are to emphasize that measuring unit is pixel and which direction +typedef int KPixelX; +typedef int KPixelY; + +class KSection; + +typedef KSection KPixelXs; +typedef KSection KPixelYs; + +} + +#endif diff --git a/khexedit/lib/kbigbuffer.cpp b/khexedit/lib/kbigbuffer.cpp new file mode 100644 index 0000000..8505ef7 --- /dev/null +++ b/khexedit/lib/kbigbuffer.cpp @@ -0,0 +1,216 @@ +/*************************************************************************** + kbigbuffer.cpp - description + ------------------- + begin : Mit Jun 02 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// c specific +#include +// lib specific +#include "kbigbuffer.h" + +using namespace KHE; + +KBigBuffer::KBigBuffer( int NP, int PS ) + : NoOfUsedPages( NP ), + NoOfFreePages( NP ), + PageSize( PS ), + FirstPage( -1 ), + LastPage( -1 ), + Size( 0 ) +{ + IsOpen = false; + +// if( !filename.empty() ) +// open(filename); +} + + +KBigBuffer::~KBigBuffer() +{ + if( File.isOpen() ) + close(); +} + + + +bool KBigBuffer::prepareRange( KSection /*Range*/ ) const +{ + return true; +} + +const char *KBigBuffer::dataSet( KSection /*Section*/ ) const +{ + return 0; +} + + +char KBigBuffer::datum( unsigned int DatumOffset ) const +{ +// std::cout << "reading datum " << DatumOffset << std::endl; + int OffsetInPage = DatumOffset - OffsetOfActualPage; + // there shouldn't be any need to check l + if( OffsetInPage >= 0 && OffsetInPage < (int)PageSize ) + return ActualPage[OffsetInPage]; + + // load the page + unsigned int PageIndex = DatumOffset / PageSize; + ensurePageLoaded( PageIndex ); + return ActualPage[DatumOffset-OffsetOfActualPage]; +} + + + + +int KBigBuffer::insert( int /*Pos*/, const char*, int /*Length*/ ) +{ + return 0; +} + +int KBigBuffer::remove( KSection /*Section*/ ) +{ + return 0; +} + +unsigned int KBigBuffer::replace( KSection /*Section*/, const char*, unsigned int /*Length*/ ) +{ + return 0; +} + +int KBigBuffer::fill( char /*FillChar*/, int /*Length*/, unsigned int /*Pos*/ ) +{ + return 0; +} + + +int KBigBuffer::move( int /*DestPos*/, KSection /*SourceSection*/ ) { return 0; } +//int KBigBuffer::find( const char*, int /*Length*/, int /*Pos*/ ) const { return 0; } +int KBigBuffer::find( const char*/*KeyData*/, int /*Length*/, KSection /*Section*/ ) const { return 0; } + +int KBigBuffer::rfind( const char*, int /*Length*/, int /*Pos*/ ) const { return 0; } + + + +bool KBigBuffer::open( const QString& FileName ) +{ + // clear old data + if( isOpen() && !close() ) // only occurs if close somehow fails. + return false; + + File.setName( FileName ); + if( !File.open(IO_ReadOnly|IO_Raw) ) + return false; + +// std::cout << "loading file " << FileName << std::endl; + + int FileSize = File.size(); + Size = FileSize; + + // calculate necessary number of pages + int NoOfPages = FileSize/PageSize + 1; + + // initialize Page pointers + Data.resize( NoOfPages ); + for( KPageOfChar::iterator D=Data.begin(); D!=Data.end(); ++D ) + *D = 0; + + FirstPage = LastPage = 0; + + return ensurePageLoaded( 0 ); +} + + +bool KBigBuffer::close() +{ + if( !isOpen() ) + return false; + + File.close(); + + if( File.status() == IO_UnspecifiedError ) + return false; + +// std::cout << "closing file " << std::endl; + + // free pages + for( KPageOfChar::iterator D=Data.begin(); D!=Data.end(); ++D ) + delete [] *D; + + FirstPage = LastPage = -1; + NoOfFreePages = NoOfUsedPages; + + return true; +} + + +bool KBigBuffer::ensurePageLoaded( unsigned int PageIndex ) const +{ + if( !isOpen() ) + return false; + // page loaded? + if( Data[PageIndex] != 0 ) + { + ActualPage = Data[PageIndex]; + OffsetOfActualPage = PageIndex * PageSize; + return true; + } + + // no page available? + if( NoOfFreePages < 1 ) + { + // free the page which is the furthest away from the page we are loading + if( abs(FirstPage-PageIndex) > abs(LastPage-PageIndex) ) + while( !freePage(FirstPage++) ); + else + while( !freePage(LastPage--) ); + } + +// std::cout << "loading page " << PageIndex << std::endl; + // create Page + Data[PageIndex] = new char[PageSize]; + --NoOfFreePages; + + // jump to position and read the page's data in + bool Success = File.at( (unsigned long)(PageIndex*PageSize) ); + if( Success ) + Success = File.readBlock( Data[PageIndex], PageSize ) > 0; + + if( Success ) + { + // correct bounds + if( (int)PageIndex < FirstPage ) + FirstPage = PageIndex; + + if( (int)PageIndex > LastPage ) + LastPage = PageIndex; + + ActualPage = Data[PageIndex]; + OffsetOfActualPage = PageIndex * PageSize; + } + + return Success; +} + + +bool KBigBuffer::freePage( unsigned int PageIndex ) const +{ + // check range and if is loaded at all + if( (unsigned int)PageIndex >= Data.size() || !Data[PageIndex] ) + return false; +// std::cout << "freeing page " << PageIndex << std::endl; + delete [] Data[PageIndex]; + Data[PageIndex] = 0; + ++NoOfFreePages; + return true; +} diff --git a/khexedit/lib/kbigbuffer.h b/khexedit/lib/kbigbuffer.h new file mode 100644 index 0000000..138e64b --- /dev/null +++ b/khexedit/lib/kbigbuffer.h @@ -0,0 +1,119 @@ +/*************************************************************************** + kbigbuffer.h - description + ------------------- + begin : Mit Jun 02 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBIGBUFFER_H +#define KHE_KBIGBUFFER_H + +// qt specific +#include +#include +// lib specific +#include "kdatabuffer.h" +#include "khexedit_export.h" + +namespace KHE { + +/** base class for all Data buffers that are used to display + * TODO: think about a way to inform KHexEdit that there has been + * a change in the buffer outside. what kind of changes are possible? + *@author Friedrich W. H. Kossebau + */ + +class KHEXEDIT_EXPORT KBigBuffer : public KDataBuffer +{ + typedef QValueVector KPageOfChar; + + public: + /** default is only 50*4k = 200k memory image */ + KBigBuffer( int NP = 50, int PS = 4096 ); + virtual ~KBigBuffer(); + + public: // KDataBuffer API + virtual bool prepareRange( KSection Range ) const; + virtual const char *dataSet( KSection S ) const; + virtual char datum( unsigned int Offset ) const; + virtual int size() const; + virtual bool isReadOnly() const; + virtual bool isModified() const; + + virtual int insert( int Pos, const char*, int Length ); + virtual int remove( KSection S ); + virtual unsigned int replace( KSection S, const char*, unsigned int InputLength ); + virtual int move( int DestPos, KSection SourceSection ); + virtual int fill( char FillChar, int Length = -1, unsigned int Pos = 0 ); + virtual void setDatum( unsigned int Offset, const char Char ); + + virtual void setModified( bool M = true ); + + //virtual int find( const char*, int Length, int Pos = 0 ) const; + virtual int find( const char*KeyData, int Length, KSection Section ) const; + virtual int rfind( const char*, int Length, int Pos = -1 ) const; + +/* virtual int find( const QString &expr, bool cs, bool wo, bool forward = true, int *index = 0 ); */ + + public: + void setReadOnly( bool RO = true ); + bool isOpen() const; + bool open (const QString& filename ); + bool close(); + + protected: + bool ensurePageLoaded( unsigned int PageIndex ) const; + bool freePage( unsigned int PageIndex ) const; + + + protected: + /** */ + mutable QFile File; + /** */ + bool ReadOnly:1; + bool IsOpen:1; + bool AtEOF:1; + /** maximum number of pages which could be currently loaded */ + unsigned int NoOfUsedPages; + /** number of actually not used pages (in terms of NoOfUsedPages) */ + mutable int NoOfFreePages; + /** number of bytes in a page */ + unsigned int PageSize; + /** first currently loaded page */ + mutable int FirstPage; + /** last currently loaded page */ + mutable int LastPage; + /** */ + mutable KPageOfChar Data; + /** */ + unsigned int Size; + + /** current offset */ + mutable unsigned int OffsetOfActualPage; + /** points to the actual page */ + mutable char* ActualPage; +}; + +inline int KBigBuffer::size() const { return Size; } +inline bool KBigBuffer::isReadOnly() const { return ReadOnly; } +inline bool KBigBuffer::isModified() const { return false; } +inline void KBigBuffer::setReadOnly( bool RO ) { ReadOnly = RO; } +inline void KBigBuffer::setModified( bool ) {} + +inline void KBigBuffer::setDatum( unsigned int, const char ) {} + +inline bool KBigBuffer::isOpen() const { return File.isOpen(); } + +} + +#endif diff --git a/khexedit/lib/kbordercoltextexport.cpp b/khexedit/lib/kbordercoltextexport.cpp new file mode 100644 index 0000000..d46490f --- /dev/null +++ b/khexedit/lib/kbordercoltextexport.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + kbordercoltextexport.cpp - description + ------------------- + begin : Sam Aug 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +// lib specific +#include "kbordercoltextexport.h" + + +using namespace KHE; + +static const uint BorderColumnTEWidth = 3; + + +int KBorderColTextExport::charsPerLine() const +{ + return BorderColumnTEWidth; +} + +void KBorderColTextExport::printFirstLine( QString &T, int /*Line*/ ) const +{ + print( T ); +} + +void KBorderColTextExport::printNextLine( QString &T ) const +{ + print( T ); +} + +void KBorderColTextExport::print( QString &T ) const +{ + T.append( " | " ); +} diff --git a/khexedit/lib/kbordercoltextexport.h b/khexedit/lib/kbordercoltextexport.h new file mode 100644 index 0000000..4103f0b --- /dev/null +++ b/khexedit/lib/kbordercoltextexport.h @@ -0,0 +1,40 @@ +/*************************************************************************** + kbordercoltextexport.h - description + ------------------- + begin : Sam Aug 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBORDERCOLTEXTEXPORT_H +#define KHE_KBORDERCOLTEXTEXPORT_H + +#include "kcoltextexport.h" + +namespace KHE +{ + +class KBorderColTextExport : public KColTextExport +{ + public: // API + void printFirstLine( QString &T, int Line ) const; + void printNextLine( QString &T) const; + /** tells how much chars per line are needed */ + int charsPerLine() const ; + + protected: + void print( QString &T ) const; +}; + +} + +#endif diff --git a/khexedit/lib/kbordercolumn.cpp b/khexedit/lib/kbordercolumn.cpp new file mode 100644 index 0000000..c590246 --- /dev/null +++ b/khexedit/lib/kbordercolumn.cpp @@ -0,0 +1,82 @@ +/*************************************************************************** + kbordercolumn.cpp - description + ------------------- + begin : Mit Mai 21 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +#include +// lib specific +#include "kcolumnsview.h" +#include "kbordercolumn.h" + + +using namespace KHE; + +static const KPixelX DefaultWidth = 9; +static const KPixelX LineX = DefaultWidth / 2; + + +KBorderColumn::KBorderColumn( KColumnsView *V, bool M ) + : KColumn( V ), + Middle( M ) +{ + setWidth( M?DefaultWidth:LineX-1 ); +} + +KBorderColumn::~KBorderColumn() +{ +} + + +void KBorderColumn::paintLine( QPainter *P ) +{ + if( LineHeight > 0 ) + { + KColumn::paintBlankLine( P ); + + if( Middle ) + { + int GridColor = View->style().styleHint( QStyle::SH_Table_GridLineColor, View ); + P->setPen( GridColor != -1 ? (QRgb)GridColor : View->colorGroup().mid() ); + P->drawLine( LineX, 0, LineX, LineHeight-1 ) ; + } + } +} + + +void KBorderColumn::paintFirstLine( QPainter *P, KPixelXs , int ) +{ + paintLine( P ); +} + + +void KBorderColumn::paintNextLine( QPainter *P ) +{ + paintLine( P ); +} + +void KBorderColumn::paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys ) +{ + KColumn::paintEmptyColumn( P,Xs,Ys ); + + KPixelX LX = x() + LineX; + if( Middle && Xs.includes(LX) ) + { + int GridColor = View->style().styleHint( QStyle::SH_Table_GridLineColor, View ); + P->setPen( GridColor != -1 ? (QRgb)GridColor : View->colorGroup().mid() ); + P->drawLine( LX, Ys.start(), LX, Ys.end() ) ; + } +} diff --git a/khexedit/lib/kbordercolumn.h b/khexedit/lib/kbordercolumn.h new file mode 100644 index 0000000..0a72c05 --- /dev/null +++ b/khexedit/lib/kbordercolumn.h @@ -0,0 +1,52 @@ +/*************************************************************************** + kbordercolumn.h - description + ------------------- + begin : Mit Mai 21 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBORDERCOLUMN_H +#define KHE_KBORDERCOLUMN_H + +#include "kcolumn.h" + +namespace KHE +{ + +/** column that does nothing but draw a vertical line in the middle of the column + * + *@author Friedrich W. H. Kossebau + */ + +class KBorderColumn : public KColumn +{ + public: + KBorderColumn( KColumnsView *V, bool M ); + ~KBorderColumn(); + + public: // KColumn-API + virtual void paintFirstLine( QPainter *P, KPixelXs Xs, int FirstLine ); + virtual void paintNextLine( QPainter *P ); + virtual void paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys ); + + protected: + virtual void paintLine( QPainter *P ); + + protected: + /** true if we are between two columns and should show a line */ + bool Middle; +}; + +} + +#endif diff --git a/khexedit/lib/kbuffercoltextexport.cpp b/khexedit/lib/kbuffercoltextexport.cpp new file mode 100644 index 0000000..a4ee91f --- /dev/null +++ b/khexedit/lib/kbuffercoltextexport.cpp @@ -0,0 +1,108 @@ +/*************************************************************************** + kbuffercoltextexport.cpp - description + ------------------- + begin : Sam Aug 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// c specific +#include +// lib specific +#include "kbuffercolumn.h" +#include "kbufferlayout.h" +#include "kbuffercoltextexport.h" + + +using namespace KHE; + +static const int DefaultTEByteSpacingWidth = 1; +static const int TEGroupSpacingWidth = 3; + +QString KBufferColTextExport::whiteSpace( uint s ) +{ + return QString().fill( ' ', s ); +} + +KBufferColTextExport::KBufferColTextExport( const KBufferColumn* BufferColumn, const char *D, + KCoordRange CR, int ByteWidth ) + : Data( D ), + CoordRange( CR ) +{ + NoOfBytesPerLine = BufferColumn->layout()->noOfBytesPerLine(); + Pos = new int[NoOfBytesPerLine]; + + // TODO: remove this hack and make it more general + int ByteSpacingWidth = BufferColumn->byteSpacingWidth(); + if( ByteSpacingWidth > 0 ) + ByteSpacingWidth = DefaultTEByteSpacingWidth; + + int SpacingTrigger = BufferColumn->noOfGroupedBytes()-1; + if( SpacingTrigger < 0 ) + SpacingTrigger = NoOfBytesPerLine; // ensures to never trigger the group spacing + + int N = 0; + int p = 0; + int gs = 0; + int *P = Pos; + for( ; P<&Pos[NoOfBytesPerLine]; ++P, ++p, ++gs ) + { + *P = N; + N += ByteWidth; + + // is there a space behind the actual byte (if it is not the last)? + if( gs == SpacingTrigger ) + { + N += TEGroupSpacingWidth; + gs = -1; + } + else + N += ByteSpacingWidth; + } + N -= (gs==0)?TEGroupSpacingWidth:ByteSpacingWidth; + + NoOfCharsPerLine = N; +} + + +KBufferColTextExport::~KBufferColTextExport() +{ + delete [] Pos; +} + + +int KBufferColTextExport::charsPerLine() const +{ + return NoOfCharsPerLine; +} + + +void KBufferColTextExport::printFirstLine( QString &T, int Line ) const +{ + PrintLine = Line; + PrintData = Data; + print( T ); +} + + +void KBufferColTextExport::printNextLine( QString &T ) const +{ + print( T ); +} + + +void KBufferColTextExport::print( QString &T ) const +{ + T.append( whiteSpace(NoOfCharsPerLine) ); + ++PrintLine; +} + diff --git a/khexedit/lib/kbuffercoltextexport.h b/khexedit/lib/kbuffercoltextexport.h new file mode 100644 index 0000000..6cb161d --- /dev/null +++ b/khexedit/lib/kbuffercoltextexport.h @@ -0,0 +1,73 @@ +/*************************************************************************** + kbuffercoltextexport.h - description + ------------------- + begin : Sam Aug 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBUFFERCOLTEXTEXPORT_H +#define KHE_KBUFFERCOLTEXTEXPORT_H + +// qt specific +#include +// lib specific +#include "kcoltextexport.h" +#include "kcoordrange.h" + + +namespace KHE +{ + +class KBufferColumn; + + +class KBufferColTextExport : public KColTextExport +{ + public: + KBufferColTextExport( const KBufferColumn* BF, const char *D, KCoordRange CR, int BytesWidth ); + virtual ~KBufferColTextExport(); + + public: // API + void printFirstLine( QString &T, int Line ) const; + void printNextLine( QString &T ) const; + /** tells how much chars per line are needed */ + int charsPerLine() const; + + + protected: // API to be reimplemented by subclasses + virtual void print( QString &T ) const; + + + protected: + static QString whiteSpace( uint s ); + + protected: + const char *Data; + KCoordRange CoordRange; + + int NoOfBytesPerLine; + + /** Line to print */ + mutable int PrintLine; + /** Data to print */ + mutable const char *PrintData; + + /** buffered value of how many chars a line needs */ + int NoOfCharsPerLine; + // positions where to paint the + int *Pos; +}; + +} + +#endif diff --git a/khexedit/lib/kbuffercolumn.cpp b/khexedit/lib/kbuffercolumn.cpp new file mode 100644 index 0000000..4291e00 --- /dev/null +++ b/khexedit/lib/kbuffercolumn.cpp @@ -0,0 +1,700 @@ +/*************************************************************************** + kbuffercolumn.cpp - description + ------------------- + begin : Mit Mai 14 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +//#include + +// qt specific +#include +// lib specific +#include "kcolumnsview.h" +#include "kbuffercursor.h" +#include "kbuffercolumn.h" +#include "kbufferlayout.h" +#include "kbufferranges.h" +#include "helper.h" +#include "kcharcodec.h" + +using namespace KHE; + +static const unsigned int StartsBefore = 1; +static const unsigned int EndsLater = 2; +static const char EmptyByte = ' '; + +static const KPixelX DefaultCursorWidth = 2; +static const KPixelX DefaultByteSpacingWidth = 3; +static const KPixelX DefaultGroupSpacingWidth = 9; +static const int DefaultNoOfGroupedBytes = 4; + +KBufferColumn::KBufferColumn( KColumnsView *CV, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R ) + : KColumn( CV ), + Buffer( B ), + Layout( L ), + Ranges( R ), + DigitWidth( 0 ), + DigitBaseLine( 0 ), + VerticalGrid( false ), + ByteWidth( 0 ), + ByteSpacingWidth( DefaultByteSpacingWidth ), + GroupSpacingWidth( DefaultGroupSpacingWidth ), + NoOfGroupedBytes( DefaultNoOfGroupedBytes ), + PosX( 0L ), + PosRightX( 0L ), + LastPos( 0 ) +{ +} + + +KBufferColumn::~KBufferColumn() +{ + delete [] PosX; + delete [] PosRightX; +} + + + +void KBufferColumn::set( KDataBuffer *B ) +{ + Buffer= B; +} + + +void KBufferColumn::resetXBuffer() +{ + delete [] PosX; + delete [] PosRightX; + + LastPos = Layout->noOfBytesPerLine()-1; + PosX = new KPixelX[LastPos+1]; + PosRightX = new KPixelX[LastPos+1]; + + if( PosX ) + recalcX(); +} + + +void KBufferColumn::setMetrics( KPixelX DW, KPixelY DBL ) +{ + DigitBaseLine = DBL; + setDigitWidth( DW ); +} + + +bool KBufferColumn::setDigitWidth( KPixelX DW ) +{ + // no changes? + if( DigitWidth == DW ) + return false; + + DigitWidth = DW; + // recalculate depend sizes + recalcByteWidth(); + + if( PosX ) + recalcX(); + return true; +} + + +bool KBufferColumn::setSpacing( KPixelX BSW, int NoGB, KPixelX GSW ) +{ + // no changes? + if( ByteSpacingWidth == BSW && NoOfGroupedBytes == NoGB && GroupSpacingWidth == GSW ) + return false; + + ByteSpacingWidth = BSW; + NoOfGroupedBytes = NoGB; + GroupSpacingWidth = GSW; + + // recalculate depend sizes + recalcVerticalGridX(); + + if( PosX ) + recalcX(); + return true; +} + + +bool KBufferColumn::setByteSpacingWidth( KPixelX BSW ) +{ + // no changes? + if( ByteSpacingWidth == BSW ) + return false; + + ByteSpacingWidth = BSW; + + // recalculate depend sizes + recalcVerticalGridX(); + + if( PosX ) + recalcX(); + return true; +} + + +bool KBufferColumn::setNoOfGroupedBytes( int NoGB ) +{ + // no changes? + if( NoOfGroupedBytes == NoGB ) + return false; + + NoOfGroupedBytes = NoGB; + + if( PosX ) + recalcX(); + return true; +} + + +bool KBufferColumn::setGroupSpacingWidth( KPixelX GSW ) +{ + // no changes? + if( GroupSpacingWidth == GSW ) + return false; + + GroupSpacingWidth = GSW; + + // recalculate depend sizes + recalcVerticalGridX(); + + if( PosX ) + recalcX(); + return true; +} + + +void KBufferColumn::recalcByteWidth() +{ + ByteWidth = DigitWidth; + recalcVerticalGridX(); +} + + +void KBufferColumn::recalcVerticalGridX() +{ + VerticalGridX = ByteWidth-1 + GroupSpacingWidth/2; +} + + +void KBufferColumn::recalcX() +{ + SpacingTrigger = noOfGroupedBytes() > 0 ? noOfGroupedBytes()-1 : LastPos+1; // last ensures to never trigger the spacing + + KPixelX NewWidth = 0; + int p = 0; + int gs = 0; + KPixelX *PX = PosX; + KPixelX *PRX = PosRightX; + for( ; PX<&PosX[LastPos+1]; ++PX, ++PRX, ++p, ++gs ) + { + *PX = NewWidth; + NewWidth += ByteWidth; + *PRX = NewWidth-1; + + // is there a space behind the actual byte (if it is not the last)? + if( gs == SpacingTrigger ) + { + NewWidth += GroupSpacingWidth; + gs = -1; + } + else + NewWidth += ByteSpacingWidth; + } + setWidth( PosRightX[LastPos]+1 ); +} + + +// TODO: why are inlined functions not available as symbols when defined before their use +//TODO: works not precisly for the byte rects but includes spacing and left and right +/*inline*/ int KBufferColumn::posOfX( KPixelX PX ) const +{ + if( !PosX ) + return NoByteFound; + + // translate + PX -= x(); + // search backwards for the first byte that is equalleft to x + for( int p=LastPos; p>=0; --p ) + if( PosX[p] <= PX ) + return p; + + return 0; //NoByteFound; +} + + +int KBufferColumn::magPosOfX( KPixelX PX ) const +{ + if( !PosX ) + return NoByteFound; + + // translate + PX -= x(); + // search backwards for the first byte that is equalleft to x + for( int p=LastPos; p>=0; --p ) + if( PosX[p] <= PX ) + { + // are we close to the right? + if( PosRightX[p]-PX < DigitWidth/2 ) // TODO: perhaps cache also the middle xpos's + ++p; + return p; + } + + return 0; //NoByteFound; +} + + +KSection KBufferColumn::posOfX( KPixelX PX, KPixelX PW ) const +{ + if( !PosX ) + return KSection(); + + // translate + PX -= x(); + int PRX = PX + PW - 1; + + KSection P; + // search backwards for the first byte that is equalleft to x + for( int p=LastPos; p>=0; --p ) + if( PosX[p] <= PRX ) + { + P.setEnd( p ); + for( ; p>=0; --p ) + if( PosX[p] <= PX ) + { + P.setStart( p ); + break; + } + break; + } + + return P; +} + + +KPixelX KBufferColumn::xOfPos( int Pos ) const { return x() + (PosX?PosX[Pos]:0); } +KPixelX KBufferColumn::rightXOfPos( int Pos ) const { return x() + (PosRightX?PosRightX[Pos]:0); } + + +int KBufferColumn::posOfRelX( KPixelX PX ) const +{ + if( !PosX ) + return NoByteFound; + + // search backwards for the first byte that is equalleft to x + for( int p=LastPos; p>=0; --p ) + if( PosX[p] <= PX ) + return p; + + return 0; //NoByteFound; +} + + +KSection KBufferColumn::posOfRelX( KPixelX PX, KPixelX PW ) const +{ + if( !PosX ) + return KSection(); + + int PRX = PX + PW - 1; + + KSection P; + // search backwards for the first byte that is equalleft to x + for( int p=LastPos; p>=0; --p ) + if( PosX[p] <= PRX ) + { + P.setEnd( p ); + for( ; p>=0; --p ) + if( PosX[p] <= PX ) + { + P.setStart( p ); + break; + } + break; + } + + return P; +} + + +KPixelX KBufferColumn::relXOfPos( int Pos ) const { return PosX ? PosX[Pos] : 0; } +KPixelX KBufferColumn::relRightXOfPos( int Pos ) const { return PosRightX ? PosRightX[Pos] : 0; } + + +KPixelXs KBufferColumn::wideXPixelsOfPos( KSection Positions ) const +{ + return KPixelXs( Positions.start()>0?rightXOfPos(Positions.start()-1)+1:xOfPos(Positions.start()), + Positions.end()0?relRightXOfPos(Positions.start()-1)+1:relXOfPos(Positions.start()), + Positions.end()hasContent(Line) ) +// return; + + paintPositions( P, Line, PaintPositions ); +} + + +void KBufferColumn::paintPositions( QPainter *P, int Line, KSection Pos ) +{ + const QColorGroup &CG = View->colorGroup(); + + // clear background + unsigned int BlankFlag = (Pos.start()!=0?StartsBefore:0) | (Pos.end()!=LastPos?EndsLater:0); + paintRange( P, CG.base(), Pos, BlankFlag ); + + // Go through the lines TODO: handle first and last line more effeciently + // check for leading and trailing spaces + KSection Positions( Layout->firstPos(KBufferCoord( Pos.start(), Line )), + Layout->lastPos( KBufferCoord( Pos.end(), Line )) ); + + // no bytes to paint? + if( !Layout->hasContent(Line) ) + return; + + // check for leading and trailing spaces + KSection Indizes( Layout->indexAtCoord(KBufferCoord( Positions.start(), Line )), Positions.width(), false ); + + unsigned int SelectionFlag; + unsigned int MarkingFlag; + KSection Selection; + KSection Marking; + bool HasMarking = Ranges->hasMarking(); + bool HasSelection = Ranges->hasSelection(); + + while( Positions.isValid() ) + { + KSection PositionsPart( Positions ); // set of positions to paint next + KSection IndizesPart( Indizes ); // set of indizes to paint next + // falls Marking nicht mehr gebuffert und noch zu erwarten + if( HasMarking && Marking.endsBefore(IndizesPart.start()) ) + { + // erhebe nchste Markierung im Bereich + HasMarking = isMarked( IndizesPart, &Marking, &MarkingFlag ); + } + // falls Selection nicht mehr gebuffert und noch zu erwarten + if( HasSelection && Selection.endsBefore(IndizesPart.start()) ) + { + // erhebe nchste Selection im Bereich + HasSelection = isSelected( IndizesPart, &Selection, &SelectionFlag ); + } + + if( Marking.start() == IndizesPart.start() ) + { + IndizesPart.setEnd( Marking.end() ); + PositionsPart.setEndByWidth( Marking.width() ); + if( PositionsPart.end() == Layout->lastPos(Line) ) MarkingFlag &= ~EndsLater; + if( PositionsPart.start() == Layout->firstPos(Line)) MarkingFlag &= ~StartsBefore; + paintMarking( P, PositionsPart, IndizesPart.start(), MarkingFlag ); + + } + else if( Selection.includes(IndizesPart.start()) ) + { + if( Selection.startsBehind(IndizesPart.start()) ) + SelectionFlag |= StartsBefore; + bool MarkingBeforeEnd = HasMarking && Marking.start() <= Selection.end(); + + IndizesPart.setEnd( MarkingBeforeEnd ? Marking.start()-1 : Selection.end() ); + PositionsPart.setEndByWidth( IndizesPart.width() ); + + if( MarkingBeforeEnd ) + SelectionFlag |= EndsLater; + if( PositionsPart.end() == Layout->lastPos(Line) ) SelectionFlag &= ~EndsLater; + if( PositionsPart.start() == Layout->firstPos(Line) ) SelectionFlag &= ~StartsBefore; + + paintSelection( P, PositionsPart, IndizesPart.start(), SelectionFlag ); + } + else + { + // calc end of plain text + if( HasMarking ) + IndizesPart.setEnd( Marking.start()-1 ); + if( HasSelection ) + IndizesPart.restrictEndTo( Selection.start()-1 ); + + PositionsPart.setEndByWidth( IndizesPart.width() ); + paintPlain( P, PositionsPart, IndizesPart.start() ); + } + Indizes.setStartBehind( IndizesPart ); + Positions.setStartBehind( PositionsPart ); + } + // we don't paint grids as default, perhaps we never will though it works + // paintGrid( P, Positions ); // TODO: get some unmodified Positions (see three lines before) +} + + +void KBufferColumn::paintPlain( QPainter *P, KSection Positions, int Index ) +{ + // paint all the bytes affected + for( int p=Positions.start(); p<=Positions.end(); ++p,++Index ) + { + KPixelX x = relXOfPos( p ); + + // draw the byte + P->translate( x, 0 ); + char Byte = Buffer->datum( Index ); + KHEChar B = Codec->decode( Byte ); + drawByte( P, Byte, B, colorForChar(B) ); + + P->translate( -x, 0 ); + } +} + + +void KBufferColumn::paintSelection( QPainter *P, KSection Positions, int Index, int Flag ) +{ + const QColorGroup &CG = View->colorGroup(); + + paintRange( P, CG.highlight(), Positions, Flag ); + + const QColor &HTC = CG.highlightedText(); + // paint all the bytes affected + for( int p=Positions.start(); p<=Positions.end(); ++p,++Index ) + { + KPixelX x = relXOfPos( p ); + + // draw the byte + P->translate( x, 0 ); + char Byte = Buffer->datum( Index ); + KHEChar B = Codec->decode( Byte ); + drawByte( P, Byte, B, HTC ); + + P->translate( -x, 0 ); + } +} + + +void KBufferColumn::paintMarking( QPainter *P, KSection Positions, int Index, int Flag ) +{ + const QColorGroup &CG = View->colorGroup(); + + paintRange( P, CG.text(), Positions, Flag ); + + const QColor &BC = CG.base(); + // paint all the bytes affected + for( int p=Positions.start(); p<=Positions.end(); ++p,++Index ) + { + KPixelX x = relXOfPos( p ); + + // draw the byte + P->translate( x, 0 ); + char Byte = Buffer->datum( Index ); + KHEChar B = Codec->decode( Byte ); + drawByte( P, Byte, B, BC ); + + P->translate( -x, 0 ); + } +} + + +// TODO: smarter calculation +void KBufferColumn::paintGrid( QPainter *P, KSection Range ) +{ + int st = 0; // counter for spacing triggering + P->setPen( Qt::black ); + // paint all the bytes affected + for( int p=Range.start(); p<=Range.end(); ++p,++st ) + { + KPixelX x = relXOfPos( p ); + + // draw the byte + P->translate( x, 0 ); + + // spacing behind byte and vertical grid enabled? + if( st == SpacingTrigger && p != LastPos ) + P->drawLine( VerticalGridX, 0, VerticalGridX, LineHeight-1 ) ; + + P->translate( -x, 0 ); + } +} + + +void KBufferColumn::paintRange( QPainter *P, const QColor &Color, KSection Positions, int Flag ) +{ + KPixelX RangeX = Flag & StartsBefore ? relRightXOfPos( Positions.start()-1 ) + 1 : relXOfPos( Positions.start() ); + KPixelX RangeW = (Flag & EndsLater ? relXOfPos( Positions.end()+1 ): relRightXOfPos( Positions.end() ) + 1) - RangeX; + + P->fillRect( RangeX,0,RangeW,LineHeight, QBrush(Color,Qt::SolidPattern) ); +} + + +void KBufferColumn::paintByte( QPainter *P, int Index ) +{ + char Byte = ( Index > -1 ) ? Buffer->datum( Index ) : EmptyByte; + KHEChar B = Codec->decode( Byte ); + + const QColorGroup &CG = View->colorGroup(); + QColor Color = CG.text(); + QBrush Brush( CG.base(), Qt::SolidPattern ); + + if( Index > -1 ) + { + if( Ranges->markingIncludes(Index) ) + { + Brush.setColor( CG.text() ); + Color = CG.base(); + } + else if( Ranges->selectionIncludes(Index) ) + { + Brush.setColor( CG.highlight() ); + Color = CG.highlightedText(); + } + else + { + Brush.setColor( CG.base() ); + Color = colorForChar( B ); + } + } + + P->fillRect( 0,0,ByteWidth,LineHeight, Brush ); + + if( Index > -1 ) + drawByte( P, Byte, B, Color ); +} + + +void KBufferColumn::paintFramedByte( QPainter *P, int Index, KFrameStyle FrameStyle ) +{ + paintByte( P, Index ); + char Byte = ( Index > -1 ) ? Buffer->datum( Index ) : EmptyByte; + KHEChar B = Codec->decode( Byte ); + + P->setPen( colorForChar(B) ); + if( FrameStyle == Frame ) + P->drawRect( 0, 0, ByteWidth, LineHeight ); + else if( FrameStyle == Left ) + P->drawLine( 0, 0, 0, LineHeight-1 ); + else + P->drawLine( ByteWidth-1,0,ByteWidth-1,LineHeight-1 ); +} + + +void KBufferColumn::paintCursor( QPainter *P, int Index ) +{ + char Byte = ( Index > -1 ) ? Buffer->datum( Index ) : EmptyByte; + KHEChar B = Codec->decode( Byte ); + P->fillRect( 0, 0, ByteWidth, LineHeight, QBrush(colorForChar(B),Qt::SolidPattern) ); +} + + +void KBufferColumn::drawByte( QPainter *P, char /*Byte*/, KHEChar B, const QColor &Color ) const +{ + P->setPen( Color ); + P->drawText( 0, DigitBaseLine, B ); +} + + +bool KBufferColumn::isSelected( KSection Range, KSection *Selection, unsigned int *Flag ) const +{ + KSection S; + unsigned int F = 0; + const KSection *OS = Ranges->firstOverlappingSelection( Range ); + if( !OS ) + return false; + S = *OS; + + // does selection start before asked range? + if( Range.start() > S.start() ) + { + S.setStart( Range.start() ); + F |= StartsBefore; + } + + // does selection go on behind asked range? + if( Range.end() < S.end() ) + { + S.setEnd( Range.end() ); + F |= EndsLater; + } + + *Selection = S; + *Flag = F; + return true; +} + + +bool KBufferColumn::isMarked( KSection Range, KSection *Marking, unsigned int *Flag ) const +{ + KSection M; + unsigned int F = 0; + const KSection *OM = Ranges->overlappingMarking( Range ); + if( !OM ) + return false; + M = *OM; + + // does selection start before asked range? + if( Range.start() > M.start() ) + { + M.setStart( Range.start() ); + F |= StartsBefore; + } + + // does selection go on behind asked range? + if( Range.end() < M.end() ) + { + M.setEnd( Range.end() ); + F |= EndsLater; + } + + *Marking = M; + *Flag = F; + return true; +} diff --git a/khexedit/lib/kbuffercolumn.h b/khexedit/lib/kbuffercolumn.h new file mode 100644 index 0000000..76ed8bc --- /dev/null +++ b/khexedit/lib/kbuffercolumn.h @@ -0,0 +1,253 @@ +/*************************************************************************** + kbuffercolumn.h - description + ------------------- + begin : Mit Mai 14 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBUFFERCOLUMN_H +#define KHE_KBUFFERCOLUMN_H + +// lib specific +#include "khe.h" +#include "kdatabuffer.h" +#include "khechar.h" +#include "kcolumn.h" +#include "kbufferlayout.h" +#include "ksection.h" + +class QPainter; +class QColor; + +namespace KHE +{ + +// class KHexEdit; +class KBufferRanges; +class KCharCodec; + +const int NoByteFound = -1; + +/** base class of all buffer column displayers + * holds all information about the vertical layout of a buffer column + * knows how to paint the data and the editing things (focus, cursor, selection) + * but does not offer + * + *@author Friedrich W. H. Kossebauint KBufferColumn::posOfX( KPixelX PX, bool *ToTheRightFlag ) const + */ +class KBufferColumn : public KColumn +{ + public: + enum KFrameStyle { Frame, Left, Right }; + public: + KBufferColumn( KColumnsView/*KHexEdit*/ *HE, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R ); + virtual ~KBufferColumn(); + + + public: // KColumn-API + virtual void paintFirstLine( QPainter *P, KPixelXs Xs, int FirstLine ); + virtual void paintNextLine( QPainter *P ); + + public: + void preparePainting( KPixelXs Xs ); + + public: + void paintLine( QPainter *P, int Line ); + void paintPositions( QPainter *P, int Line, KSection Positions ); + /** paints a cursor based on the type of the byte. + * @param Index Index of the byte to paint the cursor for. If -1 a space is used as char. + */ + void paintCursor( QPainter *P, int Index ); + /** paints the byte with background. + * @param Index Index of the byte to paint. If -1 only the background is painted. + */ + void paintByte( QPainter *P, int Index ); + /** paints the byte with background and a frame around. + * @param Index Index of the byte to paint the frame for. If -1 a space is used as char. + * @param Style the style of the framing + */ + void paintFramedByte( QPainter *P, int Index, KFrameStyle Style ); + + + public: // modification access + /** sets the spacing in the hex column + * @param ByteSpacingW spacing between the bytes in pixels + * @param NewNoOfGroupedBytes numbers of grouped bytes, 0 means no grouping + * @param GroupSpacingW spacing between the groups in pixels + * returns true if there was a change + */ + bool setSpacing( KPixelX ByteSpacingW, int NewNoOfGroupedBytes = 0, KPixelX GroupSpacingW = 0 ); + /** sets the spacing between the bytes in the hex column + * @param ByteSpacingW spacing between the bytes in pixels + * returns true if there was a change + */ + bool setByteSpacingWidth( KPixelX ByteSpacingW ); + /** sets the number of grouped bytes in the hex column + * @param NewNoOfGroupedBytes numbers of grouped bytes, 0 means no grouping + * returns true if there was a change + */ + bool setNoOfGroupedBytes( int NewNoOfGroupedBytes ); + /** sets the spacing between the groups of bytes in the hex column + * @param GroupSpacingW spacing between the groups in pixels + * returns true if there was a change + */ + bool setGroupSpacingWidth( KPixelX GroupSpacingW ); + /** sets width of digits and recalculates depend sizes + * returns true if there was a change + */ + bool setDigitWidth( KPixelX DW ); + /** sets the metrics of the used font + * @param NewDigitWidth the new width of a digit + * @param NewDigitBaseLine the new baseline of the digits + */ + void setMetrics( KPixelX NewDigitWidth, KPixelY NewDigitBaseLine ); + /** */ + void set( KDataBuffer *B ); + /** creates new buffer for x-values; to be called on any change of NoOfBytesPerLine or metrics */ + void resetXBuffer(); + /** sets the codec to be used by the char column. */ + void setCodec( KCharCodec *C ); + + public: // functional logic + /** returns byte positions covered by pixels with absolute x-coord x */ + KSection posOfX( KPixelX x, KPixelX w ) const; + /** returns byte pos at pixel with absolute x-coord x */ + int posOfX( KPixelX x ) const; + /** returns byte pos at pixel with absolute x-coord x, and sets the flag to true if we are closer to the right */ + int magPosOfX( KPixelX PX ) const; + /** returns absolute x-coord of byte at position Pos */ + KPixelX xOfPos( int Pos ) const; + /** returns right absolute x-coord of byte at position Pos */ + KPixelX rightXOfPos( int Pos ) const; + /** returns byte pos at pixel with relative x-coord x */ + int posOfRelX( KPixelX x ) const; + /** returns byte positions covered by pixels with relative x-coord x */ + KSection posOfRelX( KPixelX x, KPixelX w ) const; + /** returns relative x-coord of byte at position Pos */ + KPixelX relXOfPos( int Pos ) const; + /** returns right relative x-coord of byte at position Pos */ + KPixelX relRightXOfPos( int Pos ) const; + /** returns the positions that overlap with the absolute x-coords */ + KSection visiblePositions( KPixelX x, KPixelX w ) const; + /** returns the */ + KPixelXs wideXPixelsOfPos( KSection Positions ) const; + /** */ + KPixelXs relWideXPixelsOfPos( KSection Positions ) const; + + public: // value access + KPixelX byteWidth() const; + KPixelX digitWidth() const; + KPixelX groupSpacingWidth() const; + KPixelX byteSpacingWidth() const; + int noOfGroupedBytes() const; + + int firstPos() const; + int lastPos() const; + KSection visiblePositions() const; + const KBufferLayout *layout() const; + KCharCodec* codec() const; + + protected: + /** */ + void recalcX(); + void recalcVerticalGridX(); + + + protected: // API to be refined + /** default implementation simply prints the byte as ASCII */ + virtual void drawByte( QPainter *P, char Byte, KHEChar B, const QColor &Color ) const; + /** default implementation sets byte width to one digit width */ + virtual void recalcByteWidth(); + + + protected: + void paintGrid( QPainter *P, KSection Range ); + void paintPlain( QPainter *P, KSection Positions, int Index ); + void paintSelection( QPainter *P, KSection Positions, int Index, int Flag ); + void paintMarking( QPainter *P, KSection Positions, int Index, int Flag ); + void paintRange( QPainter *P, const QColor &Color, KSection Positions, int Flag ); + + bool isSelected( KSection Range, KSection *Selection, unsigned int *Flag ) const; + bool isMarked( KSection Range, KSection *Marking, unsigned int *Flag ) const; + + + protected: + /** pointer to the buffer */ + KDataBuffer *Buffer; + /** pointer to the layout */ + const KBufferLayout *Layout; + /** pointer to the ranges */ + KBufferRanges *Ranges; + /** */ + KCharCodec *Codec; + + /** */ + KPixelX DigitWidth; + /** */ + KPixelY DigitBaseLine; + /** */ + KPixelX VerticalGridX; + /** */ + bool VerticalGrid; + + protected: // individual data + /** total width of byte display in pixel */ + KPixelX ByteWidth; + /** width of inserting cursor in pixel */ + KPixelX CursorWidth; + /** size of the line margin */ + KPixelX ByteSpacingWidth; + /** width of spacing in pixel */ + KPixelX GroupSpacingWidth; + + /** number of grouped bytes */ + int NoOfGroupedBytes; + + /** pointer to array with buffered positions (relative to column position) + * a spacing gets assigned to the left byte -> ...c|c|c |c|c... + */ + KPixelX *PosX; + KPixelX *PosRightX; + /** index of right position */ + int LastPos; + + + protected: // buffering drawing data + KSection PaintPositions; + int PaintLine; + KPixelX PaintX; + KPixelX PaintW; + int SpacingTrigger; +}; + + +inline KPixelX KBufferColumn::byteWidth() const { return ByteWidth; } +inline KPixelX KBufferColumn::digitWidth() const { return DigitWidth; } +inline KPixelX KBufferColumn::byteSpacingWidth() const { return ByteSpacingWidth; } +inline KPixelX KBufferColumn::groupSpacingWidth() const { return GroupSpacingWidth; } + +inline int KBufferColumn::noOfGroupedBytes() const { return NoOfGroupedBytes; } + +inline int KBufferColumn::firstPos() const { return PaintPositions.start(); } +inline int KBufferColumn::lastPos() const { return PaintPositions.end(); } +inline KSection KBufferColumn::visiblePositions() const { return PaintPositions; } + +inline const KBufferLayout *KBufferColumn::layout() const { return Layout; } + + +inline void KBufferColumn::setCodec( KCharCodec *C ) { Codec = C; } +inline KCharCodec* KBufferColumn::codec() const { return Codec; } + +} + +#endif diff --git a/khexedit/lib/kbuffercoord.h b/khexedit/lib/kbuffercoord.h new file mode 100644 index 0000000..997551a --- /dev/null +++ b/khexedit/lib/kbuffercoord.h @@ -0,0 +1,293 @@ +/*************************************************************************** + kbuffercoord.h - description + ------------------- + begin : Don Mai 29 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBUFFERCOORD_H +#define KHE_KBUFFERCOORD_H + + +namespace KHE +{ + +/** + * a class which represents a coord in a 2-dim. system + * + * It consists of a line number and a position in the line. + * The coord starts at (0,0). Line numbers increase downwards, positions to the right. + * With any of both at a negative number the coord is invalid. + * TODO: change as much as possible params to unsigned integer + * + * @author Friedrich W. H. Kossebau + */ +class KBufferCoord +{ + public: + /** creates a coord with 0,0 */ + KBufferCoord(); + KBufferCoord( int P, int L ); + KBufferCoord( int Index, int LineWidth, bool /*dummy*/ ); + KBufferCoord( const KBufferCoord &C ); + KBufferCoord &operator=( const KBufferCoord &c ); + ~KBufferCoord(); + + + public: // logic + bool operator==( const KBufferCoord &c ) const; + bool operator!=( const KBufferCoord &c ) const; + bool operator<( const KBufferCoord &c ) const; + bool operator<=( const KBufferCoord &c ) const; + bool operator>( const KBufferCoord &c ) const; + bool operator>=( const KBufferCoord &c ) const; + + /** tests if the coord is prior in the same line than the given coord. + * If at least one of both is invalid the result is undefined. + * @return true if the pos is left to the pos of C and both are in the same line, otherwise false. + */ + bool isPriorInLineThan( const KBufferCoord &C ) const; + /** tests if the coord is later in the same line than the given coord. + * If at least one of both is invalid the result is undefined. + * @return true if the pos is right to the pos of C and both are in the same line, otherwise false + */ + bool isLaterInLineThan( const KBufferCoord &C ) const; + /** @return true if the line is below L, otherwise false */ + bool isBelow( int L ) const; + /** @return true if the line is above L, otherwise false */ + bool isAbove( int L ) const; + /** @return true if the coord is at (0,0) */ + bool isAtStart() const; + /** @return true if the pos is greater than 0, otherwise false */ + bool isBehindLineStart() const; + /** @return true if the pos is smaller than MaxPos, otherwise false */ + bool isBeforeLineEnd( int MaxPos ) const; + + /** calculates the index the coord is at with a given line width + * If the coord is invalid the result is undefined. + * @param LineWidth given width of line + * @return index the coord is at + */ + int indexByLineWidth( int LineWidth ) const; + + public: + /** set the coord by calculating it for an index with a given line width + * @param Index index in the buffer + * @param LineWidth given line width + */ + void setByIndexNWidth( int Index, int LineWidth ); + /** sets both position and line */ + void set( int P, int L ); + /** sets the position */ + void setPos( int P ); + /** sets the line */ + void setLine( int L ); + + /** moves the coord one position to the left. If the coord is invalid the result is undefined. */ + void goLeft(); + /** moves the coord a given number of positions to the left. + * If the coord is invalid the result is undefined or the position smaller then the given number + * the behaviour is undefined. + * @param P number of positions + */ + void goLeft( unsigned int P ); + /** moves the coord one position to the left, or if the position is already at the line start + * to the given position in the previous line. If the coord is invalid the result is undefined. + * @param MaxPos maximal allowed position + */ + void goCLeft( int MaxPos ); + /** moves the coord one position to the right. If the coord is invalid the result is undefined. */ + void goRight(); + /** moves the coord a given number of positions to the right. If the coord is invalid the result is undefined. + * @param P number of positions + */ + void goRight( unsigned int P ); + /** moves the coord one position to the right, or if the position has already reached or passed MaxPos + * to the first position in the next line. If the coord is invalid the result is undefined. + * @param MaxPos maximal allowed position + */ + void goCRight( int MaxPos ); + /** sets coord to (0,0) */ + void gotoStart(); + void gotoEndOfPreviousLine( int LastPos ); + /** sets the coord to the start of the next line. + * If the coord is invalid the behaviour is undefined. + */ + void gotoStartOfNextLine(); + /** sets the position to the start of the line or + * if the line is the same as that of the given coord to the position of it. + * If one or more of the coords is invalid the behaviour is undefined. + * @param C a possible line start coord + */ + void goLineStart( const KBufferCoord &C ); + /** sets the position to the given pos or + * if the line is the same as that of the given coord to the position of that. + * If one or more of the coords is invalid the behaviour is undefined. + * @param L last position in normal line + * @param C a possible line end coord + */ + void goLineEnd( int L, const KBufferCoord &C ); + /** moves the coord 1 lines upwards. There is no check whether the first line is overstepped. */ + void goUp(); + /** moves the coord L lines downwards. */ + void goDown(); + /** moves the coord L lines upwards. There is no check whether the first line is overstepped. + * @param L number of lines + */ + void goUp( unsigned int L ); + /** moves the coord L lines downwards. + * @param L number of lines + */ + void goDown( unsigned int L ); + + public: // state value access + /** @return the pos in the line */ + int pos() const; + /** @return the line number */ + int line() const; + /** @return true if the coord is valid */ + bool isValid() const; + + private: // member variables + /** Position in Line */ + int Pos; + /** Line */ + int Line; +}; + + +inline KBufferCoord::KBufferCoord() : Pos( 0 ), Line( 0 ) {} +inline KBufferCoord::KBufferCoord( int P, int L ) : Pos( P ), Line( L ) {} +inline KBufferCoord::KBufferCoord( int Index, int LineWidth, bool ) +{ + Line = Index / LineWidth; + Pos = Index - Line*LineWidth; +} + +inline KBufferCoord::KBufferCoord( const KBufferCoord &C ) : Pos( C.Pos ), Line( C.Line ) {} +inline KBufferCoord &KBufferCoord::operator=( const KBufferCoord &C ) { Pos = C.Pos; Line = C.Line; return *this; } +inline KBufferCoord::~KBufferCoord() {} + +inline bool KBufferCoord::operator==( const KBufferCoord &C ) const { return Pos == C.Pos && Line == C.Line; } +inline bool KBufferCoord::operator!=( const KBufferCoord &C ) const { return !(*this == C); } + +inline bool KBufferCoord::operator<( const KBufferCoord &C ) const +{ return Line < C.Line || (Line == C.Line && Pos( const KBufferCoord &C ) const +{ return Line > C.Line || (Line == C.Line && Pos>C.Pos); } +inline bool KBufferCoord::operator>=( const KBufferCoord &C ) const +{ return Line > C.Line || (Line == C.Line && Pos>=C.Pos); } + +inline int KBufferCoord::pos() const { return Pos; } +inline int KBufferCoord::line() const { return Line; } +inline bool KBufferCoord::isValid() const { return Line >= 0 && Pos >= 0; } + +inline void KBufferCoord::setByIndexNWidth( int Index, int LineWidth ) +{ + Line = Index / LineWidth; + Pos = Index - Line*LineWidth; +} + +inline void KBufferCoord::set( int P, int L ) +{ + Pos = P; + Line = L; +} +inline void KBufferCoord::setPos( int P ) { Pos = P; } +inline void KBufferCoord::setLine( int L ) { Line = L; } + +inline void KBufferCoord::goCRight( int MaxPos ) +{ + if( isBeforeLineEnd(MaxPos) ) + goRight(); + else + gotoStartOfNextLine(); +} +inline void KBufferCoord::goCLeft( int MaxPos ) +{ + if( isBehindLineStart() ) + goLeft(); + else + gotoEndOfPreviousLine( MaxPos ); +} + +inline void KBufferCoord::goRight() { ++Pos; } +inline void KBufferCoord::goLeft() { --Pos; } +inline void KBufferCoord::goRight( unsigned int P ) { Pos += P; } +inline void KBufferCoord::goLeft( unsigned int P ) { Pos -= P; } + +inline void KBufferCoord::gotoStart() { Pos = Line = 0; } + +inline void KBufferCoord::gotoEndOfPreviousLine( int LastPos ) +{ + --Line; + Pos = LastPos; +} + +inline void KBufferCoord::gotoStartOfNextLine() +{ + ++Line; + Pos = 0; +} + + +inline void KBufferCoord::goLineStart( const KBufferCoord &C ) +{ + Pos = ( Line == C.Line ) ? C.Pos : 0; +} + +inline void KBufferCoord::goLineEnd( int L, const KBufferCoord &C ) +{ + Pos = ( Line == C.Line ) ? C.Pos : L; +} + +inline void KBufferCoord::goUp() { --Line; } +inline void KBufferCoord::goDown() { ++Line; } +inline void KBufferCoord::goUp( unsigned int L ) { Line -= L; } +inline void KBufferCoord::goDown( unsigned int L ) { Line += L; } + + +inline int KBufferCoord::indexByLineWidth( int LineWidth ) const +{ + return Line * LineWidth + Pos; +} + + +inline bool KBufferCoord::isPriorInLineThan( const KBufferCoord &C ) const +{ + return Line == C.Line && Pos < C.Pos; +} + +inline bool KBufferCoord::isLaterInLineThan( const KBufferCoord &C ) const +{ + return Line == C.Line && Pos > C.Pos; +} + +inline bool KBufferCoord::isBelow( int L ) const { return Line > L; } +inline bool KBufferCoord::isAbove( int L ) const { return Line < L; } + +inline bool KBufferCoord::isBehindLineStart() const { return Pos > 0; } +inline bool KBufferCoord::isBeforeLineEnd( int MaxPos ) const { return Pos < MaxPos; } + +inline bool KBufferCoord::isAtStart() const { return Pos == 0 && Line == 0; } + +inline KBufferCoord operator+( const KBufferCoord &C, int p ) +{ + return KBufferCoord( C.pos()+p, C.line() ); +} + +} + +#endif diff --git a/khexedit/lib/kbuffercursor.cpp b/khexedit/lib/kbuffercursor.cpp new file mode 100644 index 0000000..0255d2d --- /dev/null +++ b/khexedit/lib/kbuffercursor.cpp @@ -0,0 +1,365 @@ +/*************************************************************************** + kbuffercursor.cpp - description + ------------------- + begin : Don Mai 29 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +//#include + +// lib specific +#include "kbufferlayout.h" +#include "kbuffercursor.h" + +using namespace KHE; + +KBufferCursor::KBufferCursor( const KBufferLayout *L ) + : Layout( L ), + Index( 0 ), + Coord( 0, 0 ), + Behind( false ), + AppendPosEnabled( false ) +{ +} + +KBufferCursor::~KBufferCursor() +{ +} + + +bool KBufferCursor::operator==( const KBufferCursor &C ) const +{ + return Index == C.Index && Behind == C.Behind ; +} + + +void KBufferCursor::setAppendPosEnabled( bool APE ) +{ + if( AppendPosEnabled == APE ) + return; + + AppendPosEnabled = APE; + // reposition Cursor + int Length = Layout->length(); + // behind buffer end, not end of line and not empty? + if( realIndex() >= Length && Coord.pos() < Layout->noOfBytesPerLine()-1 && Length > 0 ) + { + if( AppendPosEnabled ) + { + ++Index; + Coord.goRight(); + Behind = false; + } + else + { + --Index; + Coord.goLeft(); + Behind = true; + } + } +} + + +void KBufferCursor::gotoPreviousByte() +{ + if( Behind ) + Behind = false; + else if( Index > 0 ) + { + --Index; + Coord.goCLeft( Layout->noOfBytesPerLine()-1 ); + } +} + + +void KBufferCursor::gotoPreviousByte( int D ) +{ + if( Behind ) + { + --D; + Behind = false; + } + if( D > Index ) + { + if( Index == 0 ) + return; + gotoStart(); + } + gotoIndex( Index - D ); +} + + +void KBufferCursor::gotoNextByte() +{ + int Length = Layout->length(); + + if( Index < Length ) + { + if( Index == Length-1 ) + stepToEnd(); + else + { + ++Index; + Coord.goCRight( Layout->noOfBytesPerLine()-1 ); + Behind = false; + } + } +} + + +void KBufferCursor::gotoNextByte( int D ) // TODO: think about consistency with gotoNextByte!!! +{ + if( Behind ) + { + ++D; + Behind = false; + } + // would we end behind the end? + if( Index+D >= Layout->length() ) + gotoEnd(); + else + gotoIndex( Index + D ); +} + + +void KBufferCursor::gotoNextByteInLine() +{ + int Length = Layout->length(); + + if( Index < Length ) + { + if( Index == Length-1 ) + stepToEnd(); + else + { + ++Index; + + if( Coord.pos() < Layout->noOfBytesPerLine()-1 ) + Coord.goRight(); + else + Behind = true; + } + } +} + + +void KBufferCursor::gotoUp() +{ + // can we even go up? + if( Coord.isBelow(Layout->startLine()) ) + { + Coord.goUp(); + if( Coord.isPriorInLineThan(Layout->start()) ) + { + Index = 0; + Coord.setPos( Layout->startPos() ); + Behind = false; + } + else + { + Index -= Layout->noOfBytesPerLine(); + if( Behind && !atLineEnd() ) + { + ++Index; + Coord.goRight(); + Behind = false; + } + } + } +} + + +void KBufferCursor::gotoDown() +{ + if( Coord.isAbove(Layout->finalLine()) ) + { + Coord.goDown(); + // behind End? + if( Coord.isLaterInLineThan(Layout->final()) ) + gotoEnd(); + else + Index += Layout->noOfBytesPerLine(); + } +} + + +void KBufferCursor::gotoLineStart() +{ + int OldIndex = Index; + Index = Layout->indexAtLineStart( Coord.line() ); + Coord.goLeft( OldIndex-Index ); + Behind = false; +} + + +void KBufferCursor::gotoLineEnd() +{ + if( Index < Layout->length() ) + { + int OldIndex = Index; + Index = Layout->indexAtLineEnd( Coord.line() ); + Coord.goRight( Index-OldIndex ); + + stepToEnd(); + } +} + + +void KBufferCursor::gotoStart() +{ + Index = 0; + Coord = Layout->start(); + Behind = false; +} + + +void KBufferCursor::gotoEnd() +{ + int Length = Layout->length(); + if( Length > 0 ) + { + Index = Length-1; + Coord = Layout->final(); + + stepToEnd(); + } + else + gotoStart(); +} + + +void KBufferCursor::gotoCIndex( int i ) +{ + if( Layout->length() > 0 ) + { + Index = Layout->correctIndex( i ); + Coord = Layout->coordOfIndex( Index ); + if( i > Index ) + stepToEnd(); + else + Behind = false; + } + else + gotoStart(); +} + + +void KBufferCursor::gotoCCoord( const KBufferCoord &C ) +{ + if( Layout->length() > 0 ) + { + Coord = Layout->correctCoord( C ); + Index = Layout->indexAtCoord( Coord ); + if( C > Coord ) + stepToEnd(); + else + Behind = false; + } + else + gotoStart(); +} + + +void KBufferCursor::stepToEnd() +{ + if( AppendPosEnabled && (Coord.pos() < Layout->noOfBytesPerLine()-1) ) + { + ++Index; + Coord.goRight(); + Behind = false; + } + else + Behind = true; +} + + +void KBufferCursor::gotoIndex( int i ) +{ + Index = i; + Coord = Layout->coordOfIndex( Index ); + Behind = false; +} + + +void KBufferCursor::gotoRealIndex() +{ + if( Behind ) + { + ++Index; + Coord = Layout->coordOfIndex( Index ); + Behind = false; + } +} + + +void KBufferCursor::gotoCoord( const KBufferCoord &C ) +{ + Index = Layout->indexAtCoord( C ); + Coord = C; + Behind = false; +} + + +void KBufferCursor::updateCoord() +{ + Coord = Layout->coordOfIndex( Index ); +} + +// page down should be: one page minus one line +// -> if in the very first line page down will put the cursor on the same page into the last line +void KBufferCursor::gotoPageUp() +{ + int NoOfLinesPerPage = Layout->noOfLinesPerPage(); + int NewIndex = Index - NoOfLinesPerPage * Layout->noOfBytesPerLine(); + if( NewIndex < 0 ) + gotoStart(); + else + { + Index = NewIndex; + Coord.goUp( NoOfLinesPerPage ); + if( Behind && !atLineEnd() ) + { + ++Index; + Coord.goRight(); + Behind = false; + } + } +} + + +void KBufferCursor::gotoPageDown() +{ + int NoOfLinesPerPage = Layout->noOfLinesPerPage(); + int NewIndex = Index + NoOfLinesPerPage * Layout->noOfBytesPerLine(); + if( NewIndex >= Layout->length() ) + gotoEnd(); + else + { + Index = NewIndex; + Coord.goDown( NoOfLinesPerPage ); + } +} + + +int KBufferCursor::validIndex() const { return Index < Layout->length() ? Index : -1; } +int KBufferCursor::indexAtLineStart() const { return Layout->indexAtLineStart( Coord.line() ); } +int KBufferCursor::indexAtLineEnd() const { return Layout->indexAtLineEnd( Coord.line() ); } + + +bool KBufferCursor::atStart() const { return Index == 0; } +bool KBufferCursor::atEnd() const { return Index == Layout->length() - 1; } +bool KBufferCursor::atAppendPos() const { return realIndex() >= Layout->length(); } + + +bool KBufferCursor::atLineStart() const { return Layout->atLineStart( Coord ); } +bool KBufferCursor::atLineEnd() const { return Layout->atLineEnd( Coord ); } diff --git a/khexedit/lib/kbuffercursor.h b/khexedit/lib/kbuffercursor.h new file mode 100644 index 0000000..855b3e8 --- /dev/null +++ b/khexedit/lib/kbuffercursor.h @@ -0,0 +1,172 @@ +/*************************************************************************** + kbuffercursor.h - description + ------------------- + begin : Don Mai 29 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBUFFERCURSOR_H +#define KHE_KBUFFERCURSOR_H + +#include "kbuffercoord.h" + + +namespace KHE +{ + +class KBufferLayout; + + +/**@short navigates through the buffer in an abstract way, based on the layout + * + * The cursor is allowed to access every coord that has content as + * described in the layout. It holds the coord of the actual position + * and the according index in the data array. + * + * To enable the cursor to be placed behind the last position in a line + * (e.g, to mark all data in the line without placing the cursor to the + * beginning of the next line) there is a flag Behind that should be read + * as that the real index the cursor is at is the current one + 1 + * (as returned by realIndex()) + * + * For appending new data to the buffer there is also the need to be able + * to place the cursor at a position behind the last byte. This can be + * enabled by calling setAppendPosEnabled(true). If the cursor is placed to + * this position it gets the (real) index of the last byte + 1. As this + * index does not point to an existing byte validIndex() returns -1. + * Check for atAppendPos() to see whether cursor is at this position. + * + * If the buffer is empty there is no navigation possible, of course. + * The cursor will be placed to coord 0/0 with index 1, Behind=false. + * + *@author Friedrich W. H. Kossebau + */ +class KBufferCursor +{ + public: + KBufferCursor( const KBufferLayout *L ); + ~KBufferCursor(); + + + public: + bool operator==( const KBufferCursor &c ) const; + bool operator!=( const KBufferCursor &c ) const { return !(*this == c); } + + public: // modificator + void setAppendPosEnabled( bool APE=true ); + + public: // state value access + /** the index that is drawn at the actual coord */ + int index() const; + /** the pos of the actual coord */ + int pos() const; + /** the line of the actual coord */ + int line() const; + /** the actual coord */ + KBufferCoord coord() const; + /** true if the cursor is located to the right of the actual coord but still shown at the coord */ + bool isBehind() const; + /** returns the real index. That is if the cursor is tagged as "behind" the current index + * it's real index is the next one. + * Attention: this could be outside the data's range if the cursor is behind the last byte! + */ + int realIndex() const; + /** returns the true index if it is valid index that is it is inside the data's range. + * Otherwise -1 is returned + */ + int validIndex() const; + + //bool isValid() const; + bool appendPosEnabled() const; + + public: // index calculation service + /** returns the index at the start of the cursor's line */ + int indexAtLineStart() const; + /** returns the index at the end of the cursor's line */ + int indexAtLineEnd() const; + + public: // navigation commands + void gotoIndex( int I ); + void gotoCoord( const KBufferCoord &C ); + void gotoCIndex( int I ); + void gotoCCoord( const KBufferCoord &C ); + void gotoRealIndex(); + + void gotoPreviousByte(); + void gotoNextByte(); + void gotoPreviousByte( int D ); + void gotoNextByte( int D ); + void gotoNextByteInLine(); + void gotoUp(); + void gotoDown(); + void gotoLineStart(); + void gotoLineEnd(); + void gotoStart(); + void gotoEnd(); + void gotoPageUp(); + void gotoPageDown(); + + /** puts the cursor behind the actual position if it isn't already*/ + void stepBehind(); + void updateCoord(); + + + public: // logical state access + bool atStart() const; + bool atEnd() const; + /** could only be true in InsertMode: Cursor is behind the last byte */ + bool atAppendPos() const; + bool atLineStart() const; + bool atLineEnd() const; + + + protected: + /** if newpos allowed steps at a coord behind the last existing + * or, if that is at a line end, behind the line + * does not check for empty content! + */ + void stepToEnd(); + + private: + /** layout, tells how the column is organized */ + const KBufferLayout *Layout; + + /** Position in buffer */ + int Index; + /** Position and Line */ + KBufferCoord Coord; + + /** tells whether the cursor is actually behind the actual position. + * This is used for selection to the end of a line or of the whole buffer. + */ + bool Behind : 1; + + /** tells whether there could be a position behind the end of the layout */ + bool AppendPosEnabled : 1; +}; + + +inline int KBufferCursor::index() const { return Index; } +inline int KBufferCursor::pos() const { return Coord.pos(); } +inline int KBufferCursor::line() const { return Coord.line(); } +inline KBufferCoord KBufferCursor::coord() const { return Coord; } +inline bool KBufferCursor::isBehind() const { return Behind; } +inline int KBufferCursor::realIndex() const { return Behind ? Index + 1 : Index; } + +inline void KBufferCursor::stepBehind() { Behind = true; } + +//inline bool KBufferCursor::isValid() const { return Index != -1; } + +} + +#endif diff --git a/khexedit/lib/kbufferdrag.cpp b/khexedit/lib/kbufferdrag.cpp new file mode 100644 index 0000000..199982c --- /dev/null +++ b/khexedit/lib/kbufferdrag.cpp @@ -0,0 +1,237 @@ +/*************************************************************************** + kbufferdrag.cpp - description + ------------------- + begin : Mon Jul 07 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +#include +// kde specific +#include +#include +// lib specific +#include "kbordercoltextexport.h" +#include "koffsetcoltextexport.h" +#include "kvaluecoltextexport.h" +#include "kcharcoltextexport.h" +#include "kcharcodec.h" +#include "kbufferdrag.h" + + +using namespace std; +using namespace KHE; + +static const char OctetStream[] = "application/octet-stream"; +static const char TextPlainUTF8[] = "text/plain;charset=UTF-8"; +static const char TextPlain[] = "text/plain"; +static const char TextPlainLocalStub[] = "text/plain;charset="; + +//static const char *BaseTypes[3] = { OctetStream, TextPlainUTF8, TextPlain }; + +// creates the name for the local text/plain +static const char *localTextPlain() +{ + static QCString TextPlainLocal; + + if( TextPlainLocal.isNull() ) + { + TextPlainLocal = QCString(KGlobal::locale()->encoding()).lower(); + // remove the whitespaces + int s; + while( (s=TextPlainLocal.find(' ')) >= 0 ) + TextPlainLocal.remove( s, 1 ); + + TextPlainLocal.prepend( TextPlainLocalStub ); + } + + return TextPlainLocal; +} + +// tries to create a codec by the given charset description +static QTextCodec* codecForCharset( const QCString& Desc ) +{ + int i = Desc.find( "charset=" ); + if( i >= 0 ) + { + QCString CharSetName = Desc.mid( i+8 ); + // remove any further attributes + if( (i=CharSetName.find( ';' )) >= 0 ) + CharSetName = CharSetName.left( i ); + + // try to find codec + return QTextCodec::codecForName( CharSetName ); + } + // no charset=, use locale + return KGlobal::locale()->codecForEncoding(); +} + + + +KBufferDrag::KBufferDrag( const QByteArray &D, KCoordRange Range, + const KOffsetColumn *OC, const KValueColumn *HC, const KCharColumn *TC, + QChar SC, QChar UC, const QString &CN, + QWidget *Source, const char *Name ) + :QDragObject( Source, Name ), + CoordRange( Range ), + NoOfCol( 0 ), + SubstituteChar( SC ), + UndefinedChar( UC ), + CodecName( CN ) +{ + setData( D ); + + // print column wise? + if( HC || TC ) + { + if( OC ) + { + Columns[NoOfCol++] = new KOffsetColTextExport( OC ); + Columns[NoOfCol++] = new KBorderColTextExport(); + } + if( HC ) + Columns[NoOfCol++] = new KValueColTextExport( HC, Data.data(), CoordRange ); + if( TC ) + { + if( HC ) Columns[NoOfCol++] = new KBorderColTextExport(); + Columns[NoOfCol++] = new KCharColTextExport( TC, Data.data(), CoordRange, CodecName ); + } + } +} + + +KBufferDrag::~KBufferDrag() +{ + for( uint i=0; idecode( Data[i] ); + + Text.at(i) = B.isUndefined() ? KHEChar(UndefinedChar) : + (!B.isPrint() && B != Tab && B != Return ) ? KHEChar(SubstituteChar) : B; + } + // clean up + delete CharCodec; + } + // formatted copy + else + { + // initialize: one for the line's newline \n + uint NeededChars = 1; + for( uint i=0; icharsPerLine(); + // scale with the number of lines + NeededChars *= CoordRange.lines(); + // find out needed size + Text.reserve( NeededChars ); + + // now fill + int l = CoordRange.start().line(); + for( uint i=0; iprintFirstLine( Text, l ); + Text.append('\n'); + for( ++l; l<=CoordRange.end().line(); ++l ) + { + for( uint i=0; iprintNextLine( Text ); + Text.append('\n'); + } + } + // generate the ouput + Output = TextCodec->fromUnicode( Text ); + // fix end + //if( TextCodec->mibEnum() != 1000 ) + //{ + // Don't include NUL in size (QCString::resize() adds NUL) + // ((QByteArray&)Output).resize( Output.length() ); + //} + return Output; + } + } + + // return empty dummy + return QByteArray(); +} + + + +bool KBufferDrag::canDecode( const QMimeSource* Source ) +{ + bool c =( Source->provides(OctetStream) /*|| Source->provides(TextPlain)*/ ); + return c; +// return( Source->provides(OctetStream) /*|| Source->provides(TextPlain)*/ ); +} + + +bool KBufferDrag::decode( const QMimeSource* Source, QByteArray &Dest ) +{ +// Dest = Source->encodedData( MediaString ); +// return Dest.size() != 0; + + bool CanDecode = Source->provides( OctetStream ); + if( CanDecode ) + Dest = Source->encodedData( OctetStream ); + + return CanDecode; +} + +#include "kbufferdrag.moc" diff --git a/khexedit/lib/kbufferdrag.h b/khexedit/lib/kbufferdrag.h new file mode 100644 index 0000000..86c498f --- /dev/null +++ b/khexedit/lib/kbufferdrag.h @@ -0,0 +1,76 @@ +/*************************************************************************** + kbufferdrag.h - description + ------------------- + begin : Mon Jul 07 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBUFFERDRAG_H +#define KHE_KBUFFERDRAG_H + +// qt specific +#include +// lib specific +#include "khe.h" +#include "kcoordrange.h" +#include "kcoltextexport.h" + +namespace KHE +{ + +// class KBorderColumn; +class KOffsetColumn; +class KValueColumn; +class KCharColumn; + +typedef KColTextExport* KColTextExportPtr; +/** + *@author Friedrich W. H. Kossebau + */ +class KBufferDrag : public QDragObject +{ + Q_OBJECT + + public: + // TODO: make this call somewhat more generic + KBufferDrag( const QByteArray &, KCoordRange Range, + const KOffsetColumn *OC, const KValueColumn *HC, const KCharColumn *TC, + QChar SC, QChar UC, const QString &CN, + QWidget *Source = 0, const char *Name = 0 ); + ~KBufferDrag(); + + public: // QDragObject API + virtual const char *format( int i ) const; + virtual QByteArray encodedData( const char* ) const; + + public: + virtual void setData( const QByteArray &); + + public: + static bool canDecode( const QMimeSource* Source ); + static bool decode( const QMimeSource* Source, QByteArray &Dest ); + + protected: + QByteArray Data; + KCoordRange CoordRange; + /** collection of all the columns. All columns will be autodeleted. */ + KColTextExportPtr Columns[5]; + uint NoOfCol; + QChar SubstituteChar; + QChar UndefinedChar; + const QString &CodecName; +}; + +} + +#endif diff --git a/khexedit/lib/kbufferlayout.cpp b/khexedit/lib/kbufferlayout.cpp new file mode 100644 index 0000000..a2ea9a0 --- /dev/null +++ b/khexedit/lib/kbufferlayout.cpp @@ -0,0 +1,240 @@ +/*************************************************************************** + kbufferlayout.cpp - description + ------------------- + begin : Thu Jun 12 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#include "kbufferlayout.h" + +using namespace KHE; + + + +KBufferLayout::KBufferLayout( int NoBpL, int SO, int L ) + : NoOfBytesPerLine( NoBpL ), + StartOffset( SO ), + Length( L ) +{ + calcStart(); + calcEnd(); +} + + +KBufferLayout::~KBufferLayout() +{ +} + + +bool KBufferLayout::setStartOffset( int SO ) +{ + // rejecting <0 + if( SO < 0 ) + SO = 0; + + if( StartOffset == SO ) + return false; + + StartOffset = SO; + + calcStart(); + calcEnd(); + return true; +} + + +bool KBufferLayout::setNoOfBytesPerLine( int N ) +{ + // rejecting <1 + if( N < 1 ) + N = 1; + + // no changes? + if( NoOfBytesPerLine == N ) + return false; + + NoOfBytesPerLine = N; + + calcStart(); + calcEnd(); + return true; +} + + +bool KBufferLayout::setLength( int L ) +{ + // rejecting < 0 + if( L < 0 ) + L = 0; + + // no changes? + if( Length == L ) + return false; + + Length = L; + + calcEnd(); + return true; +} + + +void KBufferLayout::setNoOfLinesPerPage( int N ) +{ + NoOfLinesPerPage = N; +} + + +void KBufferLayout::calcStart() +{ + ContentCoords.setStart( KBufferCoord(StartOffset,NoOfBytesPerLine,false) ); +} + + +void KBufferLayout::calcEnd() +{ + ContentCoords.setEnd( (Length>0)?KBufferCoord(Length-1+StartOffset,NoOfBytesPerLine,false): + KBufferCoord(-1,ContentCoords.start().line()) ); +} + + +int KBufferLayout::indexAtCLineStart( int L ) const +{ + return ( L <= ContentCoords.start().line() ) ? 0: + ( L > ContentCoords.end().line() ) ? Length-1: + L * NoOfBytesPerLine - StartOffset; +} + + +int KBufferLayout::indexAtCLineEnd( int L ) const +{ + return ( L < ContentCoords.start().line() ) ? 0: + ( L >= ContentCoords.end().line() ) ? Length-1: + (L+1)*NoOfBytesPerLine-StartOffset-1; +} + + +int KBufferLayout::indexAtCCoord( const KBufferCoord &C ) const +{ + int Index = indexAtCoord( C ); + + return ( Index <= 0 ) ? 0: + ( Index >= Length ) ? Length-1: + Index; +} + + +int KBufferLayout::lineAtCIndex( int Index ) const +{ + return ( Index <= 0 ) ? ContentCoords.start().line(): + ( Index >= Length ) ? ContentCoords.end().line(): + lineAtIndex(Index); +} + + +KBufferCoord KBufferLayout::coordOfCIndex( int Index ) const +{ + return ( Index <= 0 ) ? ContentCoords.start(): + ( Index >= Length ) ? ContentCoords.end(): + coordOfIndex(Index); +} + + +int KBufferLayout::indexAtLineStart( int L ) const +{ + return ( L == ContentCoords.start().line() ) ? 0 : L*NoOfBytesPerLine-StartOffset; +} + + +int KBufferLayout::indexAtLineEnd( int L ) const +{ + return ( L == ContentCoords.end().line() ) ? Length-1 : (L+1)*NoOfBytesPerLine-StartOffset-1; +} + + +int KBufferLayout::indexAtCoord( const KBufferCoord &C ) const +{ + return C.indexByLineWidth( NoOfBytesPerLine ) - StartOffset; +} + +int KBufferLayout::lineAtIndex( int Index ) const +{ + return (Index+StartOffset)/NoOfBytesPerLine; +} + +KBufferCoord KBufferLayout::coordOfIndex( int Index ) const +{ + return KBufferCoord( Index+StartOffset, NoOfBytesPerLine, false ); +} + + + +int KBufferLayout::correctIndex( int I ) const +{ + return ( I <= 0 ) ? 0: + ( I >= Length ) ? Length-1: + I; +} + + +KBufferCoord KBufferLayout::correctCoord( const KBufferCoord &C ) const +{ + return ( C <= ContentCoords.start() ) ? ContentCoords.start(): + ( C >= ContentCoords.end() ) ? ContentCoords.end(): + ( C.pos() >= NoOfBytesPerLine ) ? KBufferCoord( NoOfBytesPerLine-1, C.line() ): + C; +} + + +bool KBufferLayout::atLineStart( const KBufferCoord &C ) const +{ + return ( C.line() == ContentCoords.start().line() ) ? C.pos() == ContentCoords.start().pos(): + C.pos() == 0; +} + +bool KBufferLayout::atLineEnd( const KBufferCoord &C ) const +{ + return ( C.line() == ContentCoords.end().line() ) ? C.pos() == ContentCoords.end().pos(): + C.pos() == NoOfBytesPerLine-1; +} + + +KSection KBufferLayout::positions( int Line ) const +{ + return KSection( firstPos(Line), lastPos(Line) ); +} + + +int KBufferLayout::firstPos( const KBufferCoord &C ) const +{ + return ( ContentCoords.start().isLaterInLineThan(C) ) ? ContentCoords.start().pos() : C.pos(); +} + +int KBufferLayout::lastPos( const KBufferCoord &C ) const +{ + return ( ContentCoords.end().isPriorInLineThan(C) ) ? ContentCoords.end().pos() : C.pos(); +} + +int KBufferLayout::firstPos( int Line ) const +{ + return Line == ContentCoords.start().line() ? ContentCoords.start().pos() : 0; +} + +int KBufferLayout::lastPos( int Line ) const +{ + return ( Line == ContentCoords.end().line() ) ? ContentCoords.end().pos() : NoOfBytesPerLine-1; +} + +bool KBufferLayout::hasContent( int Line ) const +{ + return ContentCoords.includesLine( Line ); +} diff --git a/khexedit/lib/kbufferlayout.h b/khexedit/lib/kbufferlayout.h new file mode 100644 index 0000000..c243225 --- /dev/null +++ b/khexedit/lib/kbufferlayout.h @@ -0,0 +1,196 @@ +/*************************************************************************** + kbufferlayout.h - description + ------------------- + begin : Thu Jun 12 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBUFFERLAYOUT_H +#define KHE_KBUFFERLAYOUT_H + +// lib specific +#include "kcoordrange.h" +#include "ksection.h" + +namespace KHE { + +/**@short the logical layout of a plain buffer view + * + * Given the values for + * * length of the buffer, + * * number of bytes per line, + * * a possible (relative) offset in the display, and + * * the number of lines per page jump + * the following values are calculated: + * * starting line of display, + * * starting position in this line, + * * final line of display, + * * final position in this line, and + * * the total number of lines (is final line +1 or 0) + * + * This layout sees the buffer as a continous stream of byte, + * thus uses each line after the start from the begin to the end. + * + * If the buffer is empty the end coord will be set one pos left to the start coord + * to easen the cursor handling. + * + *@author Friedrich W. H. Kossebau + */ +class KBufferLayout +{ + public: + KBufferLayout( int NoBpL, int SO, int L ); + //KBufferLayout(); + ~KBufferLayout(); + + + public: // given values + /** */ + int startOffset() const; + /** returns number of bytes per line */ + int noOfBytesPerLine() const; + /** returns the length of the displayed data (equals Buffer->size()) */ + int length() const; + /** returns number of lines per visual page */ + int noOfLinesPerPage() const; + + public: // calculated values + int startLine() const; + int startPos() const; + /** returns the coord of the start */ + KBufferCoord start() const; + + int finalLine() const; + int finalPos() const; + /** returns the coord of the end */ + KBufferCoord final() const; + + /** tells how much lines this layout needs (incl. blank leading lines due to StartOffset) */ + int noOfLines() const; + + + public: // value calculation service + /** calculates the index of the coord + * If the coord is before the first coord the first index is returned, + * if the coord is behind the last coord the last index is returned + */ + int indexAtCCoord( const KBufferCoord &C ) const; + /** calculates the index of the first pos in line. + * If the line is below the first line the first index is returned, + * if the line is above the last line the last index is returned + */ + int indexAtCLineStart( int L ) const; + /** calculates the index of last pos in line + * If the line is below the first line the first index is returned, + * if the line is above the last line the last index is returned + */ + int indexAtCLineEnd( int L ) const; + /** calculates the line in which index is found + * If the index is below the first index the first line is returned, + * if the index is above the last index the last line is returned + */ + int lineAtCIndex( int Index ) const; + /** calculates the coord in which index is found + * If the index is below the first index the first coord is returned, + * if the index is above the last index the last coord is returned + */ + KBufferCoord coordOfCIndex( int Index ) const; + + /** calculates the index of coord. if coord is invalid the behaviour is undefinded */ + int indexAtCoord( const KBufferCoord &C ) const; + /** calculates the index of the first pos in line. if line is invalid the behaviour is undefinded */ + int indexAtLineStart( int L ) const; + /** calculates the index of last pos in line. if line is invalid the behaviour is undefinded */ + int indexAtLineEnd( int L ) const; + /** calculates the line in which index is found. if index is invalid the behaviour is undefinded */ + int lineAtIndex( int Index ) const; + /** calculates the coord in which index is found. if index is invalid the behaviour is undefinded */ + KBufferCoord coordOfIndex( int Index ) const; + + /** returns the used positions in line */ + KSection positions( int Line ) const; + /** returns the first Pos in line. if line is invalid the behaviour is undefinded */ + int firstPos( int Line ) const; + /** returns the last Pos in line. if line is invalid the behaviour is undefinded */ + int lastPos( int Line ) const; + /** returns the valid Pos or the first Pos in line. if coord is invalid the behaviour is undefinded */ + int firstPos( const KBufferCoord &C ) const; + /** returns the valid Pos or the last Pos in line. if coord is invalid the behaviour is undefinded */ + int lastPos( const KBufferCoord &C ) const; + /** returns true if the line has content */ + bool hasContent( int Line ) const; + /** returns true if the coord is the first in it's line. if coord is invalid the behaviour is undefinded */ + bool atLineStart( const KBufferCoord &C ) const; + /** returns true if the coord is the last in it's line. if coord is invalid the behaviour is undefinded */ + bool atLineEnd( const KBufferCoord &C ) const; + + /** returns the index if valid or the nearest valid index */ + int correctIndex( int I ) const; + /** returns the coord if valid or the nearest valid coord */ + KBufferCoord correctCoord( const KBufferCoord &C ) const; + + + public: // modification access; return true if changes + /** sets StartOffset, returns true if changed */ + bool setStartOffset( int SO ); + /** sets number of bytes per line, returns true if changed */ + bool setNoOfBytesPerLine( int N ); + /** sets number of lines per page */ + void setNoOfLinesPerPage( int N ); + /** sets length of data to display, returns true if changed */ + bool setLength( int L ); + + + protected: + /** calculates the start coord by startoffset and number of bytes per line */ + void calcStart(); + /** calculates the final coord by startoffset, length, and number of bytes per line */ + void calcEnd(); + + + protected: + /** how many chars per line */ + int NoOfBytesPerLine; + /** starting offset of the displayed data */ + int StartOffset; + /** length of the displayed buffer */ + int Length; + /** number of lines that are moved by page up/down */ + int NoOfLinesPerPage; + + protected: // calculated values, buffered + /** coord in which the start offset is (starting with 0) */ +// KBufferCoord Start; + /** coord in which the last byte is (starting with 0) */ +// KBufferCoord Final; + /** */ + KCoordRange ContentCoords; +}; + + +inline int KBufferLayout::startOffset() const { return StartOffset; } +inline int KBufferLayout::noOfBytesPerLine() const { return NoOfBytesPerLine; } +inline int KBufferLayout::length() const { return Length; } + +inline KBufferCoord KBufferLayout::final() const { return ContentCoords.end(); } +inline KBufferCoord KBufferLayout::start() const { return ContentCoords.start(); } +inline int KBufferLayout::startPos() const { return start().pos(); } +inline int KBufferLayout::finalPos() const { return final().pos(); } +inline int KBufferLayout::startLine() const { return start().line(); } +inline int KBufferLayout::finalLine() const { return final().line(); } +inline int KBufferLayout::noOfLinesPerPage() const { return NoOfLinesPerPage; } +inline int KBufferLayout::noOfLines() const { return Length==0?0:final().line()+1; } + +} + +#endif diff --git a/khexedit/lib/kbufferranges.cpp b/khexedit/lib/kbufferranges.cpp new file mode 100644 index 0000000..57fb9c4 --- /dev/null +++ b/khexedit/lib/kbufferranges.cpp @@ -0,0 +1,307 @@ +/*************************************************************************** + kbufferranges.cpp - description + ------------------- + begin : Sun Jun 22 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +//#include + +// lib specific +#include "kbufferranges.h" + + +using namespace KHE; + +KBufferRanges::KBufferRanges( KBufferLayout *L ) + : Modified( false ), + Layout( L ) +{ +} + + +KBufferRanges::~KBufferRanges() +{ +} + + +void KBufferRanges::reset() +{ + Selection.cancel(); + FirstWordSelection.unset(); + Marking.unset(); + ChangedRanges.clear(); +} + + +void KBufferRanges::setMarking( KSection M ) +{ + if( Marking == M ) + return; + + Marking = M; + addChangedRange( M ); +} + + +void KBufferRanges::removeFurtherSelections() +{ + for( int i = 1; i < noOfSelections(); ++i ) + removeSelection( i ); +} + + +void KBufferRanges::setSelection( KSection S ) +{ + bool Changed = Selection.isValid(); + if( Changed ) + addChangedRange( Selection ); + Selection = S; + addChangedRange( Selection ); +} + +void KBufferRanges::setSelectionStart( int StartIndex ) +{ + bool Changed = Selection.isValid(); + if( Changed ) + addChangedRange( Selection ); + + Selection.setStart( StartIndex ); +} + + +void KBufferRanges::setSelectionEnd( int EndIndex ) +{ + KSection OldSelection = Selection; + Selection.setEnd( EndIndex ); + + // TODO: think about rather building a diff of the sections + if( !OldSelection.isValid() ) + { + addChangedRange( Selection ); + return; + } + if( !Selection.isValid() ) + { + addChangedRange( OldSelection ); + return; + } + + if( OldSelection == Selection ) + return; + int CS_; + int CE_; + // changes at the end? + if( Selection.start() == OldSelection.start() ) + { + CS_ = OldSelection.end()+1; + CE_ = Selection.end(); + if( CE_ < CS_ ) + { + CS_ = Selection.end()+1; + CE_ = OldSelection.end(); + } + } + // changes at the start? + else if( Selection.end() == OldSelection.end() ) + { + CS_ = OldSelection.start(); + CE_ = Selection.start()-1; + if( CE_ < CS_ ) + { + CS_ = Selection.start(); + CE_ = OldSelection.start()-1; + } + } + // change over the anchor + else + { + CS_ = OldSelection.start(); + CE_ = Selection.end(); + if( CE_ < CS_ ) + { + CS_ = Selection.start(); + CE_ = OldSelection.end(); + } + } + KSection C( CS_, CE_ ); + + bool Changed = C.isValid(); + if( Changed ) + addChangedRange( C ); + return; +} + + +void KBufferRanges::removeSelection( int id ) +{ + if( id > 0 ) + return; + + bool Changed = Selection.isValid(); + if( Changed ) + addChangedRange( Selection ); + + Selection.cancel(); + FirstWordSelection.unset(); +} + + +bool KBufferRanges::overlapsSelection( int FirstIndex, int LastIndex, int *SI, int *EI ) const +{ + if( Selection.overlaps(KSection(FirstIndex,LastIndex)) ) + { + *SI = Selection.start(); + *EI = Selection.end(); + return true; + } + return false; +} + + +bool KBufferRanges::overlapsMarking( int FirstIndex, int LastIndex, int *SI, int *EI ) const +{ + if( Marking.overlaps(KSection(FirstIndex,LastIndex)) ) + { + *SI = Marking.start(); + *EI = Marking.end(); + return true; + } + return false; +} + + +const KSection *KBufferRanges::firstOverlappingSelection( KSection Range ) const +{ + if( Selection.overlaps(Range) ) + return &Selection; + + return 0L; +} + + +const KSection *KBufferRanges::overlappingMarking( KSection Range ) const +{ + if( Marking.overlaps(Range) ) + return &Marking; + + return 0L; +} + +/* +bool KBufferRanges::overlapsChanges( int FirstIndex, int LastIndex, int *SI, int *EI ) const +{ + for( KCoordRangeList::const_iterator S=ChangedRanges.begin(); S!=ChangedRanges.end(); ++S ) + { + if( (*S).overlaps(KBuff(FirstIndex,LastIndex)) ) + { + *SI = (*S).start(); + *EI = (*S).end(); + return true; + } + } + + return false; +} + +bool KBufferRanges::overlapsChanges( KSection Indizes, KSection *ChangedRange ) const +{ + for( KSectionList::const_iterator S=ChangedRanges.begin(); S!=ChangedRanges.end(); ++S ) + { + if( (*S).overlaps(Indizes) ) + { + *ChangedRange = *S; + return true; + } + } + + return false; +} +*/ +bool KBufferRanges::overlapsChanges( const KCoordRange &Range, KCoordRange *ChangedRange ) const +{ + // TODO: add a lastusedrange pointer for quicker access + for( KCoordRangeList::const_iterator R=ChangedRanges.begin(); R!=ChangedRanges.end(); ++R ) + { + if( (*R).overlaps(Range) ) + { + *ChangedRange = *R; + return true; + } + } + + return false; +} + + +void KBufferRanges::addChangedRange( int SI, int EI ) +{ + addChangedRange( KSection(SI,EI) ); +} + + +void KBufferRanges::addChangedRange( KSection S ) +{ + addChangedRange( KCoordRange(Layout->coordOfIndex(S.start()),Layout->coordOfIndex(S.end())) ); +} + + +void KBufferRanges::addChangedRange( const KCoordRange &NewRange ) +{ + ChangedRanges.addCoordRange( NewRange ); + + Modified = true; +} + + +void KBufferRanges::removeMarking() +{ + bool Changed = Marking.isValid(); + if( Changed ) + addChangedRange( Marking ); + + Marking.unset(); +} + + +void KBufferRanges::resetChangedRanges() +{ + ChangedRanges.clear(); + Modified = false; +} + + +void KBufferRanges::setFirstWordSelection( KSection Section ) +{ + FirstWordSelection = Section; + setSelection( FirstWordSelection ); +} + + void KBufferRanges::ensureWordSelectionForward( bool Forward ) + { + // in the anchor not on the right side? + if( Selection.isForward() != Forward ) + { + if( Forward ) + { + setSelectionEnd( FirstWordSelection.start() ); + Selection.setForward(); + } + else + { + setSelectionEnd( FirstWordSelection.end()+1 ); + Selection.setBackward(); + } + } + } + diff --git a/khexedit/lib/kbufferranges.h b/khexedit/lib/kbufferranges.h new file mode 100644 index 0000000..ed2cbce --- /dev/null +++ b/khexedit/lib/kbufferranges.h @@ -0,0 +1,130 @@ +/*************************************************************************** + kbufferranges.h - description + ------------------- + begin : Sun Jun 22 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBUFFERRANGES_H +#define KHE_KBUFFERRANGES_H + +// lib specific +#include "kbufferlayout.h" +#include "kselection.h" +#include "ksectionlist.h" +#include "kcoordrangelist.h" + +namespace KHE +{ + +/** a class to control all the ranges like marking and selections + * holds also all modified ranges and merges them so a repaint can take its info from here + * + * @author Friedrich W. H. Kossebau + */ +class KBufferRanges +{ + public: + KBufferRanges( KBufferLayout *L ); + ~KBufferRanges(); + + public: // modifcation access + void setMarking( KSection M ); + void setSelectionStart( int StartIndex ); + void setSelectionEnd( int StartIndex ); + void setSelection( KSection S ); + /** */ + void setFirstWordSelection( KSection S ); + /** */ + void ensureWordSelectionForward( bool Forward ); + + /** removes marking and returns true if something changed */ + void removeMarking(); + /** removes selection with id and returns true if something changed */ + void removeSelection( int id = 0 ); + /** removes all but the standard selection and returns true if something changed */ + void removeFurtherSelections(); + + void addChangedRange( KSection S ); + void addChangedRange( int SI, int EI ); + void addChangedRange( const KCoordRange &NewRange ); + void resetChangedRanges(); + + void setModified( bool M = true ); + /** removes all ranges */ + void reset(); + + public: // value access + int noOfSelections() const; + int selectionStart() const; + int selectionEnd() const; + KSection selection() const; + KSection firstWordSelection() const; + int selectionLength() const; + bool isModified() const; + + public: // calculated logic access + bool hasSelection() const; + bool hasMarking() const; + bool selectionStarted() const; + bool selectionJustStarted() const; + bool hasFirstWordSelection() const; + bool selectionIncludes( int Index ) const; + bool markingIncludes( int Index ) const; + // TODO: next three are deprecated + bool overlapsSelection( int FirstIndex, int LastIndex, int *SI, int *EI ) const; + bool overlapsMarking( int FirstIndex, int LastIndex, int *SI, int *EI ) const; +// bool overlapsChanges( int FirstIndex, int LastIndex, int *SI, int *EI ) const; +// bool overlapsChanges( KSection Indizes, KSection *ChangedRange ) const; + bool overlapsChanges( const KCoordRange &Range, KCoordRange *ChangedRange ) const; + const KSection *firstOverlappingSelection( KSection Range ) const; + const KSection *overlappingMarking( KSection Range ) const; + + + protected: + /** true if something changed */ + bool Modified; + + KSection Marking; + KSelection Selection; + /** memories first selected word on wordwise selection */ + KSection FirstWordSelection; + + KCoordRangeList ChangedRanges; + + KBufferLayout *Layout; +}; + + +inline int KBufferRanges::noOfSelections() const { return 1; } + +inline int KBufferRanges::selectionStart() const { return Selection.start(); } +inline int KBufferRanges::selectionEnd() const { return Selection.end(); } +inline KSection KBufferRanges::selection() const { return Selection; } +inline KSection KBufferRanges::firstWordSelection() const { return FirstWordSelection; } +inline int KBufferRanges::selectionLength() const { return Selection.width(); } +inline bool KBufferRanges::isModified() const { return Modified; } + +inline bool KBufferRanges::hasSelection() const { return Selection.isValid(); } +inline bool KBufferRanges::selectionStarted() const { return Selection.started(); } +inline bool KBufferRanges::selectionJustStarted() const { return Selection.justStarted(); } +inline bool KBufferRanges::hasFirstWordSelection() const { return FirstWordSelection.isValid(); } +inline bool KBufferRanges::hasMarking() const { return Marking.isValid(); } +inline bool KBufferRanges::selectionIncludes( int Index ) const { return Selection.includes( Index ); } +inline bool KBufferRanges::markingIncludes( int Index ) const { return Marking.includes( Index ); } + +inline void KBufferRanges::setModified( bool M ) { Modified = M; } + +} + +#endif diff --git a/khexedit/lib/kbytecodec.h b/khexedit/lib/kbytecodec.h new file mode 100644 index 0000000..fc4e1b3 --- /dev/null +++ b/khexedit/lib/kbytecodec.h @@ -0,0 +1,73 @@ +/*************************************************************************** + kbytecodec.h - description + ------------------- + begin : Sam Mai 17 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBYTECODEC_H +#define KHE_KBYTECODEC_H + +#include "khe.h" +#include + +namespace KHE +{ + +/** class that is able to convert codings to and from + * hexadecimal, decimal, octal, and binary + * + * the buffer will be always filled up to CodingWidth, if not using shortCodingFunction + * a closing '\0' will be always added + * + *@author Friedrich W. H. Kossebau + */ + +class KByteCodec +{ + public: + static KByteCodec *createCodec( KCoding C ); + + + protected: // hiding, as this class should never be instanciated + KByteCodec() {} + + public: // API to be implemented + /** */ + virtual unsigned int encodingWidth() const = 0; + /** */ + virtual unsigned char digitsFilledLimit() const = 0; + + /** encodes the Char and writes the result to */ + virtual void encode( QString &Digits, unsigned int Pos, const unsigned char Char ) const = 0; + /** */ + virtual void encodeShort( QString &Digits, unsigned int Pos, const unsigned char Char ) const = 0; + + /** */ + virtual bool appendDigit( unsigned char *Byte, const unsigned char Digit ) const = 0; + /** */ + virtual void removeLastDigit( unsigned char *Byte ) const = 0; + /** */ + virtual bool isValidDigit( const unsigned char Digit ) const = 0; + /** */ + virtual bool turnToValue( unsigned char *Digit ) const = 0; + + + public: + /** */ + uint decode( unsigned char *Char, const QString &Digits, uint Pos ) const; +}; + +} + +#endif diff --git a/khexedit/lib/kbytesedit.cpp b/khexedit/lib/kbytesedit.cpp new file mode 100644 index 0000000..40b57a1 --- /dev/null +++ b/khexedit/lib/kbytesedit.cpp @@ -0,0 +1,162 @@ +/*************************************************************************** + kbytesedit.cpp - description + ------------------- + begin : Die Jul 9 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "kplainbuffer.h" +#include "kbytesedit.h" +#include "kbufferranges.h" +#include "kbuffercursor.h" + +using namespace KHE; + + +KBytesEdit::KBytesEdit( char *D, int DS_, int RS_, bool KM, QWidget *Parent, const char *Name, WFlags F ) + : KHexEdit( 0L, Parent, Name, F ), + AutoDelete( false ) +{ + setData( D, DS_, RS_, KM ); +} + +KBytesEdit::KBytesEdit( char *D, int DS_, QWidget *Parent, const char *Name, WFlags F ) + : KHexEdit( 0L, Parent, Name, F ), + AutoDelete( false ) +{ + setData( D, DS_ ); +} + + +KBytesEdit::KBytesEdit( QWidget *Parent, const char *Name, WFlags F ) + : KHexEdit( 0L, Parent, Name, F ), + AutoDelete( false ) +{ + setDataBuffer( new KPlainBuffer() ); +} + +KBytesEdit::~KBytesEdit() +{ + clean(); +} + +void KBytesEdit::setReadOnly( bool RO ) +{ + KPlainBuffer *Buffer = dynamic_cast(DataBuffer); + if( Buffer ) + Buffer->setReadOnly( RO ); + KHexEdit::setReadOnly( RO ); +} + + +void KBytesEdit::setAutoDelete( bool AD ) +{ + AutoDelete = AD; +} + + +char *KBytesEdit::data() const +{ + KPlainBuffer *Buffer = dynamic_cast(DataBuffer); + return Buffer ? Buffer->data() : 0L; +} + + +void KBytesEdit::setData( char *D, int S, int RS_, bool KM ) +{ + KPlainBuffer *NewBuffer = new KPlainBuffer( D, S, RS_, KM ); + if( DataBuffer ) + { + // take the settings + NewBuffer->setReadOnly( DataBuffer->isReadOnly() ); + clean(); + } + else + NewBuffer->setReadOnly( isReadOnly() ); + + setDataBuffer( NewBuffer ); +} + + +int KBytesEdit::dataSize() const +{ + KPlainBuffer *Buffer = dynamic_cast(DataBuffer); + return Buffer ? Buffer->size() : -1; +} + + +int KBytesEdit::maxDataSize() const +{ + KPlainBuffer *Buffer = dynamic_cast(DataBuffer); + return Buffer ? Buffer->maxSize() : -1; +} + + +void KBytesEdit::setMaxDataSize( int MS ) +{ + KPlainBuffer *Buffer = dynamic_cast(DataBuffer); + if( Buffer ) + Buffer->setMaxSize( MS ); +} + + +bool KBytesEdit::keepsMemory() const +{ + KPlainBuffer *Buffer = dynamic_cast(DataBuffer); + return Buffer ? Buffer->keepsMemory() : false; +} + + +void KBytesEdit::setKeepsMemory( bool KM ) +{ + KPlainBuffer *Buffer = dynamic_cast(DataBuffer); + if( Buffer ) + Buffer->setKeepsMemory( KM ); +} + + +bool KBytesEdit::isAutoDelete() const { return AutoDelete; } + + +void KBytesEdit::repaintRange( int i1, int i2 ) +{ + bool ChangeCursor = !(CursorPaused) && KSection(i1,i2).includes( BufferCursor->index() ); + if( ChangeCursor ) + pauseCursor(); + + BufferRanges->addChangedRange( i1, i2 ); + + repaintChanged(); + + if( ChangeCursor ) + unpauseCursor(); +} + + +void KBytesEdit::clean() +{ + if( DataBuffer ) + { + if( AutoDelete ) + { + char *D = data(); + if( D ) + delete [] D; + } + delete DataBuffer; + } +} + + +#include "kbytesedit.moc" diff --git a/khexedit/lib/kbytesedit.h b/khexedit/lib/kbytesedit.h new file mode 100644 index 0000000..daf8b6e --- /dev/null +++ b/khexedit/lib/kbytesedit.h @@ -0,0 +1,163 @@ +/*************************************************************************** + kbytesedit.h - description + ------------------- + begin : Die Jul 9 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KBYTESEDIT_H +#define KHE_KBYTESEDIT_H + + +#include "khexedit.h" + +#include + +namespace KHE +{ + +class KDataBuffer; +class KBytesEditPrivate; + +/** the beginner's hex edit widget ;) + * + * It hides the concept of the KDataBuffer and accepts a pure pointer + * to a reasonable large array of bytes + * + * 1. used as viewer + * a) static data ranges -> no changes for data pointer and length + * possible changes are told to the widget by repaintRange + * b) changing data ranges -> data pointer and length might change + * changes told by + * * resetData( char *, int size, bool repaint ); + * * + * 2. used as editor + * a) static data ranges + * data pointer stays the same + * b) changing data ranges + * pointer to the data changes in charge of the widget: + * given pointer and intermediate pointer are possibly invalid + * problem: who cares about the array if the data is deleted? + * -> solved by setAutoDelete() + * + * + *@author Friedrich W. H. Kossebau + */ +//TODO: give the bytes edit widget an empty buffer as default +class KHEXEDIT_EXPORT KBytesEdit : public KHexEdit +{ + Q_OBJECT + //_PROPERTY( char * Data READ data ) + Q_PROPERTY( int DataSize READ dataSize ) + Q_PROPERTY( int MaxDataSize READ maxDataSize WRITE setMaxDataSize ) + Q_PROPERTY( bool AutoDelete READ isAutoDelete WRITE setAutoDelete DESIGNABLE false ) + + + public: + /** creates a new widget to view/edit data + * @param D pointer to memory + * @param S size of used memory + * @param RS_ real size of the memory + * @param KM keep the memory on resize (RS_ is then the maximum size) + * @param Parent parent widget + * @param Name name for this widget + * @param F flags + */ + KBytesEdit( char *D, int DS_, int RS_, bool KM, QWidget *Parent = 0, const char *Name = 0, WFlags F = 0 ); + /** hands over to the editor a new byte array. + * If there exists an old one and autodelete is set the old one gets deleted. + * @param D pointer to memory + * @param S size of used memory + * @param RS_ real size of the memory + * @param KM keep the memory on resize (RS_ is the maximum size) + */ + KBytesEdit( char *D, int DS_, QWidget *Parent = 0, const char *Name = 0, WFlags F = 0 ); + /** hands over to the editor a new byte array. + * If there exists an old one and autodelete is set the old one gets deleted. + * @param D pointer to memory + * @param S size of used memory + * @param RS_ real size of the memory + * @param KM keep the memory on resize (RS_ is the maximum size) + */ + KBytesEdit( QWidget *Parent = 0, const char *Name = 0, WFlags F = 0 ); + virtual ~KBytesEdit(); + + + public: // value access + /** returns the pointer to the actual byte array. This can be but must not be the one + * that was given in the constructor. + */ + char *data() const; + /** returns the size of the actual byte array */ + int dataSize() const; + /** returns the maximal allowed size for the byte array */ + int maxDataSize () const; + /** returns whether autodelete is set for the byte array */ + bool isAutoDelete() const; + /** returns whether the memory of the byte array is kept */ + bool keepsMemory() const; + + public: // logic value service + + public: // modification access + + public slots: + /** hands over to the editor a new byte array. + * If there exists an old one and autodelete is set the old one gets deleted. + * @param D pointer to memory + * @param S size of used memory + * @param RS_ real size of the memory + * @param KM keep the memory on resize (RS_ is the maximum size) + */ + void setData( char *D, int S, int RS_ = -1, bool KM = true ); + + /** sets whether the given array should be handled read only or not */ + virtual void setReadOnly( bool RO = true ); + /** sets the maximal size of the actual byte array. If the actual array is already larger + * it will not be modified but there can be only done non-inserting actions + * until the array's is below the limit + */ + void setMaxDataSize( int MS ); + /** sets whether the array should be deleted on the widget's end or if a new array is set. + * Default is false + */ + void setAutoDelete( bool AD = true ); + /** sets whether the memory given by setData or in the constructor should be kept on resize + */ + void setKeepsMemory( bool KM = true ); + + /** repaint the indizes from i1 to i2 */ + void repaintRange( int i1, int i2 ); + + protected: + /** deletes the databuffer */ + void clean(); + + + protected slots: + + + protected: + /** */ + bool AutoDelete:1; + /** */ + KBytesEditPrivate *d; + + private: // Disabling copy constructor and operator= - not useful + KBytesEdit( const KBytesEdit & ); + KBytesEdit &operator=( const KBytesEdit & ); +}; + +} + +#endif diff --git a/khexedit/lib/kcharcodec.h b/khexedit/lib/kcharcodec.h new file mode 100644 index 0000000..9d1b628 --- /dev/null +++ b/khexedit/lib/kcharcodec.h @@ -0,0 +1,55 @@ +/*************************************************************************** + kcharcodec.h - description + ------------------- + begin : Do Nov 25 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCHARCODEC_H +#define KHE_KCHARCODEC_H + +// qt specific +#include +// lib specific +#include "khe.h" +#include "khechar.h" +#include "khexedit_export.h" + + +namespace KHE +{ + +class KHEXEDIT_EXPORT KCharCodec +{ + public: + /** */ + static KCharCodec* createCodec( KEncoding E ); + /** */ + static KCharCodec* createCodec( const QString &Name ); + + static const QStringList &codecNames(); + + public: // API to be implemented + virtual KHEChar decode( char Byte ) const = 0; + virtual bool encode( char *D, const QChar &C ) const = 0; + virtual const QString& name() const = 0; + + protected: + /** */ + static QStringList CodecNames; +}; + +} + +#endif + diff --git a/khexedit/lib/kcharcoltextexport.cpp b/khexedit/lib/kcharcoltextexport.cpp new file mode 100644 index 0000000..bc4a60e --- /dev/null +++ b/khexedit/lib/kcharcoltextexport.cpp @@ -0,0 +1,71 @@ +/*************************************************************************** + kcharcoltextexport.cpp - description + ------------------- + begin : Wed Sep 03 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "kbufferlayout.h" +#include "kcharcolumn.h" +#include "kcharcodec.h" +#include "kcharcoltextexport.h" + +using namespace KHE; + + +KCharColTextExport::KCharColTextExport( const KCharColumn* TC, const char *D, KCoordRange CR, const QString &CodecName ) + : KBufferColTextExport( TC, D, CR, 1 ), + CharCodec( KCharCodec::createCodec(CodecName) ), + SubstituteChar( TC->substituteChar() ), + UndefinedChar( TC->undefinedChar() ) +{ +} + + +KCharColTextExport::~KCharColTextExport() +{ + delete CharCodec; +} + + +void KCharColTextExport::print( QString &T ) const +{ + int p = 0; + int pEnd = NoOfBytesPerLine; + // correct boundaries + if( PrintLine == CoordRange.start().line() ) + p = CoordRange.start().pos(); + if( PrintLine == CoordRange.end().line() ) + pEnd = CoordRange.end().pos()+1; + + // draw individual chars + uint e = 0; + for( ; pdecode( *PrintData ); + + T.append( B.isUndefined() ? KHEChar(UndefinedChar) : !B.isPrint() ? KHEChar(SubstituteChar) : B ); + e = t + 1; + } + + T.append( whiteSpace(NoOfCharsPerLine-e) ); + + ++PrintLine; +} diff --git a/khexedit/lib/kcharcoltextexport.h b/khexedit/lib/kcharcoltextexport.h new file mode 100644 index 0000000..05a570c --- /dev/null +++ b/khexedit/lib/kcharcoltextexport.h @@ -0,0 +1,50 @@ +/*************************************************************************** + kcharcoltextexport.h - description + ------------------- + begin : Wed Sep 3 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCHARCOLTEXTEXPORT_H +#define KHE_KCHARCOLTEXTEXPORT_H + +// lib specific +#include "khe.h" +#include "kbuffercoltextexport.h" + + +namespace KHE +{ + +class KCharColumn; +class KCharCodec; + + +class KCharColTextExport : public KBufferColTextExport +{ + public: + KCharColTextExport( const KCharColumn* BF, const char *D, KCoordRange CR, const QString &CodecName ); + virtual ~KCharColTextExport(); + + protected: //API + virtual void print( QString &T ) const; + + protected: + KCharCodec *CharCodec; + QChar SubstituteChar; + QChar UndefinedChar; +}; + +} + +#endif diff --git a/khexedit/lib/kcharcolumn.cpp b/khexedit/lib/kcharcolumn.cpp new file mode 100644 index 0000000..9ecbd5a --- /dev/null +++ b/khexedit/lib/kcharcolumn.cpp @@ -0,0 +1,61 @@ +/*************************************************************************** + kcharcolumn.cpp - description + ------------------- + begin : Mit Sep 3 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// c specific +#include +// qt specific +#include +// kde specific +#include +#include +#include +// lib specific +#include "kcolumnsview.h" +#include "kbuffercursor.h" +#include "kbufferlayout.h" +#include "kbufferranges.h" +#include "kcharcolumn.h" + +using namespace KHE; + +static const bool DefaultShowUnprintable = false; +static const QChar DefaultSubstituteChar = (char)'.'; +static const QChar DefaultUndefinedChar = (char)'?'; + + +KCharColumn::KCharColumn( KColumnsView *CV, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R ) + : KBufferColumn( CV, B, L, R ), + ShowUnprintable( DefaultShowUnprintable ), + SubstituteChar( DefaultSubstituteChar ), + UndefinedChar( DefaultUndefinedChar ) +{ + setSpacing( 0, 0, 0 ); +} + + +KCharColumn::~KCharColumn() +{ +} + +void KCharColumn::drawByte( QPainter *P, char /*Byte*/, KHEChar B, const QColor &Color ) const +{ + // make a drawable String out of it + QString BS( B.isUndefined() ? KHEChar(UndefinedChar) : ( !(ShowUnprintable || B.isPrint()) ? KHEChar(SubstituteChar) : B )); + + P->setPen( Color ); + P->drawText( 0, DigitBaseLine, BS ); +} diff --git a/khexedit/lib/kcharcolumn.h b/khexedit/lib/kcharcolumn.h new file mode 100644 index 0000000..1e875b0 --- /dev/null +++ b/khexedit/lib/kcharcolumn.h @@ -0,0 +1,116 @@ +/*************************************************************************** + kcharcolumn.h - description + ------------------- + begin : Mit Sep 3 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCHARCOLUMN_H +#define KHE_KCHARCOLUMN_H + +// qt specific +#include +// lib specific +#include "kbuffercolumn.h" + +class QPainter; +class QColor; + + +namespace KHE +{ + + +/** buffer column that interprets the bytes as chars + * + *@author Friedrich W. H. Kossebau + */ +class KCharColumn : public KBufferColumn +{ + public: + KCharColumn( KColumnsView *CV, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R ); + virtual ~KCharColumn(); + + + public: // modification access + /** sets whether "unprintable" chars (>32) should be displayed in the char column + * with their corresponding character. + * @param SU + * returns true if there was a change + */ + bool setShowUnprintable( bool SU = true ); + /** sets the substitute character for "unprintable" chars + * returns true if there was a change + */ + bool setSubstituteChar( QChar SC ); + /** sets the undefined character for "undefined" chars + * returns true if there was a change + */ + bool setUndefinedChar( QChar UC ); + + + public: // value access + /** returns true if "unprintable" chars (>32) are displayed in the char column + * with their corresponding character, default is false + */ + bool showUnprintable() const; + /** returns the actually used substitute character for "unprintable" chars, default is '.' */ + QChar substituteChar() const; + /** returns the actually used undefined character for "undefined" chars, default is '?' */ + QChar undefinedChar() const; + + + protected: // KBufferColumn API + virtual void drawByte( QPainter *P, char Byte, KHEChar B, const QColor &Color ) const; + + protected: + /** */ + bool ShowUnprintable; + /** */ + QChar SubstituteChar; + /** */ + QChar UndefinedChar; +}; + + +inline bool KCharColumn::showUnprintable() const { return ShowUnprintable; } +inline QChar KCharColumn::substituteChar() const { return SubstituteChar; } +inline QChar KCharColumn::undefinedChar() const { return UndefinedChar; } + +inline bool KCharColumn::setSubstituteChar( QChar SC ) +{ + if( SubstituteChar == SC ) + return false; + SubstituteChar = SC; + return true; +} + +inline bool KCharColumn::setUndefinedChar( QChar UC ) +{ + if( UndefinedChar == UC ) + return false; + UndefinedChar = UC; + return true; +} + +inline bool KCharColumn::setShowUnprintable( bool SU ) +{ + if( ShowUnprintable == SU ) + return false; + ShowUnprintable = SU; + return true; +} + +} + +#endif diff --git a/khexedit/lib/kcoltextexport.h b/khexedit/lib/kcoltextexport.h new file mode 100644 index 0000000..d0b3918 --- /dev/null +++ b/khexedit/lib/kcoltextexport.h @@ -0,0 +1,40 @@ +/*************************************************************************** + kcoltextexport.h - description + ------------------- + begin : Sam Aug 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCOLTEXTEXPORT_H +#define KHE_KCOLTEXTEXPORT_H + +class QString; + +namespace KHE +{ +/** + * interface for the text export of columns + * @author Friedrich W. H. Kossebau + */ +class KColTextExport +{ + public: // API + virtual void printFirstLine( QString &T, int Line ) const = 0; + virtual void printNextLine( QString &T ) const = 0; + /** tells how much chars per line are needed */ + virtual int charsPerLine() const = 0; +}; + +} + +#endif diff --git a/khexedit/lib/kcolumn.cpp b/khexedit/lib/kcolumn.cpp new file mode 100644 index 0000000..f9b0ce5 --- /dev/null +++ b/khexedit/lib/kcolumn.cpp @@ -0,0 +1,60 @@ +/*************************************************************************** + kcolumn.cpp - description + ------------------- + begin : Mit Mai 21 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +// lib specific +#include "kcolumnsview.h" +#include "kcolumn.h" + +using namespace KHE; + + +KColumn::KColumn( KColumnsView *V ) + : View( V ), + Visible( true ), //TODO: would false be better? + LineHeight( V->lineHeight() ), + XSpan( 0,0,true ) +{ + V->addColumn( this ); +} + + +void KColumn::paintFirstLine( QPainter *P, KPixelXs, int /*FirstLine*/ ) +{ + paintBlankLine( P ); +} + + +void KColumn::paintNextLine( QPainter *P ) +{ + paintBlankLine( P ); +} + + +void KColumn::paintBlankLine( QPainter *P ) const +{ + if( LineHeight > 0 ) + P->fillRect( 0,0,width(),LineHeight, View->backgroundBrush() ); +} + + +void KColumn::paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys ) +{ + Xs.restrictTo( XSpan ); + P->fillRect( Xs.start(), Ys.start(), Xs.width(), Ys.width(), View->backgroundBrush() ); +} diff --git a/khexedit/lib/kcolumn.h b/khexedit/lib/kcolumn.h new file mode 100644 index 0000000..37c3118 --- /dev/null +++ b/khexedit/lib/kcolumn.h @@ -0,0 +1,126 @@ +/*************************************************************************** + kcolumn.h - description + ------------------- + begin : Mit Mai 21 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCOLUMN_H +#define KHE_KCOLUMN_H + + +// lib specific +#include "kadds.h" +#include "ksection.h" + +class QPainter; + +namespace KHE +{ + +class KColumnsView; + +/** base class for columns of the KColumnsView + * + * + *@author Friedrich W. H. Kossebau + */ + +class KColumn +{ +// friend class KColumnsView; + public: + KColumn( KColumnsView *V ); + virtual ~KColumn() {} + + + public: // API to be reimplemented in the subclasses + /** Before an update of the columns view each column that intersects with the area to be painted + * will be called with this function. As often multiple lines of a column are affected + * for each lines the same values (like first and last char positions) might be calculated. + * This function enables a one-time-calculation for such data that must be stored in some + * class members, though. + * @param P painter variable + * @param cx + * @param cw + * @param FirstLine no of the first of the range of lines to paint + */ + virtual void paintFirstLine( QPainter *P, KPixelXs Xs, int FirstLine ); + /** the actual painting call for a column's line. + * The default implementation simply paints the background + */ + virtual void paintNextLine( QPainter *P ); + + /** */ + virtual void paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys ); + + public: // modification access + /** sets starting point of the column */ + void setX( KPixelX NewX ); + /** sets visibily */ + void setVisible( bool V ); + /** buffer actual line height in column */ + void setLineHeight( KPixelY H ); + + public: // value access + /** left offset x in pixel */ + KPixelX x() const; + /** total width in pixel */ + KPixelX width() const; + /** right offset x in pixel */ + KPixelX rightX() const; + /** should Column be displayed? */ + bool isVisible() const; + /** convinience: returns width if visible else 0 */ + KPixelX visibleWidth() const; + + public: // functional logic + /** true if column overlaps with pixels between x-positions x1, x2 */ + bool overlaps( KPixelXs Xs ) const; + + protected: + /** sets width of the column */ + void setWidth( KPixelX W ); + /** */ + void paintBlankLine( QPainter *P ) const; + + protected: // general column data + /** pointer to the view */ + KColumnsView *View; + /** should Column be displayed? */ + bool Visible; + + /** buffered value */ + KPixelY LineHeight; + + /** left offset x in pixel */ + KPixelXs XSpan; +}; + + +inline KPixelX KColumn::x() const { return XSpan.start(); } +inline KPixelX KColumn::rightX() const { return XSpan.end(); } +inline KPixelX KColumn::width() const { return XSpan.width(); } +inline bool KColumn::isVisible() const { return Visible; } +inline KPixelX KColumn::visibleWidth() const { return Visible ? XSpan.width(): 0; } + +inline void KColumn::setX( KPixelX NewX ) { XSpan.moveToStart( NewX ); } +inline void KColumn::setWidth( KPixelX W ) { XSpan.setEndByWidth( W ); } +inline void KColumn::setVisible( bool V ) { Visible = V; } +inline void KColumn::setLineHeight( KPixelY H ) { LineHeight = H; } + +inline bool KColumn::overlaps( KPixelXs Xs ) const { return XSpan.overlaps(Xs); } + +} + +#endif diff --git a/khexedit/lib/kcolumnsview.cpp b/khexedit/lib/kcolumnsview.cpp new file mode 100644 index 0000000..1c93af8 --- /dev/null +++ b/khexedit/lib/kcolumnsview.cpp @@ -0,0 +1,236 @@ +/*************************************************************************** + kcolumnsview.cpp - description + ------------------- + begin : Mit Mai 21 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +//#include + +// qt specific +#include +// lib specific +#include "kcolumn.h" +#include "kcolumnsview.h" + + +using namespace KHE; + +static bool DefaultHorizontalGrid = false; + +KColumnsView::KColumnsView( /*bool R,*/ QWidget *Parent, const char *Name, WFlags Flags ) + : QScrollView( Parent, Name, Flags | WRepaintNoErase /*| WStaticContents*/ ), + NoOfLines( 0 ), + LineHeight( 0 ), + TotalWidth( 0 ), + HorizontalGrid( DefaultHorizontalGrid ), +// Reversed( R ), + d( 0 ) +{ + viewport()->setBackgroundMode( PaletteBase ); + setBackgroundMode( PaletteBackground, PaletteBase ); + viewport()->setFocusProxy( this ); + + Columns.setAutoDelete( true ); +} + +KColumnsView::~KColumnsView() +{ +} + + +void KColumnsView::setNoOfLines( int NewNoOfLines ) +{ + NoOfLines = NewNoOfLines; +} + + +void KColumnsView::setLineHeight( KPixelY LH ) +{ + LineHeight = LH; + for( KColumn *C=Columns.first(); C; C=Columns.next() ) + C->setLineHeight( LineHeight ); + verticalScrollBar()->setLineStep( LineHeight ); + + updateLineBufferSize(); +} + + +void KColumnsView::updateWidths() +{ + TotalWidth = 0; + for( KColumn *C=Columns.first(); C; C=Columns.next() ) + { + C->setX( TotalWidth ); + TotalWidth += C->visibleWidth(); + } + + updateLineBufferSize(); +} + + +void KColumnsView::updateLineBufferSize() +{ + int w = totalWidth(); + int h = LineHeight; + + if( w != LineBuffer.width() || h != LineBuffer.height() ) + LineBuffer.resize( w, h ); +} + + +int KColumnsView::noOfLinesPerPage() const +{ + if( !viewport() || LineHeight == 0 ) + return 1; +// int NoOfLinesPerPage = (visibleHeight()-1) / LineHeight; // -1 ensures to get always the last visible line + int NoOfLinesPerPage = (viewport()->height()-1) / LineHeight; // -1 ensures to get always the last visible line + + if( NoOfLinesPerPage == 0 ) + // ensure to move down at least one line + NoOfLinesPerPage = 1; + return NoOfLinesPerPage; +} + + +void KColumnsView::addColumn( KColumn *C ) +{ +// if( Reversed ) +// Columns.prepend( C ); +// else + Columns.append( C ); + + updateWidths(); +} + + +void KColumnsView::removeColumn( KColumn *C ) +{ + Columns.remove( C ); + + updateWidths(); +} + + +void KColumnsView::updateView() +{ + resizeContents( totalWidth(), totalHeight() ); + updateContents(); +} + + +void KColumnsView::repaintView() +{ + resizeContents( totalWidth(), totalHeight() ); + repaintContents( false ); +} + + +void KColumnsView::paintEmptyArea( QPainter *P, int cx ,int cy, int cw, int ch) +{ + P->fillRect( cx, cy, cw, ch, backgroundBrush() ); +} + + +void KColumnsView::drawContents( QPainter *P, int cx, int cy, int cw, int ch ) +{ + //kdDebug(1501) << "drawContents(" << cx<<","< RedrawColumns; + for( KColumn *C=Columns.first(); C; C=Columns.next() ) + if( C->isVisible() && C->overlaps(AffectedXs) ) + RedrawColumns.append( C ); + + // any lines to be drawn? + if( NoOfLines > 0 ) + { + // calculate affected lines + KSection AffectedLines = visibleLines( AffectedYs ); + AffectedLines.restrictEndTo( NoOfLines - 1 ); + + if( AffectedLines.isValid() ) + { + QPainter Paint; + Paint.begin( &LineBuffer, this ); + + // starting painting with the first line + KColumn *C = RedrawColumns.first(); + Paint.translate( C->x(), 0 ); + + for( ; C; C=RedrawColumns.next() ) + { + C->paintFirstLine( &Paint, AffectedXs, AffectedLines.start() ); + Paint.translate( C->width(), 0 ); + } + + // Go through the other lines + KPixelY y = AffectedLines.start() * LineHeight; + int l = AffectedLines.start(); + while( true ) + { + Paint.end(); + P->drawPixmap( cx, y, LineBuffer, cx, 0, cw, LineHeight ); // bitBlt directly impossible: lack of real coord + + // copy to screen +// bitBlt( viewport(), cx - contentsX(), y - contentsY(), +// &LineBuffer, cx, 0, cw, LineHeight ); + + ++l; + y += LineHeight; + + if( l > AffectedLines.end() ) + break; + + // to avoid flickers we first paint to the linebuffer + Paint.begin( &LineBuffer, this ); + + KColumn *C = RedrawColumns.first(); + Paint.translate( C->x(), 0 ); + + for( ; C; C=RedrawColumns.next() ) + { + C->paintNextLine( &Paint ); + Paint.translate( C->width(), 0 ); + } + + if( HorizontalGrid && cx < TotalWidth ) + Paint.drawLine( cx, LineHeight-1, TotalWidth-1, LineHeight-1 ); // TODO: use a additional TotalHeight? + } + } + } + + // draw empty columns? + AffectedYs.setStart( totalHeight() ); + if( AffectedYs.isValid() ) + { + for( KColumn *C = RedrawColumns.first(); C; C=RedrawColumns.next() ) + C->paintEmptyColumn( P, AffectedXs, AffectedYs ); + } + } + + // Paint empty rects + AffectedXs.setStart( TotalWidth ); + if( AffectedXs.isValid() ) + paintEmptyArea( P, AffectedXs.start(), cy, AffectedXs.width(), ch ); +} + +// Implemented to get rid of a compiler warning +void KColumnsView::drawContents( QPainter * ) {} + +#include "kcolumnsview.moc" diff --git a/khexedit/lib/kcolumnsview.h b/khexedit/lib/kcolumnsview.h new file mode 100644 index 0000000..aa3521d --- /dev/null +++ b/khexedit/lib/kcolumnsview.h @@ -0,0 +1,168 @@ +/*************************************************************************** + kcolumnsview.h - description + ------------------- + begin : Mit Mai 21 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCOLUMNSVIEW_H +#define KHE_KCOLUMNSVIEW_H + +// qt specific +#include +#include +#include +#include +// lib specific +#include "kadds.h" +#include "ksection.h" // TODO: think about moving this out of the public API + +namespace KHE +{ + +class KColumn; +class KColumnsViewPrivate; + +/** general class for widgets with columns that display different aspects of the same data + * with the same lineheight for all lines + * + *@author Friedrich W. H. Kossebau + */ + +class KColumnsView : public QScrollView +{ + Q_OBJECT + + friend class KColumn; + + public: + KColumnsView( /*bool R = false,*/ QWidget *parent=0, const char *name=0, WFlags Flags=0 ); + virtual ~KColumnsView(); + + public: // drawing + virtual void paintEmptyArea( QPainter *p, int cx, int cy, int cw, int ch ); + virtual void drawContents( QPainter *p, int cx, int cy, int cw, int ch ); + + public: // data-wise sizes + /** returns the number of all lines */ + int noOfLines() const; + /** returns number of fully visible lines, at least 1 (as needed by page down/up) + * doesn't care about the total height being smaller than the display height + */ + int noOfLinesPerPage() const; + + public: // pixel-wise sizes + /** returns the height of each line */ + KPixelY lineHeight() const; + /** returns the size of all visible columns together */ + QSize totalViewSize() const; + /** returns the width of all visible columns together */ + KPixelX totalWidth() const; + /** returns the height of all lines together */ + KPixelY totalHeight() const; + + public: // services + /** gives the index of the line that would include y in pixel coord. + * y is not forced to be inside the total height. + */ + uint lineAt( KPixelY y ) const; + /** gives the index of the first and the last line that would be visible + * these lines might not contain anything + */ + KSection visibleLines() const; + /** gives the index of the first and the last line that would be visible in the given pixel range + * these lines might not contain anything + */ + KSection visibleLines( KPixelYs YPixels ) const; + + + protected: + /** called by KColumn */ + void addColumn( KColumn *C ); + void removeColumn( KColumn *C ); + + + protected: // + /** sets height of all lines and propagates this information to all columns + * doesn't update the content size + * @param NewLineHeight height in pixels + */ + virtual void setLineHeight( KPixelY NewLineHeight ); + /** sets the number of lines + * doesn't update the content size + * @param NewNoOfLines new number of lines to display + */ + virtual void setNoOfLines( int NewNoOfLines ); + + protected: // recalculations + /** recalculates the positions of the columns and the total width */ + void updateWidths(); + /** ensures that the line buffer has the size of the whole line */ + void updateLineBufferSize(); + + protected: // painting + void updateView(); + void repaintView(); + + private: + /** hiding it*/ + void drawContents( QPainter* ); + + + protected: // calculated + /** collection of all the columns. All columns will be autodeleted. */ + QPtrList Columns; + /** the number of lines which the column view has */ + int NoOfLines; + /** the height of each line in pixels */ + KPixelY LineHeight; + /** the width of all visible columns together */ + KPixelX TotalWidth; +// /** width that is used by columns that are not resizeable (if shown) */ +// KPixelX ReservedWidth; + + protected: + // TODO: do we really want this? + bool HorizontalGrid; + /** Buffer where each line is drawn to before it is copied onto the screen */ + QPixmap LineBuffer; +// bool Reversed; + + private: + KColumnsViewPrivate *d; +}; + + +inline int KColumnsView::noOfLines() const { return NoOfLines; } +inline KPixelY KColumnsView::lineHeight() const { return LineHeight; } +inline uint KColumnsView::lineAt( KPixelY y ) const { return LineHeight!=0 ? y / LineHeight : 0; } +inline KSection KColumnsView::visibleLines() const +{ + KPixelY cy = contentsY(); + KPixelY ch = visibleHeight(); + return KSection( lineAt(cy), lineAt(cy+ch-1) ); +} + +inline KSection KColumnsView::visibleLines( KPixelYs YPixels ) const +{ + return KSection( lineAt(YPixels.start()), lineAt(YPixels.end()) ); +} + +inline KPixelY KColumnsView::totalHeight() const { return NoOfLines*LineHeight; } +inline KPixelX KColumnsView::totalWidth() const { return TotalWidth; } + +inline QSize KColumnsView::totalViewSize() const { return QSize( totalWidth(), totalHeight() ); } + +} + +#endif diff --git a/khexedit/lib/kcoordrange.h b/khexedit/lib/kcoordrange.h new file mode 100644 index 0000000..0d5b186 --- /dev/null +++ b/khexedit/lib/kcoordrange.h @@ -0,0 +1,95 @@ +/*************************************************************************** + kcoordrange.h - description + ------------------- + begin : Sun 03.08.2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de +****************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCOORDRANGE_H +#define KHE_KCOORDRANGE_H + +// lib specific +#include "krange.h" +#include "kbuffercoord.h" +#include "ksection.h" + +namespace KHE +{ + +template<> +inline const KBufferCoord KRange::null() const { return KBufferCoord(-1,-1);} + +typedef KRange KBasicCoordRange; + +/** describes a range in the buffercoord + *@author Friedrich W. H. Kossebau + */ +class KCoordRange : public KRange +{ + public: + /** + * @param SC start coord + * @param EC end coord + */ + KCoordRange( KBufferCoord SC, KBufferCoord EC ); + /** + * @param Pos start and end pos + * @param Lines start and end line + */ + KCoordRange( KSection Pos, KSection Lines ); + KCoordRange(); + ~KCoordRange(); + + public: + KCoordRange &operator=( const KCoordRange &S ); + + public: + bool operator==( const KCoordRange &S ) const; + + public: + /** calculates the number of coords that are covered if a line has the given length. + * If the range is invalid the behaviour is undefined. + * @param LineLength + * @return the number of points covered if a line has a length of LineLength. + */ + int width( int LineLength ) const; + /** calculates the number of lines that are covered by the range. + * If the range is invalid the behaviour is undefined. + * @return number of lines covered + */ + int lines() const; + /** tests if the given line is included by the range. + * If the range is invalid or the line < 0 the behaviour is undefined. + * @param Line index of line + * @return @c true if Line is included, otherwise @c false + */ + bool includesLine( int Line ) const; +}; + + +inline KCoordRange::KCoordRange( KBufferCoord SC, KBufferCoord EC ) : KBasicCoordRange(SC,EC) {} +inline KCoordRange::KCoordRange( KSection Pos, KSection Lines ) + : KBasicCoordRange( KBufferCoord(Pos.start(),Lines.start()), KBufferCoord(Pos.end(),Lines.end()) ) {} +inline KCoordRange::KCoordRange() {} +inline KCoordRange::~KCoordRange() {} + +inline bool KCoordRange::operator==( const KCoordRange &R ) const { return KBasicCoordRange::operator==(R); } + +inline KCoordRange &KCoordRange::operator=( const KCoordRange &R ) { KBasicCoordRange::operator=(R); return *this; } + +inline int KCoordRange::width( int LineLength ) const { return LineLength*(lines()-1) + End.pos() - Start.pos()+1; } +inline int KCoordRange::lines() const { return End.line() - Start.line() + 1; } +inline bool KCoordRange::includesLine( int Line ) const { return Line >= Start.line() && Line <= End.line(); } +} + +#endif diff --git a/khexedit/lib/kcoordrangelist.cpp b/khexedit/lib/kcoordrangelist.cpp new file mode 100644 index 0000000..3028c7d --- /dev/null +++ b/khexedit/lib/kcoordrangelist.cpp @@ -0,0 +1,78 @@ +/*************************************************************************** + kcoordrangelist.cpp - description + ------------------- + begin : Mon Jun 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "kcoordrangelist.h" + +using namespace KHE; + +KCoordRangeList::KCoordRangeList() +{ +} + + +KCoordRangeList::~KCoordRangeList() +{ +} + + +void KCoordRangeList::addCoordRange( KCoordRange NewCoordRange ) +{ + if( !NewCoordRange.isValid() ) + return; + // we try to insert it by ascending indizes + // if sections are overlapping we combine them + iterator S = begin(); + for( ; S!=end(); ++S ) + { + // is next CoordRange behind the new CoordRange? + if( NewCoordRange.endsBefore(*S) ) + { + // put the new before it + insert( S, NewCoordRange ); + return; + } + + // does the next CoordRange overlap? + if( (*S).overlaps(NewCoordRange) ) + { + // Start of the combined sections is the smaller one + NewCoordRange.extendStartTo( (*S).start() ); + // next we search all the overlapping sections and keep the highest end index + KBufferCoord End((*S).end()); + iterator LS = S; + for( ++LS; LS!=end(); ++LS ) + { + if( !(*LS).overlaps(NewCoordRange) ) + break; + End = (*LS).end(); + } + // the higher end is the end of the combined CoordRange + NewCoordRange.extendEndTo( End ); + // remove all overlapping sections + S = erase( S, LS ); + // and instead insert the combined one + insert( S, NewCoordRange ); + return; + } + } + + // all others are before the new? + if( S == end() ) + // add it at the end + append( NewCoordRange ); +} diff --git a/khexedit/lib/kcoordrangelist.h b/khexedit/lib/kcoordrangelist.h new file mode 100644 index 0000000..187ec7f --- /dev/null +++ b/khexedit/lib/kcoordrangelist.h @@ -0,0 +1,44 @@ +/*************************************************************************** + kcoordrangelist.h - description + ------------------- + begin : Wed Aug 13 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCOORDRANGELIST_H +#define KHE_KCOORDRANGELIST_H + +// qt specific +#include +// lib specific +#include "kcoordrange.h" + +namespace KHE { + +typedef QValueList KCoordRangeBasicList; +/** +@author Friedrich W. H. Kossebau +*/ +class KCoordRangeList : public KCoordRangeBasicList +{ + public: + KCoordRangeList(); + ~KCoordRangeList(); + + public: + void addCoordRange( KCoordRange S ); +}; + +} + +#endif diff --git a/khexedit/lib/kcursor.cpp b/khexedit/lib/kcursor.cpp new file mode 100644 index 0000000..3150751 --- /dev/null +++ b/khexedit/lib/kcursor.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** + kcursor.cpp - description + ------------------- + begin : Mit Jun 26 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#include "kcursor.h" + +using namespace KHE; + +KCursor::KCursor() +: CursorX( 0 ), + CursorW( -1 ) +{ +} + + +KCursor::~KCursor() +{ +} + + + +void KCursor::setSize( KPixelX Width, KPixelY Height ) +{ + if( Width != OnPixmap.width() || Height != OnPixmap.height() ) + { + OnPixmap.resize( Width, Height ); + OffPixmap.resize( Width, Height ); + } +} + + +void KCursor::setShape( KPixelX X, KPixelX W ) +{ + CursorX = X; + CursorW = W; +} diff --git a/khexedit/lib/kcursor.h b/khexedit/lib/kcursor.h new file mode 100644 index 0000000..428c7ed --- /dev/null +++ b/khexedit/lib/kcursor.h @@ -0,0 +1,68 @@ +/*************************************************************************** + kbuffercolumn.h - description + ------------------- + begin : Mit Jun 26 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KCURSOR_H +#define KHE_KCURSOR_H + + +#include + +#include "kadds.h" + +namespace KHE +{ + +/** + *@author Friedrich W. H. Kossebau + */ +class KCursor +{ + public: + KCursor(); + virtual ~KCursor(); + + public: + /** sets size of the full cursor */ + void setSize( KPixelX Width, KPixelY Height ); + /** sets the shape of the cursor to be drawn */ + void setShape( KPixelX X, KPixelX W ); + + public: // access + const QPixmap &onPixmap() const; + const QPixmap &offPixmap() const; + KPixelX cursorX() const; + KPixelX cursorW() const; + + + protected: + QPixmap OnPixmap; + QPixmap OffPixmap; + + KPixelX CursorX; + KPixelX CursorW; +}; + + +inline const QPixmap &KCursor::onPixmap() const { return OnPixmap; } +inline const QPixmap &KCursor::offPixmap() const { return OffPixmap; } + +inline KPixelX KCursor::cursorX() const { return CursorX; } +inline KPixelX KCursor::cursorW() const { return CursorW; } + +} + +#endif diff --git a/khexedit/lib/kdatabuffer.cpp b/khexedit/lib/kdatabuffer.cpp new file mode 100644 index 0000000..054d792 --- /dev/null +++ b/khexedit/lib/kdatabuffer.cpp @@ -0,0 +1,51 @@ +/*************************************************************************** + kdatabuffer.cpp - description + ------------------- + begin : Fri Aug 01 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// c specific +#include +// lib specific +#include "kdatabuffer.h" + +using namespace KHE; + + +int KDataBuffer::insert( int Pos, const char* D, int Length ) +{ + return replace( Pos,0,D,Length ); +} + + +int KDataBuffer::remove( KSection Remove ) +{ + replace( Remove, 0, 0 ); + return Remove.width(); // TODO: check if this is true +} + +int KDataBuffer::copyTo( char* Dest, int Pos, int Length ) const +{ + return copyTo( Dest, KSection(Pos,Length,false) ); +} + + + +int KDataBuffer::copyTo( char* Dest, KSection Source ) const +{ + Source.restrictEndTo( size()-1 ); + for( int i=Source.start(); i<=Source.end(); ++i ) + *Dest++ = datum( i ); + return Source.width(); +} diff --git a/khexedit/lib/kdatabuffer.h b/khexedit/lib/kdatabuffer.h new file mode 100644 index 0000000..e9733d8 --- /dev/null +++ b/khexedit/lib/kdatabuffer.h @@ -0,0 +1,246 @@ +/*************************************************************************** + kdatabuffer.h - description + ------------------- + begin : Mit Mai 14 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KDATABUFFER_H +#define KHE_KDATABUFFER_H + + +// lib specific +#include "ksection.h" +#include "khexedit_export.h" + +namespace KHE +{ + +/** could it be useful to hide the data access behind an iterator? * +class KDataBufferIterator +{ + public: + bool hasNext(); + char next(); + protected: + + protected: + char * + int Length; +} + +bool KDataBufferIterator::hasNext() +{ +} +// this function should be simple as possible +char KDataBufferIterator::next() +{ + // if next span is empty + if( ) + return *NextChar++; +} +*/ +/** base class for all Data buffers that are used to display + * TODO: think about a way to inform KHexEdit that there has been + * a change in the buffer outside. what kind of changes are possible? + * + * Operations on the data: + * + * Finding: is implemented stateless. FindNext has to be done by perhaps a FindManager + * Replacing: not available. Implement within a ReplaceManager + * + *@author Friedrich W. H. Kossebau + */ + +class KHEXEDIT_EXPORT KDataBuffer +{ + friend class KDataBufferIterator; + + + protected: + KDataBuffer(); + public: + virtual ~KDataBuffer(); + + + public: // data access API + /** locates working range + * The idea behind is to tell buffer which range will be requested in the following time, + * so that e.g. the corresponding pages will be loaded in advance + * TODO: do we really need this? Where will this lead to real enhancements? + * @param Range + * @return @c true if successfull, @c false otherwise + */ + virtual bool prepareRange( KSection Range ) const = 0; + /** convenience function, same as above */ + bool prepareRange( int Offset, int Length ) const; + + /** creates an iterator to */ + //virtual KDataBufferIterator *iterator() const = 0; + /** expects pointer to memory, should be in prepared range + * it is only expected to be a valid pointer until any further call + * to this or any modifying function + * @param Section + * @return pointer to + */ + virtual const char *dataSet( KSection Section ) const = 0; + /** convenience function, same as above */ + const char *dataSet( int Offset, int Length ) const; + + /** requests a single byte + * if the offset is not valid the behaviout is undefined + * @param Offset offset of the datum requested + */ + virtual char datum( unsigned int Offset ) const = 0; + + /** + * @return the size of the data + */ + virtual int size() const = 0; + + + public: // state read API + /** + * @return @c true if the buffer can only be read, @c false if writing is allowed + */ + virtual bool isReadOnly() const; + /** + * @return @c true if the buffer has been modified, @c false otherwise + */ + virtual bool isModified() const = 0; + + + public: // modification API + /** inserts bytes copied from the given source at Position. + * The original data beginnung at the position is moved + * with the buffer enlarged as needed + * If the buffer is readOnly this is a noop and returns 0. + * @param Pos + * @param Source data source + * @param SourceLength number of bytes to copy + * @return length of inserted data + */ + virtual int insert( int Pos, const char* Source, int SourceLength ); + + /** removes beginning with position as much as possible + * @param Section + * @return length of removed data + */ + virtual int remove( KSection Section ); + /** convenience function, behaves as above */ + int remove( int Pos, int Length ); + + /** replaces as much as possible + * @param DestSection + * @param Source + * @param SourceLength + * @return length of replacced data + */ + virtual unsigned int replace( KSection DestSection, const char* Source, unsigned int SourceLength ) = 0; + /** convenience function, behaves as above */ + unsigned int replace( unsigned int Pos, unsigned int RemoveLength, + const char* Source, unsigned int SourceLength ); + + /** moves a part of the data to a new position, while floating the other data around + * when moving to a higher place the length of the block must be taken into account + * if the new positions extend beyond the buffers end the section is moved to the end. + * @param DesPos position of the data where the section should be moved behind + * @param SourceSection data section to be moved + * @return new pos of moved data or old, if failed + */ + virtual int move( int DestPos, KSection SourceSection ) = 0; + + /** + * fills the buffer with the FillChar. If the buffer is to small it will be extended as much as possible. + * @param FillChar char to use + * @param Length number of chars to fill. If Length is -1, the current buffer length is used. + * @param Pos position where the filling starts + * @return number of filled characters + */ + virtual int fill( const char FillChar, int Length = -1, unsigned int Pos = 0 ) = 0; + + /** sets a single byte + * if the offset is not valid the behaviour is undefined + * @param Offset offset of the datum requested + * @param Char new byte value + */ + virtual void setDatum( unsigned int Offset, const char Char ) = 0; + + /** sets the modified flag for the buffer + * @param M + */ + virtual void setModified( bool M ) = 0; + + + public: // service functions + /** copies the data of the section into a given array Dest. If the section extends the buffers range + * the section is limited to the buffer's end. If the section is invalid the behaviour is undefined. + * @param Dest pointer to a char array large enough to hold the copied section + * @param Source + * @return number of copied bytes + */ + virtual int copyTo( char* Dest, KSection Source ) const; + /** convenience function, behaves as above */ + int copyTo( char* Dest, int Pos, int n ) const; + + + public: // finding API + /** searches beginning with byte at Pos. + * @param + * @param Length length of search string + * @param Pos the position to start the search + * @return index of the first or -1 + */ + //virtual int find( const char*, int Length, int Pos = 0 ) const = 0; + /** searches for a given data string + * The section limits the data within which the key has to be found + * If the end of the section is lower then the start the search continues at the start??? + * @param + * @param Length length of search string + * @param Section section within the keydata is to be found + * @return index of the first occurence or -1 + */ + virtual int find( const char*KeyData, int Length, KSection Section ) const = 0; + /** searches backward beginning with byte at Pos. + * @param + * @param Length length of search string + * @param Pos the position to start the search. If -1 the search starts at the end. + * @return index of the first or -1 + */ + virtual int rfind( const char*, int Length, int Pos = -1 ) const = 0; + +/* virtual int find( const QString &expr, bool cs, bool wo, bool forward = true, int *index = 0 ); */ +}; + + +inline KDataBuffer::KDataBuffer() {} +inline KDataBuffer::~KDataBuffer() {} + +inline bool KDataBuffer::prepareRange( int Offset, int Length ) const +{ return prepareRange( KSection(Offset,Offset+Length-1) ); } + +inline const char *KDataBuffer::dataSet( int Offset, int Length ) const +{ return dataSet( KSection(Offset,Offset+Length-1) ); } + +inline int KDataBuffer::remove( int Pos, int Length ) +{ return remove( KSection(Pos,Pos+Length-1) ); } + +inline unsigned int KDataBuffer::replace( unsigned int Pos, unsigned int RemoveLength, + const char* D, unsigned int InputLength ) +{ return replace( KSection(Pos,Pos+RemoveLength-1), D, InputLength ); } + +inline bool KDataBuffer::isReadOnly() const { return false; } + +} + +#endif diff --git a/khexedit/lib/kfixedsizebuffer.cpp b/khexedit/lib/kfixedsizebuffer.cpp new file mode 100644 index 0000000..2945620 --- /dev/null +++ b/khexedit/lib/kfixedsizebuffer.cpp @@ -0,0 +1,272 @@ +/*************************************************************************** + kfixedsizebuffer.cpp - description + ------------------- + begin : Mit Jun 03 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + +//#include +// c specific +#include +// lib specific +#include "kfixedsizebuffer.h" + +using namespace KHE; + +KFixedSizeBuffer::KFixedSizeBuffer( char *D, unsigned int S, char FUC ) + : Data( D ), + Size( S ), + FillUpChar( FUC ), + ReadOnly( true ), + Modified( false ), + AutoDelete( false ) +{ +} + +KFixedSizeBuffer::KFixedSizeBuffer( unsigned int S, char FUC ) + : Data( new char[S] ), + Size( S ), + FillUpChar( FUC ), + ReadOnly( false ), + Modified( false ), + AutoDelete( true ) +{ + reset( 0, S ); +} + +KFixedSizeBuffer::~KFixedSizeBuffer() +{ + if( AutoDelete ) + delete [] Data; +} + + + +int KFixedSizeBuffer::insert( int Pos, const char* D, int InputLength ) +{ + // check all parameters + if( Pos >= (int)Size || InputLength == 0 ) + return 0; + if( Pos + InputLength > (int)Size ) + InputLength = Size - Pos; + + unsigned int BehindInsertPos = Pos + InputLength; + // fmove right data behind the input range + memmove( &Data[BehindInsertPos], &Data[Pos], Size-BehindInsertPos ); + // insert input + memcpy( &Data[Pos], D, InputLength ); + + Modified = true; + return InputLength; +} + + +int KFixedSizeBuffer::remove( KSection Remove ) +{ + if( Remove.start() >= (int)Size || Remove.width() == 0 ) + return 0; + + Remove.restrictEndTo( Size-1 ); + + int RemoveLength = Remove.width(); + int BehindRemovePos = Remove.end()+1;; + // fmove right data behind the input range + memmove( &Data[Remove.start()], &Data[BehindRemovePos], Size-BehindRemovePos ); + // clear freed space + reset( Size-RemoveLength, RemoveLength ); + + Modified = true; + return RemoveLength; +} + + +unsigned int KFixedSizeBuffer::replace( KSection Remove, const char* D, unsigned int InputLength ) +{ + // check all parameters + if( Remove.startsBehind( Size-1 ) || (Remove.width()==0 && InputLength==0) ) + return 0; + + Remove.restrictEndTo( Size-1 ); + if( Remove.start() + InputLength > Size ) + InputLength = Size - Remove.start(); + + int SizeDiff = InputLength - Remove.width(); + + // is input longer than removed? + if( SizeDiff > 0 ) + { + unsigned int BehindInsertPos = Remove.start() + InputLength; + // fmove right data behind the input range + memmove( &Data[BehindInsertPos], &Data[Remove.end()+1], Size-BehindInsertPos ); + } + // is input smaller than removed? + else if( SizeDiff < 0 ) + { + unsigned int BehindRemovePos = Remove.end()+1; + // fmove right data behind the input range + memmove( &Data[Remove.start()+InputLength], &Data[BehindRemovePos], Size-BehindRemovePos ); + // clear freed space + reset( Size+SizeDiff, -SizeDiff ); + } + // insert input + memcpy( &Data[Remove.start()], D, InputLength ); + + Modified = true; + return InputLength; +} + + +int KFixedSizeBuffer::move( int DestPos, KSection SourceSection ) +{ + // check all parameters + if( SourceSection.start() >= (int)Size || SourceSection.width() == 0 + || DestPos > (int)Size || SourceSection.start() == DestPos ) + return SourceSection.start(); + + SourceSection.restrictEndTo( Size-1 ); + bool ToRight = DestPos > SourceSection.start(); + int MovedLength = SourceSection.width(); + int DisplacedLength = ToRight ? DestPos - SourceSection.end()-1 : SourceSection.start() - DestPos; + + // find out section that is smaller + int SmallPartLength, LargePartLength, SmallPartStart, LargePartStart, SmallPartDest, LargePartDest; + // moving part is smaller? + if( MovedLength < DisplacedLength ) + { + SmallPartStart = SourceSection.start(); + SmallPartLength = MovedLength; + LargePartLength = DisplacedLength; + // moving part moves right? + if( ToRight ) + { + SmallPartDest = DestPos - MovedLength; + LargePartStart = SourceSection.end()+1; + LargePartDest = SourceSection.start(); + } + else + { + SmallPartDest = DestPos; + LargePartStart = DestPos; + LargePartDest = DestPos + MovedLength; + } + } + else + { + LargePartStart = SourceSection.start(); + LargePartLength = MovedLength; + SmallPartLength = DisplacedLength; + // moving part moves right? + if( ToRight ) + { + LargePartDest = DestPos - MovedLength; + SmallPartStart = SourceSection.end()+1; + SmallPartDest = SourceSection.start(); + } + else + { + LargePartDest = DestPos; + SmallPartStart = DestPos; + SmallPartDest = DestPos + MovedLength; + } + } + + // copy smaller part to tempbuffer + char *Temp = new char[SmallPartLength]; + memcpy( Temp, &Data[SmallPartStart], SmallPartLength ); + + // move the larger part + memmove( &Data[LargePartDest], &Data[LargePartStart], LargePartLength ); + + // copy smaller part to its new dest + memcpy( &Data[SmallPartDest], Temp, SmallPartLength ); + delete [] Temp; + + Modified = true; + return MovedLength < DisplacedLength ? SmallPartDest : LargePartDest; +} + + +int KFixedSizeBuffer::fill( const char FChar, int FillLength, unsigned int Pos ) +{ + // nothing to fill + if( Pos >= Size ) + return 0; + + unsigned int LengthToEnd = Size - Pos; + + if( FillLength < 0 || FillLength > (int)LengthToEnd ) + FillLength = LengthToEnd; + + memset( &Data[Pos], FChar, FillLength ); + Modified = true; + return FillLength; +} + + +int KFixedSizeBuffer::compare( const KDataBuffer &Other, KSection OtherRange, unsigned int Pos ) +{ + //kdDebug() << QString("Pos: %1, OtherRange: (%3/%4)" ).arg(Pos).arg(OtherRange.start()).arg(OtherRange.end()) + // << endl; + // test other values + if( OtherRange.startsBehind(Other.size()-1) ) + return 1; + + // check own values + if( Pos >= Size ) + return -1; + + int ValueByLength = 0; // default: equal + + KSection Range( Pos, OtherRange.width(), true ); + int Last = Other.size()-1; + // + if( OtherRange.endsBehind(Last) ) + { + // make shorter + OtherRange.setEnd( Last ); + if( OtherRange.width() < Range.width() ) + ValueByLength = 1; + } + Last = Size-1; + if( Range.endsBehind(Last) ) + { + // make shorter + Range.setEnd( Last ); + if( OtherRange.width() > Range.width() ) + ValueByLength = -1; + } + //kdDebug() + // << QString( "Range: (%1/%2), OtherRange: (%3/%4)" ).arg(Range.start()).arg(Range.end()).arg(OtherRange.start()).arg(OtherRange.end()) + // << endl; + int oi = OtherRange.start(); + for( int i=Range.start(); i<=Range.end(); ++i,++oi ) + { + char OD = Other.datum(oi); + char D = Data[i]; + //kdDebug() << QString("%1==%2").arg((int)D).arg((int)OD) << endl; + if( OD == D ) + continue; + return OD < D ? 1 : -1; + } + + return ValueByLength; +} + + +int KFixedSizeBuffer::find( const char*/*KeyData*/, int /*Length*/, KSection /*Section*/ ) const { return 0; } +int KFixedSizeBuffer::rfind( const char*, int /*Length*/, int /*Pos*/ ) const { return 0; } + + +void KFixedSizeBuffer::reset( unsigned int Pos, unsigned int Length ) +{ + memset( &Data[Pos], FillUpChar, Length ); +} diff --git a/khexedit/lib/kfixedsizebuffer.h b/khexedit/lib/kfixedsizebuffer.h new file mode 100644 index 0000000..15c17da --- /dev/null +++ b/khexedit/lib/kfixedsizebuffer.h @@ -0,0 +1,116 @@ +/*************************************************************************** + kfixedsizebuffer.h - description + ------------------- + begin : Mit Jun 03 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KFIXEDSIZEBUFFER_H +#define KHE_KFIXEDSIZEBUFFER_H + +#include "kdatabuffer.h" + +namespace KHE +{ + +/** base class for all Data buffers that are used to display + * TODO: think about a way to inform KHexEdit that there has been + * a change in the buffer outside. what kind of changes are possible? + *@author Friedrich W. H. Kossebau + */ + +class KFixedSizeBuffer : public KDataBuffer +{ + public: + /** creates a readonly buffer around the given data */ + KFixedSizeBuffer( char *D, unsigned int S, char FUC = '\0' ); + /** creates a writeable buffer which is deleted at the end */ + KFixedSizeBuffer( unsigned int S, char FUC = '\0' ); + virtual ~KFixedSizeBuffer(); + + public: // KDataBuffer API + virtual bool prepareRange( KSection Range ) const; + virtual const char *dataSet( KSection S ) const; + virtual char datum( unsigned int Offset ) const; + virtual int size() const; + virtual bool isReadOnly() const; + virtual bool isModified() const; + + virtual int insert( int Pos, const char*, int Length ); + virtual int remove( KSection Remove ); + virtual unsigned int replace( KSection Remove, const char*, unsigned int InputLength ); + virtual int move( int DestPos, KSection SourceSection ); + virtual int fill( const char FillChar, int Length = -1, unsigned int Pos = 0 ); + virtual void setDatum( unsigned int Offset, const char Char ); + + virtual void setModified( bool M = true ); + + virtual int find( const char*KeyData, int Length, KSection Section ) const; + virtual int rfind( const char*, int Length, int Pos = -1 ) const; + +/* virtual int find( const QString &expr, bool cs, bool wo, bool forward = true, int *index = 0 ); */ + + public: + void setReadOnly( bool RO = true ); + int compare( const KDataBuffer &Other, KSection Range, unsigned int Pos = 0 ); + int compare( const KDataBuffer &Other, int OtherPos, int Length, unsigned int Pos = 0 ); + int compare( const KDataBuffer &Other ); + + public: + char *rawData() const; + + protected: + void reset( unsigned int Pos, unsigned int Length ); + + protected: + /** */ + char *Data; + /***/ + unsigned int Size; + /** */ + char FillUpChar; + /** */ + bool ReadOnly:1; + /** */ + bool Modified:1; + /** */ + bool AutoDelete:1; +}; + + +inline bool KFixedSizeBuffer::prepareRange( KSection ) const { return true; } +inline const char *KFixedSizeBuffer::dataSet( KSection S ) const { return &Data[S.start()]; } + +inline char KFixedSizeBuffer::datum( unsigned int Offset ) const { return Data[Offset]; } +inline int KFixedSizeBuffer::size() const { return Size; } + +inline void KFixedSizeBuffer::setDatum( unsigned int Offset, const char Char ) +{ Data[Offset] = Char; Modified = true; } + +inline bool KFixedSizeBuffer::isReadOnly() const { return ReadOnly; } +inline bool KFixedSizeBuffer::isModified() const { return Modified; } + +inline void KFixedSizeBuffer::setReadOnly( bool RO ) { ReadOnly = RO; } +inline void KFixedSizeBuffer::setModified( bool M ) { Modified = M; } + +inline int KFixedSizeBuffer::compare( const KDataBuffer &Other ) +{ return compare( Other, KSection(0,Other.size()-1),0 ); } + +inline int KFixedSizeBuffer::compare( const KDataBuffer &Other, int OtherPos, int Length, unsigned int Pos ) +{ return compare( Other, KSection(OtherPos,Length,true),Pos ); } + +inline char *KFixedSizeBuffer::rawData() const { return Data; } + +} + +#endif diff --git a/khexedit/lib/khe.h b/khexedit/lib/khe.h new file mode 100644 index 0000000..af029ea --- /dev/null +++ b/khexedit/lib/khe.h @@ -0,0 +1,95 @@ +/*************************************************************************** + khe.h - description + ------------------- + begin : Mon Jul 14 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KHE_H +#define KHE_KHE_H + +// here we collect all general data +// let's see how much it gets ;) + +namespace KHE +{ + enum KCoding { HexadecimalCoding=0, DecimalCoding=1, OctalCoding=2, BinaryCoding=3, MaxCodingId=0xFFFF }; + static const int NoOfCodings = 4; + + /** */ + enum KEncoding + { + /** the coding of your shell */ + LocalEncoding=0, + /** ASCII encoding, also known as Latin1 */ + ISO8859_1Encoding, + /** */ + ISO8859_2Encoding, + /** */ + ISO8859_3Encoding, + /** */ + ISO8859_4Encoding, + /** */ + ISO8859_5Encoding, + /** */ + ISO8859_6Encoding, + /** */ + ISO8859_7Encoding, + /** */ + ISO8859_8Encoding, + /** */ + ISO8859_8_IEncoding, + /** */ + ISO8859_9Encoding, + /** */ + ISO8859_11Encoding, + /** */ + ISO8859_13Encoding, + /** */ + ISO8859_15Encoding, + /** */ + CP1250Encoding, + /** */ + CP1251Encoding, + /** */ + CP1252Encoding, + /** */ + CP1253Encoding, + /** */ + CP1254Encoding, + /** */ + CP1255Encoding, + /** */ + CP1256Encoding, + /** */ + CP1257Encoding, + /** */ + CP1258Encoding, + /** */ + IBM850Encoding, + /** */ + IBM866Encoding, + /** */ + KOI8_REncoding, + /** */ + KOI8_UEncoding, + /** the most common EBCDIC codepage */ + EBCDIC1047Encoding, + /** Offset for own encodings which are bound in by plugins */ + StartOfOwnEncoding=0x8000, + /** this should enable extension without breaking binary compatibility */ + MaxEncodingId=0xFFFF + }; +} + +#endif diff --git a/khexedit/lib/khechar.h b/khexedit/lib/khechar.h new file mode 100644 index 0000000..4f51e9e --- /dev/null +++ b/khexedit/lib/khechar.h @@ -0,0 +1,44 @@ +/*************************************************************************** + helper.h - description + ------------------- + begin : Do Nov 25 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + +#ifndef KHE_KHECHAR_H +#define KHE_KHECHAR_H + +// qt specific +#include + +namespace KHE +{ + +class KHEChar : public QChar +{ + public: + KHEChar( QChar C ); + KHEChar( QChar C, bool U ); + public: + bool isUndefined() const; + protected: + // the byte is not defined + bool IsUndefined:1; +}; + +inline KHEChar::KHEChar( QChar C ) : QChar( C ), IsUndefined( false ) {} +inline KHEChar::KHEChar( QChar C, bool U ) : QChar( C ), IsUndefined( U ) {} +inline bool KHEChar::isUndefined() const { return IsUndefined; } + +} + +#endif diff --git a/khexedit/lib/khexedit.cpp b/khexedit/lib/khexedit.cpp new file mode 100644 index 0000000..85478e5 --- /dev/null +++ b/khexedit/lib/khexedit.cpp @@ -0,0 +1,2032 @@ +/*************************************************************************** + khexedit.cpp - description + ------------------- + begin : Die Mai 13 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +//#include + +// c specific +#include +//#include +// c++ specific +//#include +// qt specific +#include +#include +#include +#include +#include +// kde specific +#ifndef QT_ONLY +#include +#endif +// lib specific +#include "kdatabuffer.h" +#include "koffsetcolumn.h" +#include "kvaluecolumn.h" +#include "kcharcolumn.h" +#include "kbordercolumn.h" +#include "kbuffercursor.h" +#include "kbufferlayout.h" +#include "kbufferranges.h" +#include "controller/ktabcontroller.h" +#include "controller/knavigator.h" +#include "controller/kvalueeditor.h" +#include "controller/kchareditor.h" +#include "kbufferdrag.h" +#include "kcursor.h" +#include "kbytecodec.h" +#include "kcharcodec.h" +#include "kwordbufferservice.h" +#include "khexedit.h" + +using namespace KHE; + +// zooming is done in steps of font size points +static const int DefaultZoomStep = 1; +static const int DefaultStartOffset = 0;//5; +static const int DefaultFirstLineOffset = 0; +static const int DefaultNoOfBytesPerLine = 16; +static const KHexEdit::KResizeStyle DefaultResizeStyle = KHexEdit::FullSizeUsage; +static const KHexEdit::KEncoding DefaultEncoding = KHexEdit::LocalEncoding; +static const int DefaultScrollTimerPeriod = 100; +static const int InsertCursorWidth = 2; + + + +KHexEdit::KHexEdit( KDataBuffer *Buffer, QWidget *Parent, const char *Name, WFlags Flags ) + : KColumnsView( Parent, Name, Flags ), + DataBuffer( Buffer ), + BufferLayout( new KBufferLayout(DefaultNoOfBytesPerLine,DefaultStartOffset,0) ), + BufferCursor( new KBufferCursor(BufferLayout) ), + BufferRanges( new KBufferRanges(BufferLayout) ), + CursorBlinkTimer( new QTimer(this) ), + ScrollTimer( new QTimer(this) ), + DragStartTimer( new QTimer(this) ), + TrippleClickTimer( new QTimer(this) ), + CursorPixmaps( new KCursor() ), + Codec( 0 ), + ClipboardMode( QClipboard::Clipboard ), + ResizeStyle( DefaultResizeStyle ), + Encoding( MaxEncodingId ), // forces update + ReadOnly( false ), +// Modified( false ), + OverWriteOnly( false ), + OverWrite( true ), + MousePressed( false ), + InDoubleClick( false ), + InDnD( false ), + DragStartPossible( false ), + CursorPaused( false ), + BlinkCursorVisible( false ), + InZooming( false ), + d( 0 ) +{ + // initalize layout + if( DataBuffer ) + BufferLayout->setLength( DataBuffer->size() ); + BufferLayout->setNoOfLinesPerPage( noOfLinesPerPage() ); + + // creating the columns in the needed order + OffsetColumn = new KOffsetColumn( this, DefaultFirstLineOffset, DefaultNoOfBytesPerLine, KOffsetFormat::Hexadecimal ); + FirstBorderColumn = new KBorderColumn( this, false ); + ValueColumn = new KValueColumn( this, DataBuffer, BufferLayout, BufferRanges ); + SecondBorderColumn = new KBorderColumn( this, true ); + CharColumn = new KCharColumn( this, DataBuffer, BufferLayout, BufferRanges ); + + // select the active column + ActiveColumn = &charColumn(); + InactiveColumn = &valueColumn(); + + // set encoding + Codec = KCharCodec::createCodec( (KHE::KEncoding)DefaultEncoding ); + valueColumn().setCodec( Codec ); + charColumn().setCodec( Codec ); + Encoding = DefaultEncoding; + + TabController = new KTabController( this, 0 ); + Navigator = new KNavigator( this, TabController ); + ValueEditor = new KValueEditor( ValueColumn, BufferCursor, this, Navigator ); + CharEditor = new KCharEditor( CharColumn, BufferCursor, this, Navigator ); + + Controller = Navigator; + +#ifdef QT_ONLY + QFont FixedFont( "fixed", 10 ); + FixedFont.setFixedPitch( true ); + setFont( FixedFont ); +#else + setFont( KGlobalSettings::fixedFont() ); +#endif + + // get the full control + viewport()->setFocusProxy( this ); + viewport()->setFocusPolicy( WheelFocus ); + + viewport()->installEventFilter( this ); + installEventFilter( this ); + + connect( CursorBlinkTimer, SIGNAL(timeout()), this, SLOT(blinkCursor()) ); + connect( ScrollTimer, SIGNAL(timeout()), this, SLOT(autoScrollTimerDone()) ); + connect( DragStartTimer, SIGNAL(timeout()), this, SLOT(startDrag()) ); + + viewport()->setAcceptDrops( true ); +} + + +KHexEdit::~KHexEdit() +{ + delete TabController; + delete Navigator; + delete ValueEditor; + delete CharEditor; +} + + +int KHexEdit::noOfBytesPerLine() const { return BufferLayout->noOfBytesPerLine(); } +int KHexEdit::firstLineOffset() const { return OffsetColumn->firstLineOffset(); } +int KHexEdit::startOffset() const { return BufferLayout->startOffset(); } +KHexEdit::KResizeStyle KHexEdit::resizeStyle() const { return ResizeStyle; } +KHexEdit::KCoding KHexEdit::coding() const { return (KHexEdit::KCoding)valueColumn().coding(); } +KPixelX KHexEdit::byteSpacingWidth() const { return valueColumn().byteSpacingWidth(); } +int KHexEdit::noOfGroupedBytes() const { return valueColumn().noOfGroupedBytes(); } +KPixelX KHexEdit::groupSpacingWidth() const { return valueColumn().groupSpacingWidth(); } +KPixelX KHexEdit::binaryGapWidth() const { return valueColumn().binaryGapWidth(); } +bool KHexEdit::isOverwriteMode() const { return OverWrite; } +bool KHexEdit::isOverwriteOnly() const { return OverWriteOnly; } +bool KHexEdit::isReadOnly() const { return ReadOnly; } +bool KHexEdit::isModified() const { return DataBuffer->isModified(); } +bool KHexEdit::tabChangesFocus() const { return TabController->tabChangesFocus(); } +bool KHexEdit::showUnprintable() const { return charColumn().showUnprintable(); } +QChar KHexEdit::substituteChar() const { return charColumn().substituteChar(); } +QChar KHexEdit::undefinedChar() const { return charColumn().undefinedChar(); } +KHexEdit::KEncoding KHexEdit::encoding() const { return (KHexEdit::KEncoding)Encoding; } +const QString &KHexEdit::encodingName() const { return Codec->name(); } + +KSection KHexEdit::selection() const { return BufferRanges->selection(); } +int KHexEdit::cursorPosition() const { return BufferCursor->index(); } +bool KHexEdit::isCursorBehind() const { return BufferCursor->isBehind(); } +KHexEdit::KBufferColumnId KHexEdit::cursorColumn() const +{ return static_cast( ActiveColumn ) == &valueColumn()? ValueColumnId : CharColumnId; } + +void KHexEdit::setOverwriteOnly( bool OO ) { OverWriteOnly = OO; if( OverWriteOnly ) setOverwriteMode( true ); } +void KHexEdit::setModified( bool M ) { DataBuffer->setModified(M); } +void KHexEdit::setTabChangesFocus( bool TCF ) { TabController->setTabChangesFocus(TCF); } +void KHexEdit::setFirstLineOffset( int FLO ) { OffsetColumn->setFirstLineOffset( FLO ); } + +bool KHexEdit::offsetColumnVisible() const { return OffsetColumn->isVisible(); } +int KHexEdit::visibleBufferColumns() const +{ return (valueColumn().isVisible() ? ValueColumnId : 0) | (charColumn().isVisible() ? CharColumnId : 0); } + + +void KHexEdit::setOverwriteMode( bool OM ) +{ + if( (OverWriteOnly && !OM) || (OverWrite == OM) ) + return; + + OverWrite = OM; + + // affected: + // cursor shape + bool ChangeCursor = !( CursorPaused || ValueEditor->isInEditMode() ); + if( ChangeCursor ) + pauseCursor(); + + BufferCursor->setAppendPosEnabled( !OverWrite ); + + if( ChangeCursor ) + unpauseCursor(); + + emit cutAvailable( !OverWrite && BufferRanges->hasSelection() ); +} + + +void KHexEdit::setDataBuffer( KDataBuffer *B ) +{ + //pauseCursor(); + ValueEditor->reset(); + CursorPaused = true; + + DataBuffer = B; + valueColumn().set( DataBuffer ); + charColumn().set( DataBuffer); + + // affected: + // length -> no of lines -> width + BufferLayout->setLength( DataBuffer->size() ); + adjustLayoutToSize(); + + // ensure that the widget is readonly if the buffer is + if( DataBuffer->isReadOnly() ) + setReadOnly( true ); + + updateView(); + BufferCursor->gotoStart(); + ensureCursorVisible(); + unpauseCursor(); +} + + +void KHexEdit::setStartOffset( int SO ) +{ + if( !BufferLayout->setStartOffset(SO) ) + return; + + pauseCursor(); + // affects: + // the no of lines -> width + adjustLayoutToSize(); + + updateView(); + + BufferCursor->updateCoord(); + ensureCursorVisible(); + unpauseCursor(); +} + + +void KHexEdit::setReadOnly( bool RO ) +{ + // don't set editor readwrite if databuffer is readonly + ReadOnly = (DataBuffer && DataBuffer->isReadOnly()) ? true : RO; + + Controller = ReadOnly ? (KController*)Navigator : + cursorColumn() == CharColumnId ? (KController*)CharEditor : (KController*)ValueEditor; +} + + +void KHexEdit::setBufferSpacing( KPixelX ByteSpacing, int NoOfGroupedBytes, KPixelX GroupSpacing ) +{ + if( !valueColumn().setSpacing(ByteSpacing,NoOfGroupedBytes,GroupSpacing) ) + return; + + updateViewByWidth(); +} + + +void KHexEdit::setCoding( KCoding C ) +{ + uint OldCodingWidth = valueColumn().byteCodec()->encodingWidth(); + + if( !valueColumn().setCoding((KHE::KCoding)C) ) + return; + + uint NewCodingWidth = valueColumn().byteCodec()->encodingWidth(); + ValueEditor->ByteBuffer.setLength( NewCodingWidth ); //hack for now + + // no change in the width? + if( NewCodingWidth == OldCodingWidth ) + updateColumn( valueColumn() ); + else + updateViewByWidth(); +} + + +void KHexEdit::setResizeStyle( KResizeStyle NewStyle ) +{ + if( ResizeStyle == NewStyle ) + return; + + ResizeStyle = NewStyle; + + updateViewByWidth(); +} + + +void KHexEdit::setNoOfBytesPerLine( int NoBpL ) +{ + // if the number is explicitly set we expect a wish for no automatic resize + ResizeStyle = NoResize; + + if( !BufferLayout->setNoOfBytesPerLine(NoBpL) ) + return; + updateViewByWidth(); +} + + +void KHexEdit::setByteSpacingWidth( int/*KPixelX*/ BSW ) +{ + if( !valueColumn().setByteSpacingWidth(BSW) ) + return; + updateViewByWidth(); +} + +void KHexEdit::setNoOfGroupedBytes( int NoGB ) +{ + if( !valueColumn().setNoOfGroupedBytes(NoGB) ) + return; + updateViewByWidth(); +} + + +void KHexEdit::setGroupSpacingWidth( int/*KPixelX*/ GSW ) +{ + if( !valueColumn().setGroupSpacingWidth(GSW) ) + return; + updateViewByWidth(); +} + + +void KHexEdit::setBinaryGapWidth( int/*KPixelX*/ BGW ) +{ + if( !valueColumn().setBinaryGapWidth(BGW) ) + return; + updateViewByWidth(); +} + + +void KHexEdit::setSubstituteChar( QChar SC ) +{ + if( !charColumn().setSubstituteChar(SC) ) + return; + pauseCursor(); + updateColumn( charColumn() ); + unpauseCursor(); +} + +void KHexEdit::setUndefinedChar( QChar UC ) +{ + if( !charColumn().setUndefinedChar(UC) ) + return; + pauseCursor(); + updateColumn( charColumn() ); + unpauseCursor(); +} + +void KHexEdit::setShowUnprintable( bool SU ) +{ + if( !charColumn().setShowUnprintable(SU) ) + return; + pauseCursor(); + updateColumn( charColumn() ); + unpauseCursor(); +} + + +void KHexEdit::setEncoding( KEncoding C ) +{ + if( Encoding == C ) + return; + + KCharCodec *NC = KCharCodec::createCodec( (KHE::KEncoding)C ); + if( NC == 0 ) + return; + + valueColumn().setCodec( NC ); + charColumn().setCodec( NC ); + + delete Codec; + Codec = NC; + Encoding = C; + + pauseCursor(); + updateColumn( valueColumn() ); + updateColumn( charColumn() ); + unpauseCursor(); +} + +// TODO: join with function above! +void KHexEdit::setEncoding( const QString& EncodingName ) +{ + if( EncodingName == Codec->name() ) + return; + + KCharCodec *NC = KCharCodec::createCodec( EncodingName ); + if( NC == 0 ) + return; + + valueColumn().setCodec( NC ); + charColumn().setCodec( NC ); + + delete Codec; + Codec = NC; + Encoding = LocalEncoding; // TODO: add encoding no to every known codec + + pauseCursor(); + updateColumn( valueColumn() ); + updateColumn( charColumn() ); + unpauseCursor(); +} + + +void KHexEdit::fontChange( const QFont &OldFont ) +{ + QScrollView::fontChange( OldFont ); + + if( !InZooming ) + DefaultFontSize = font().pointSize(); + + // get new values + QFontMetrics FM( fontMetrics() ); + KPixelX DigitWidth = FM.maxWidth(); + KPixelY DigitBaseLine = FM.ascent(); + + setLineHeight( FM.height() ); + + // update all dependant structures + BufferLayout->setNoOfLinesPerPage( noOfLinesPerPage() ); + + OffsetColumn->setMetrics( DigitWidth, DigitBaseLine ); + valueColumn().setMetrics( DigitWidth, DigitBaseLine ); + charColumn().setMetrics( DigitWidth, DigitBaseLine ); + + updateViewByWidth(); +} + + +void KHexEdit::updateViewByWidth() +{ + pauseCursor(); + + adjustToLayoutNoOfBytesPerLine(); + adjustLayoutToSize(); + + updateView(); + + BufferCursor->updateCoord(); + ensureCursorVisible(); + + unpauseCursor(); +} + + +void KHexEdit::zoomIn() { zoomIn( DefaultZoomStep ); } +void KHexEdit::zoomOut() { zoomOut( DefaultZoomStep ); } + +void KHexEdit::zoomIn( int PointInc ) +{ + InZooming = true; + QFont F( font() ); + F.setPointSize( QFontInfo(F).pointSize() + PointInc ); + setFont( F ); + InZooming = false; +} + +void KHexEdit::zoomOut( int PointDec ) +{ + InZooming = true; + QFont F( font() ); + F.setPointSize( QMAX( 1, QFontInfo(F).pointSize() - PointDec ) ); + setFont( F ); + InZooming = false; +} + + +void KHexEdit::zoomTo( int PointSize ) +{ + InZooming = true; + QFont F( font() ); + F.setPointSize( PointSize ); + setFont( F ); + InZooming = false; +} + + +void KHexEdit::unZoom() +{ + zoomTo( DefaultFontSize ); +} + + +void KHexEdit::adjustLayoutToSize() +{ + // check whether there is a change with the numbers of fitting bytes per line + if( ResizeStyle != NoResize ) + { + int FittingBytesPerLine = fittingBytesPerLine( size() ); + +// std::cout<<"FitBpL"<setNoOfBytesPerLine(FittingBytesPerLine) ) + adjustToLayoutNoOfBytesPerLine(); + } + + setNoOfLines( BufferLayout->noOfLines() ); +} + + +void KHexEdit::adjustToLayoutNoOfBytesPerLine() +{ + OffsetColumn->setDelta( BufferLayout->noOfBytesPerLine() ); + valueColumn().resetXBuffer(); + charColumn().resetXBuffer(); + + updateWidths(); +} + + +void KHexEdit::setNoOfLines( int NewNoOfLines ) +{ + KColumnsView::setNoOfLines( NewNoOfLines>1?NewNoOfLines:1 ); +} + + +void KHexEdit::toggleOffsetColumn( bool Visible ) +{ + bool OCVisible = OffsetColumn->isVisible(); + // no change? + if( OCVisible == Visible ) + return; + + OffsetColumn->setVisible( Visible ); + FirstBorderColumn->setVisible( Visible ); + + updateViewByWidth(); +} + + +QSize KHexEdit::sizeHint() const +{ + return QSize( totalWidth(), totalHeight() ); +} + + +QSize KHexEdit::minimumSizeHint() const +{ + // TODO: better minimal width (visibility!) + return QSize( OffsetColumn->visibleWidth()+FirstBorderColumn->visibleWidth()+SecondBorderColumn->visibleWidth()+valueColumn().byteWidth()+charColumn().byteWidth(), + lineHeight() + noOfLines()>1? style().pixelMetric(QStyle::PM_ScrollBarExtent):0 ); +} + + +void KHexEdit::resizeEvent( QResizeEvent *ResizeEvent ) +{ + if( ResizeStyle != NoResize ) + { + int FittingBytesPerLine = fittingBytesPerLine( ResizeEvent->size() ); + + // changes? + if( BufferLayout->setNoOfBytesPerLine(FittingBytesPerLine) ) + { + setNoOfLines( BufferLayout->noOfLines() ); + updateViewByWidth(); + } + } + + QScrollView::resizeEvent( ResizeEvent ); + + BufferLayout->setNoOfLinesPerPage( noOfLinesPerPage() ); // TODO: doesn't work with the new size!!! +} + + +int KHexEdit::fittingBytesPerLine( const QSize &NewSize ) const +{ + KPixelX ReservedWidth = OffsetColumn->visibleWidth() + FirstBorderColumn->visibleWidth() + SecondBorderColumn->visibleWidth(); + + // abstract framewidth as well as offset and border columns width + int UsedbyFrameWidth = 2 * frameWidth(); + KPixelX FullWidth = NewSize.width() - UsedbyFrameWidth - ReservedWidth; + +// // no width left for resizeable columns? TODO: put this in resizeEvent +// if( FullWidth < 0 ) +// return; + + KPixelY FullHeight = NewSize.height() - UsedbyFrameWidth; + + // check influence of dis-/appearing of the vertical scrollbar + bool VerticalScrollbarIsVisible = verticalScrollBar()->isVisible(); + KPixelX ScrollbarExtent = style().pixelMetric( QStyle::PM_ScrollBarExtent );//verticalScrollBar()->width(); + + KPixelX AvailableWidth = FullWidth; + if( VerticalScrollbarIsVisible ) + AvailableWidth -= ScrollbarExtent; + + enum KMatchTrial { FirstRun, RerunWithScrollbarOn, TestWithoutScrollbar }; + KMatchTrial MatchRun = FirstRun; + + // prepare needed values + KPixelX DigitWidth = valueColumn().digitWidth(); + KPixelX TextByteWidth = charColumn().isVisible() ? DigitWidth : 0; + KPixelX HexByteWidth = valueColumn().isVisible() ? valueColumn().byteWidth() : 0; + KPixelX ByteSpacingWidth = valueColumn().isVisible() ? valueColumn().byteSpacingWidth() : 0; + KPixelX GroupSpacingWidth; + int NoOfGroupedBytes = valueColumn().noOfGroupedBytes(); + // no grouping? + if( NoOfGroupedBytes == 0 ) + { + // faking grouping by 1 + NoOfGroupedBytes = 1; + GroupSpacingWidth = 0; + } + else + GroupSpacingWidth = valueColumn().isVisible() ? valueColumn().groupSpacingWidth() : 0; + + KPixelX HexByteGroupWidth = NoOfGroupedBytes * HexByteWidth + (NoOfGroupedBytes-1)*ByteSpacingWidth; + KPixelX TextByteGroupWidth = NoOfGroupedBytes * TextByteWidth; + KPixelX TotalGroupWidth = HexByteGroupWidth + GroupSpacingWidth + TextByteGroupWidth; + + int FittingBytesPerLine; + int WithScrollbarFittingBytesPerLine = 0; + for(;;) + { +// std::cout << "matchWidth: " << FullWidth +// << " (v:" << visibleWidth() +// << ", f:" << frameWidth() +// << ", A:" << AvailableWidth +// << ", S:" << ScrollbarExtent +// << ", R:" << ReservedWidth << ")" << std::endl; + + // calculate fitting groups per line + int FittingGroupsPerLine = (AvailableWidth+GroupSpacingWidth) // fake spacing after last group + / TotalGroupWidth; + + // calculate the fitting bytes per line by groups + FittingBytesPerLine = NoOfGroupedBytes * FittingGroupsPerLine; + + // not only full groups? + if( ResizeStyle == FullSizeUsage && NoOfGroupedBytes > 1 ) + { + if( FittingGroupsPerLine > 0 ) + AvailableWidth -= FittingGroupsPerLine*TotalGroupWidth; // includes additional spacing after last group + +// std::cout << "Left: " << AvailableWidth << "("< 0 ) + FittingBytesPerLine += (AvailableWidth+ByteSpacingWidth) / (HexByteWidth+ByteSpacingWidth+TextByteWidth); + + // is there not even the space for a single byte? + if( FittingBytesPerLine == 0 ) + { + // ensure at least one byte per line + FittingBytesPerLine = 1; + // and + break; + } + } + // is there not the space for a single group? + else if( FittingBytesPerLine == 0 ) + { + // ensures at least one group + FittingBytesPerLine = NoOfGroupedBytes; + break; + } + +// std::cout << "meantime: " << FittingGroupsPerLine << " (T:" << TotalGroupWidth +// << ", h:" << HexByteGroupWidth +// << ", t:" << TextByteGroupWidth +// << ", s:" << GroupSpacingWidth << ") " <length()+BufferLayout->startOffset()+FittingBytesPerLine-1) + / FittingBytesPerLine; + KPixelY NewHeight = NewNoOfLines * LineHeight; + + if( VerticalScrollbarIsVisible ) + { + if( MatchRun == TestWithoutScrollbar ) + { + // did the test without the scrollbar fail, don't the data fit into the view? + if( NewHeight>FullHeight ) + // reset to old calculated value + FittingBytesPerLine = WithScrollbarFittingBytesPerLine; + break; + } + + // a chance for to perhaps fit in height? + if( FittingBytesPerLine <= BufferLayout->noOfBytesPerLine() ) + { + // remember this trial's result and calc number of bytes with vertical scrollbar on + WithScrollbarFittingBytesPerLine = FittingBytesPerLine; + AvailableWidth = FullWidth; + MatchRun = TestWithoutScrollbar; +// std::cout << "tested without scrollbar..." << std::endl; + continue; + } + } + else + { + // doesn't it fit into the height anymore? + if( NewHeight>FullHeight && MatchRun==FirstRun ) + { + // need for a scrollbar has risen... ->less width, new calculation + AvailableWidth = FullWidth - ScrollbarExtent; + MatchRun = RerunWithScrollbarOn; +// std::cout << "rerun with scrollbar on..." << std::endl; + continue; + } + } + + break; + } + + return FittingBytesPerLine; +} + + +bool KHexEdit::selectWord( /*unsigned TODO:change all unneeded signed into unsigned!*/ int Index ) +{ + if( Index >= 0 && Index < BufferLayout->length() ) + { + KWordBufferService WBS( DataBuffer, Codec ); + KSection WordSection = WBS.wordSection( Index ); + if( WordSection.isValid() ) + { + pauseCursor(); + + BufferRanges->setFirstWordSelection( WordSection ); + BufferCursor->gotoIndex( WordSection.end()+1 ); + repaintChanged(); + + unpauseCursor(); + return true; + } + } + return false; +} + +void KHexEdit::select( KSection Section ) +{ + if( !Section.isValid() ) + return; + + Section.restrictTo( KSection(0,BufferLayout->length()-1) ); + + pauseCursor(); + + BufferRanges->setSelection( Section ); + BufferCursor->gotoIndex( Section.end()+1 ); + repaintChanged(); + + unpauseCursor(); + + if( !OverWrite ) emit cutAvailable( BufferRanges->hasSelection() ); + emit copyAvailable( BufferRanges->hasSelection() ); + emit selectionChanged( Section.start(), Section.end() ); +} + +void KHexEdit::selectAll( bool Select ) +{ + KSection Selection; + + pauseCursor( true ); + + if( !Select ) + BufferRanges->removeSelection(); + else + { + Selection.set( 0, BufferLayout->length()-1 ); + BufferRanges->setSelection( Selection ); + BufferCursor->gotoEnd(); + } + + repaintChanged(); + + unpauseCursor(); + + if( !OverWrite ) emit cutAvailable( BufferRanges->hasSelection() ); + emit copyAvailable( BufferRanges->hasSelection() ); + emit selectionChanged( Selection.start(), Selection.end() ); + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +} + + +bool KHexEdit::hasSelectedData() const +{ + return BufferRanges->hasSelection(); +} + + +QByteArray KHexEdit::selectedData() const +{ + if( !BufferRanges->hasSelection() ) + return QByteArray(); + + KSection Selection = BufferRanges->selection(); + QByteArray SD( Selection.width() ); + DataBuffer->copyTo( SD.data(), Selection.start(), Selection.width() ); + return SD; +} + + +KBufferDrag *KHexEdit::dragObject( QWidget *Parent ) const +{ + if( !BufferRanges->hasSelection() ) + return 0; + + const KOffsetColumn *OC; + const KValueColumn *HC; + const KCharColumn *TC; + KCoordRange Range; + + if( static_cast( ActiveColumn ) == &charColumn() ) + { + OC = 0; + HC = 0; + TC = 0; + } + else + { + OC = OffsetColumn->isVisible() ? OffsetColumn : 0; + HC = valueColumn().isVisible() ? &valueColumn() : 0; + TC = charColumn().isVisible() ? &charColumn() : 0; + KSection S = BufferRanges->selection(); + Range.set( BufferLayout->coordOfIndex(S.start()),BufferLayout->coordOfIndex(S.end()) ); + } + + return new KBufferDrag( selectedData(), Range, OC, HC, TC, + charColumn().substituteChar(), charColumn().undefinedChar(), + Codec->name(), Parent ); +} + + +void KHexEdit::cut() +{ + if( isReadOnly() || OverWrite ) + return; + + KBufferDrag *Drag = dragObject(); + if( !Drag ) + return; + + QApplication::clipboard()->setData( Drag, ClipboardMode ); + + removeSelectedData(); +} + + +void KHexEdit::copy() +{ + KBufferDrag *Drag = dragObject(); + if( !Drag ) + return; + + QApplication::clipboard()->setData( Drag, ClipboardMode ); +} + + +void KHexEdit::paste() +{ + if( isReadOnly() ) + return; + + QMimeSource *Source = QApplication::clipboard()->data( ClipboardMode ); + pasteFromSource( Source ); +} + + +void KHexEdit::pasteFromSource( QMimeSource *Source ) +{ + if( !Source || !KBufferDrag::canDecode(Source) ) + return; + + QByteArray Data; + if( !KBufferDrag::decode(Source,Data) ) + return; + + if( !Data.isEmpty() ) + insert( Data ); +} + + +void KHexEdit::insert( const QByteArray &D ) +{ + pauseCursor( true ); + + KSection ChangedRange; + + if( OverWrite ) + { + if( BufferRanges->hasSelection() ) + { + // replacing the selection: + // we restrict the replacement to the minimum length of selection and input + ChangedRange = BufferRanges->selection(); + ChangedRange.restrictEndTo( ChangedRange.start()+D.size()-1 ); + int W = DataBuffer->replace( ChangedRange, D.data(), ChangedRange.width() ); + BufferCursor->gotoCIndex( ChangedRange.start()+W ); + BufferRanges->removeSelection(); + } + else + { + if( !BufferCursor->isBehind() ) + { + // replacing the normal data, at least until the end + ChangedRange.setByWidth( BufferCursor->realIndex(), D.size() ); + ChangedRange.restrictEndTo( BufferLayout->length()-1 ); + if( ChangedRange.isValid() ) + { + int W = DataBuffer->replace( ChangedRange, D.data(), ChangedRange.width() ); + BufferCursor->gotoNextByte( W ); + } + } + } + } + else + { + if( BufferRanges->hasSelection() ) + { + // replacing the selection + KSection Selection = BufferRanges->selection(); + int OldLastIndex = BufferLayout->length() - 1; + int W = DataBuffer->replace( Selection, D.data(), D.size() ); + updateLength(); + BufferCursor->gotoIndex( Selection.start() + W ); + if( W > 0 ) + { + if( Selection.width() == (int)D.size() ) + ChangedRange = Selection; + else + { + int NewLastIndex = DataBuffer->size() - 1; + ChangedRange.set( Selection.start(), NewLastIndex>OldLastIndex?NewLastIndex:OldLastIndex ); + } + } + BufferRanges->removeSelection(); + } + else + { + bool Appending = BufferCursor->atAppendPos(); + int OldIndex = BufferCursor->realIndex(); + int W = DataBuffer->insert( OldIndex, D.data(), D.size() ); + updateLength(); + // worked? + if( W > 0 ) + { + if( Appending ) + BufferCursor->gotoEnd(); + else + BufferCursor->gotoNextByte( W ); + ChangedRange.set( OldIndex, DataBuffer->size()-1 ); + } + } + } + + bool Changed = ChangedRange.isValid(); + if( Changed ) + { + BufferRanges->addChangedRange( ChangedRange ); + repaintChanged(); + } + ensureCursorVisible(); + + unpauseCursor(); + + if( Changed ) emit bufferChanged( ChangedRange.start(), ChangedRange.end() ); + KSection Selection = BufferRanges->selection(); + emit selectionChanged( Selection.start(), Selection.end() ); +} + + +void KHexEdit::removeSelectedData() +{ + // Can't we do this? + if( isReadOnly() || OverWrite || ValueEditor->isInEditMode() ) + return; + + pauseCursor(); + + KSection Selection = BufferRanges->selection(); + + BufferRanges->removeFurtherSelections(); + + KSection ChangedRange = removeData( Selection ); + BufferRanges->removeSelection(); + + repaintChanged(); + + BufferCursor->gotoCIndex( Selection.start() ); + + ensureCursorVisible(); +// clearUndoRedo(); + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); + + unpauseCursor(); + + if( ChangedRange.isValid() ) emit bufferChanged( ChangedRange.start(), ChangedRange.end() ); + emit selectionChanged( -1, -1 ); +} + + +KSection KHexEdit::removeData( KSection Indizes ) +{ +// if( undoEnabled ) +// { +// checkUndoRedoInfo( UndoRedoInfo::RemoveSelected ); +// if( !undoRedoInfo.valid() ) +// { +// doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index ); +// undoRedoInfo.d->text = QString::null; +// } +// readFormats( c1, c2, undoRedoInfo.d->text, TRUE ); +// } + + KSection ChangedRange( Indizes.start(), BufferLayout->length()-1 ); + // do it! + DataBuffer->remove( Indizes ); + updateLength(); + BufferRanges->addChangedRange( ChangedRange ); + + return ChangedRange; +} + + +void KHexEdit::updateLength() +{ + BufferLayout->setLength( DataBuffer->size() ); + setNoOfLines( BufferLayout->noOfLines() ); +} + + +void KHexEdit::clipboardChanged() +{ + // don't listen to selection changes + disconnect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0 ); + selectAll( false ); +} + + +void KHexEdit::setCursorPosition( int Index, bool Behind ) +{ + pauseCursor( true ); + + BufferCursor->gotoCIndex( Index ); + if( Behind ) + BufferCursor->stepBehind(); + + BufferRanges->removeSelection(); + bool RangesModifed = BufferRanges->isModified(); + if( RangesModifed ) + { + repaintChanged(); + + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); + + } + ensureCursorVisible(); + unpauseCursor(); + + if( RangesModifed ) + { + if( !OverWrite ) emit cutAvailable( BufferRanges->hasSelection() ); + emit copyAvailable( BufferRanges->hasSelection() ); + emit selectionChanged( -1, -1 ); + } +} + + +void KHexEdit::showBufferColumns( int CCs ) +{ + int Columns = visibleBufferColumns(); + + // no changes or no column selected? + if( CCs == Columns || !(CCs&( ValueColumnId | CharColumnId )) ) + return; + + valueColumn().setVisible( ValueColumnId & CCs ); + charColumn().setVisible( CharColumnId & CCs ); + SecondBorderColumn->setVisible( CCs == (ValueColumnId|CharColumnId) ); + + // active column not visible anymore? + if( !activeColumn().isVisible() ) + { + KBufferColumn *H = ActiveColumn; + ActiveColumn = InactiveColumn; + InactiveColumn = H; + Controller = ReadOnly ? (KController*)Navigator : + cursorColumn() == CharColumnId ? (KController*)CharEditor : (KController*)ValueEditor; + } + + updateViewByWidth(); +} + + +void KHexEdit::setCursorColumn( KBufferColumnId CC ) +{ + // no changes or not visible? + if( CC == cursorColumn() + || (CC == ValueColumnId && !valueColumn().isVisible()) + || (CC == CharColumnId && !charColumn().isVisible()) ) + return; + + pauseCursor( true ); + + if( CC == ValueColumnId ) + { + ActiveColumn = &valueColumn(); + InactiveColumn = &charColumn(); + } + else + { + ActiveColumn = &charColumn(); + InactiveColumn = &valueColumn(); + } + Controller = ReadOnly ? (KController*)Navigator : + cursorColumn() == CharColumnId ? (KController*)CharEditor : (KController*)ValueEditor; + + ensureCursorVisible(); + unpauseCursor(); +} + + +void KHexEdit::placeCursor( const QPoint &Point ) +{ + resetInputContext(); + + // switch active column if needed + if( charColumn().isVisible() && Point.x() >= charColumn().x() ) + { + ActiveColumn = &charColumn(); + InactiveColumn = &valueColumn(); + } + else + { + ActiveColumn = &valueColumn(); + InactiveColumn = &charColumn(); + } + Controller = ReadOnly ? (KController*)Navigator : + cursorColumn() == CharColumnId ? (KController*)CharEditor : (KController*)ValueEditor; + + // get coord of click and whether this click was closer to the end of the pos + KBufferCoord C( activeColumn().magPosOfX(Point.x()), lineAt(Point.y()) ); + + BufferCursor->gotoCCoord( C ); +} + + +int KHexEdit::indexByPoint( const QPoint &Point ) const +{ + const KBufferColumn *C; + if( charColumn().isVisible() && Point.x() >= charColumn().x() ) + C = &charColumn(); + else + C = &valueColumn(); + + KBufferCoord Coord( C->posOfX(Point.x()), lineAt(Point.y()) ); + + return BufferLayout->indexAtCCoord( Coord ); +} + + +void KHexEdit::showEvent( QShowEvent *e ) +{ + KColumnsView::showEvent( e ); + BufferLayout->setNoOfLinesPerPage( noOfLinesPerPage() ); +} + + +bool KHexEdit::eventFilter( QObject *O, QEvent *E ) +{ + if( O == this || O == viewport() ) + { + if( E->type() == QEvent::FocusIn ) + { + startCursor(); + } + else if( E->type() == QEvent::FocusOut ) + { + stopCursor(); + } + } + +// if( O == this && E->type() == QEvent::PaletteChange ) +// { +// QColor old( viewport()->colorGroup().color(QColorGroup::Text) ); +// +// if( old != colorGroup().color(QColorGroup::Text) ) +// { +// QColor c( colorGroup().color(QColorGroup::Text) ); +// doc->setMinimumWidth( -1 ); +// doc->setDefaultFormat( doc->formatCollection()->defaultFormat()->font(), c ); +// lastFormatted = doc->firstParagraph(); +// formatMore(); +// repaintChanged(); +// } +// } + + return QScrollView::eventFilter( O, E ); +} + + +void KHexEdit::blinkCursor() +{ + // skip the cursor drawing? + if( CursorPaused || ValueEditor->isInEditMode() ) + return; + + // switch the cursor state + paintActiveCursor( !BlinkCursorVisible ); +} + + +void KHexEdit::startCursor() +{ + CursorPaused = false; + + updateCursor(); + + CursorBlinkTimer->start( QApplication::cursorFlashTime()/2 ); +} + + +void KHexEdit::unpauseCursor() +{ + CursorPaused = false; + + if( CursorBlinkTimer->isActive() ) + updateCursor(); +} + + +void KHexEdit::updateCursor() +{ + createCursorPixmaps(); + + paintActiveCursor( true ); + paintInactiveCursor( true ); +} + + +void KHexEdit::stopCursor() +{ + CursorBlinkTimer->stop(); + + pauseCursor(); +} + + +void KHexEdit::pauseCursor( bool LeaveEdit ) +{ + paintActiveCursor( false ); + paintInactiveCursor( false ); + + if( LeaveEdit ) + ValueEditor->InEditMode = false; + CursorPaused = true; +} + + +void KHexEdit::createCursorPixmaps() +{ + // create CursorPixmaps + CursorPixmaps->setSize( activeColumn().byteWidth(), LineHeight ); + + int Index = BufferCursor->validIndex(); + + QPainter Paint; + Paint.begin( &CursorPixmaps->offPixmap(), this ); + activeColumn().paintByte( &Paint, Index ); + Paint.end(); + + Paint.begin( &CursorPixmaps->onPixmap(), this ); + activeColumn().paintCursor( &Paint, Index ); + Paint.end(); + + // calculat the shape + KPixelX CursorX; + KPixelX CursorW; + if( BufferCursor->isBehind() ) + { + CursorX = QMAX( 0, CursorPixmaps->onPixmap().width()-InsertCursorWidth ); + CursorW = InsertCursorWidth; + } + else + { + CursorX = 0; + CursorW = OverWrite ? -1 : InsertCursorWidth; + } + CursorPixmaps->setShape( CursorX, CursorW ); +} + + +void KHexEdit::pointPainterToCursor( QPainter &Painter, const KBufferColumn &Column ) const +{ + int x = Column.xOfPos( BufferCursor->pos() ) - contentsX(); + int y = LineHeight * BufferCursor->line() - contentsY(); + + Painter.begin( viewport() ); + Painter.translate( x, y ); +} + + +void KHexEdit::paintActiveCursor( bool CursorOn ) +{ + // any reason to skip the cursor drawing? + if( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() + || (CursorOn && !hasFocus() && !viewport()->hasFocus() && !InDnD ) ) + return; + + QPainter Painter; + pointPainterToCursor( Painter, activeColumn() ); + + // paint edited byte? + if( ValueEditor->isInEditMode() ) + { + int Index = BufferCursor->index(); + + if( CursorOn ) + valueColumn().paintEditedByte( &Painter, ValueEditor->EditValue, ValueEditor->ByteBuffer ); + else + valueColumn().paintByte( &Painter, Index ); + } + else + { + + Painter.drawPixmap( CursorPixmaps->cursorX(), 0, + CursorOn?CursorPixmaps->onPixmap():CursorPixmaps->offPixmap(), + CursorPixmaps->cursorX(),0,CursorPixmaps->cursorW(),-1 ); + // store state + BlinkCursorVisible = CursorOn; + } +} + + +void KHexEdit::paintInactiveCursor( bool CursorOn ) +{ + // any reason to skip the cursor drawing? + if( !isUpdatesEnabled() + || !viewport()->isUpdatesEnabled() + || !inactiveColumn().isVisible() + || (CursorOn && !hasFocus() && !viewport()->hasFocus() && !InDnD) ) + return; + + int Index = BufferCursor->validIndex(); + + QPainter Painter; + pointPainterToCursor( Painter, inactiveColumn() ); + if( CursorOn ) + { + KBufferColumn::KFrameStyle Style = + BufferCursor->isBehind() ? KBufferColumn::Right : + (OverWrite||ValueEditor->isInEditMode()) ? KBufferColumn::Frame : + KBufferColumn::Left; + inactiveColumn().paintFramedByte( &Painter, Index, Style ); + } + else + inactiveColumn().paintByte( &Painter, Index ); +} + + +void KHexEdit::drawContents( QPainter *P, int cx, int cy, int cw, int ch ) +{ + KColumnsView::drawContents( P, cx, cy, cw, ch ); + // TODO: update non blinking cursors. Should this perhaps be done in the buffercolumn? + // Then it needs to know about inactive, insideByte and the like... well... + // perhaps subclassing the buffer columns even more, to KCharColumn and KValueColumn? + + if( !CursorPaused && visibleLines(KPixelYs(cy,ch,false)).includes(BufferCursor->line()) ) + { + paintActiveCursor( true ); + paintInactiveCursor( true ); + } +} + +void KHexEdit::updateColumn( KColumn &Column ) +{ + //kdDebug(1501) << "updateColumn\n"; + if( Column.isVisible() ) + updateContents( Column.x(), 0, Column.width(), totalHeight() ); +} + + +void KHexEdit::keyPressEvent( QKeyEvent *KeyEvent ) +{ + if( !Controller->handleKeyPress( KeyEvent ) ) + KeyEvent->ignore(); +} + + +void KHexEdit::repaintChanged() +{ + if( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() || !BufferRanges->isModified() ) + return; + + // TODO: we do this only to let the scrollview handle new or removed lines. overlaps with repaintRange + resizeContents( totalWidth(), totalHeight() ); + + KPixelXs Xs( contentsX(), visibleWidth(), true ); + + // collect affected buffer columns + QPtrList RepaintColumns; + + KBufferColumn *C = ValueColumn; + while( true ) + { + if( C->isVisible() && C->overlaps(Xs) ) + { + RepaintColumns.append( C ); + C->preparePainting( Xs ); + } + + if( C == CharColumn ) + break; + C = CharColumn; + } + + // any colums to paint? + if( RepaintColumns.count() > 0 ) + { + KPixelYs Ys( contentsY(), visibleHeight(), true ); + + // calculate affected lines/indizes + KSection FullPositions( 0, BufferLayout->noOfBytesPerLine()-1 ); + KCoordRange VisibleRange( FullPositions, visibleLines(Ys) ); + + KCoordRange ChangedRange; + // as there might be multiple selections on this line redo until no more is changed + while( hasChanged(VisibleRange,&ChangedRange) ) + { +// std::cout << " changed->"<noOfLines() + + BufferRanges->resetChangedRanges(); +} + + +void KHexEdit::paintLine( KBufferColumn *C, int Line, KSection Positions ) +{ + Positions.restrictTo( C->visiblePositions() ); + + // nothing to paint? + if( !Positions.isValid() ) + return; +// std::cout << " paintLine->"<wideXPixelsOfPos( Positions ); + + KPixelY cy = Line * LineHeight; + + // to avoid flickers we first paint to the linebuffer + QPainter Paint; + Paint.begin( &LineBuffer, this ); + + Paint.translate( C->x(), 0 ); + C->paintPositions( &Paint, Line, Positions ); + Paint.translate( -C->x(), 0 ); + + if( HorizontalGrid && XPixels.start() < TotalWidth ) + Paint.drawLine( XPixels.start(), LineHeight-1, XPixels.width(), LineHeight-1 ); // TODO: use a additional TotalHeight? + + Paint.end(); + // copy to screen + bitBlt( viewport(), XPixels.start() - contentsX(), cy - contentsY(), + &LineBuffer, XPixels.start(), 0, XPixels.width(), LineHeight ); +} + + +bool KHexEdit::hasChanged( const KCoordRange &VisibleRange, KCoordRange *ChangedRange ) const +{ + if( !BufferRanges->overlapsChanges(VisibleRange,ChangedRange) ) + return false; + + ChangedRange->restrictTo( VisibleRange ); + return true; +} + + +void KHexEdit::ensureCursorVisible() +{ +// // Not visible or the user is draging the window, so don't position to caret yet +// if ( !isVisible() || isHorizontalSliderPressed() || isVerticalSliderPressed() ) +// { +// d->ensureCursorVisibleInShowEvent = true; +// return; +// } + + KPixelX x = activeColumn().xOfPos( BufferCursor->pos() )+ activeColumn().byteWidth()/2; + KPixelY y = LineHeight * BufferCursor->line() + LineHeight/2; + int xMargin = activeColumn().byteWidth()/2 + 1; + int yMargin = LineHeight/2 + 1; + ensureVisible( x, y, xMargin, yMargin ); +} + + + +void KHexEdit::contentsMousePressEvent( QMouseEvent *e ) +{ +// clearUndoRedo(); + pauseCursor( true ); + + // care about a left button press? + if( e->button() == LeftButton ) + { + MousePressed = true; + + // select whole line? + if( TrippleClickTimer->isActive() + && (e->globalPos()-DoubleClickPoint).manhattanLength() < QApplication::startDragDistance() ) + { + BufferRanges->setSelectionStart( BufferLayout->indexAtLineStart(DoubleClickLine) ); + BufferCursor->gotoLineEnd(); + BufferRanges->setSelectionEnd( BufferCursor->realIndex() ); + repaintChanged(); + + unpauseCursor(); + return; + } + + QPoint MousePoint = e->pos(); + placeCursor( MousePoint ); + ensureCursorVisible(); + + // start of a drag perhaps? + if( BufferRanges->selectionIncludes(BufferCursor->index()) ) + { + DragStartPossible = true; + DragStartTimer->start( QApplication::startDragTime(), true ); + DragStartPoint = MousePoint; + + unpauseCursor(); + return; + } + + int RealIndex = BufferCursor->realIndex(); + if( BufferRanges->selectionStarted() ) + { + if( e->state() & ShiftButton ) + BufferRanges->setSelectionEnd( RealIndex ); + else + { + BufferRanges->removeSelection(); + BufferRanges->setSelectionStart( RealIndex ); + } + } + else // start of a new selection possible + { + BufferRanges->setSelectionStart( RealIndex ); + + if( !isReadOnly() && (e->state()&ShiftButton) ) // TODO: why only for readwrite? + BufferRanges->setSelectionEnd( RealIndex ); + } + + BufferRanges->removeFurtherSelections(); + } + else if( e->button() == MidButton ) + BufferRanges->removeSelection(); + + if( BufferRanges->isModified() ) + { + repaintChanged(); + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); + } + + unpauseCursor(); +} + + +void KHexEdit::contentsMouseMoveEvent( QMouseEvent *e ) +{ + if( MousePressed ) + { + if( DragStartPossible ) + { + DragStartTimer->stop(); + // moved enough for a drag? + if( (e->pos()-DragStartPoint).manhattanLength() > QApplication::startDragDistance() ) + startDrag(); + if( !isReadOnly() ) + viewport()->setCursor( ibeamCursor ); + return; + } + // selecting + QPoint MousePoint = e->pos(); + handleMouseMove( MousePoint ); + } + else if( !isReadOnly() ) + { + // visual feedback for possible dragging + bool InSelection = BufferRanges->hasSelection() && BufferRanges->selectionIncludes( indexByPoint(e->pos()) ); + viewport()->setCursor( InSelection?arrowCursor:ibeamCursor ); + } +} + + +void KHexEdit::contentsMouseReleaseEvent( QMouseEvent *e ) +{ + // this is not the release of a doubleclick so we need to process it? + if( !InDoubleClick ) + { + int Line = lineAt( e->pos().y() ); + int Pos = activeColumn().posOfX( e->pos().x() ); // TODO: can we be sure here about the active column? + int Index = BufferLayout->indexAtCCoord( KBufferCoord(Pos,Line) ); // TODO: can this be another index than the one of the cursor??? + emit clicked( Index ); + } + + if( MousePressed ) + { + MousePressed = false; + + if( ScrollTimer->isActive() ) + ScrollTimer->stop(); + + // was only click inside selection, nothing dragged? + if( DragStartPossible ) + { + selectAll( false ); + DragStartTimer->stop(); + DragStartPossible = false; + + unpauseCursor(); + } + // was end of selection operation? + else if( BufferRanges->hasSelection() ) + { + if( QApplication::clipboard()->supportsSelection() ) + { + ClipboardMode = QClipboard::Selection; + disconnect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0); + + copy(); + + connect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, SLOT(clipboardChanged()) ); + ClipboardMode = QClipboard::Clipboard; + } + } + } + // middle mouse button paste? + else if( e->button() == MidButton && !isReadOnly() ) + { + pauseCursor(); + + placeCursor( e->pos() ); + + // replace no selection? + if( BufferRanges->hasSelection() && !BufferRanges->selectionIncludes(BufferCursor->index()) ) + BufferRanges->removeSelection(); + + ClipboardMode = QClipboard::Selection; + paste(); + ClipboardMode = QClipboard::Clipboard; + + // ensure selection changes to be drawn TODO: create a insert/pasteAtCursor that leaves out drawing + repaintChanged(); + + ensureCursorVisible(); + unpauseCursor(); + } + + InDoubleClick = false; + + if( BufferRanges->selectionJustStarted() ) + BufferRanges->removeSelection(); + + emit cursorPositionChanged( BufferCursor->index() ); + + if( !OverWrite ) emit cutAvailable( BufferRanges->hasSelection() ); + emit copyAvailable( BufferRanges->hasSelection() ); + KSection Selection = BufferRanges->selection(); + emit selectionChanged( Selection.start(), Selection.end() ); +} + + +// gets called after press and release instead of a plain press event (?) +void KHexEdit::contentsMouseDoubleClickEvent( QMouseEvent *e ) +{ + // we are only interested in LMB doubleclicks + if( e->button() != Qt::LeftButton ) + { + e->ignore(); + return; + } + + DoubleClickLine = BufferCursor->line(); + + int Index = BufferCursor->validIndex(); + + if( ActiveColumn == &charColumn() ) + { + selectWord( Index ); + + // as we already have a doubleclick maybe it is a tripple click + TrippleClickTimer->start( qApp->doubleClickInterval(), true ); + DoubleClickPoint = e->globalPos(); + } +// else +// ValueEditor->goInsideByte(); TODO: make this possible again + + InDoubleClick = true; // + MousePressed = true; + + emit doubleClicked( Index ); +} + + +void KHexEdit::autoScrollTimerDone() +{ + if( MousePressed ) + handleMouseMove( viewportToContents(viewport()->mapFromGlobal( QCursor::pos() )) ); +} + + +void KHexEdit::handleMouseMove( const QPoint& Point ) // handles the move of the mouse with pressed buttons +{ + // no scrolltimer and outside of viewport? + if( !ScrollTimer->isActive() && Point.y() < contentsY() || Point.y() > contentsY() + visibleHeight() ) + ScrollTimer->start( DefaultScrollTimerPeriod, false ); + // scrolltimer but inside of viewport? + else if( ScrollTimer->isActive() && Point.y() >= contentsY() && Point.y() <= contentsY() + visibleHeight() ) + ScrollTimer->stop(); + + pauseCursor(); + + placeCursor( Point ); + ensureCursorVisible(); + + // do wordwise selection? + if( InDoubleClick && BufferRanges->hasFirstWordSelection() ) + { + int NewIndex = BufferCursor->realIndex(); + KSection FirstWordSelection = BufferRanges->firstWordSelection(); + KWordBufferService WBS( DataBuffer, Codec ); + // are we before the selection? + if( NewIndex < FirstWordSelection.start() ) + { + BufferRanges->ensureWordSelectionForward( false ); + NewIndex = WBS.indexOfLeftWordSelect( NewIndex ); + } + // or behind? + else if( NewIndex > FirstWordSelection.end() ) + { + BufferRanges->ensureWordSelectionForward( true ); + NewIndex = WBS.indexOfRightWordSelect( NewIndex ); + } + // or inside? + else + { + BufferRanges->ensureWordSelectionForward( true ); + NewIndex = FirstWordSelection.end()+1; + } + + BufferCursor->gotoIndex( NewIndex ); + } + + if( BufferRanges->selectionStarted() ) + BufferRanges->setSelectionEnd( BufferCursor->realIndex() ); + + repaintChanged(); + + unpauseCursor(); +} + + +void KHexEdit::startDrag() +{ + // reset states + MousePressed = false; + InDoubleClick = false; + DragStartPossible = false; + + // create data + QDragObject *Drag = dragObject( viewport() ); + if( !Drag ) + return; + + // will we only copy the data? + if( isReadOnly() || OverWrite ) + Drag->dragCopy(); + // or is this left to the user and he choose to move? + else if( Drag->drag() ) + // Not inside this widget itself? + if( QDragObject::target() != this && QDragObject::target() != viewport() ) + removeSelectedData(); +} + + +void KHexEdit::contentsDragEnterEvent( QDragEnterEvent *e ) +{ + // interesting for this widget? + if( isReadOnly() || !KBufferDrag::canDecode(e) ) + { + e->ignore(); + return; + } + + e->acceptAction(); + InDnD = true; +} + + +void KHexEdit::contentsDragMoveEvent( QDragMoveEvent *e ) +{ + // is this content still interesting for us? + if( isReadOnly() || !KBufferDrag::canDecode(e) ) + { + e->ignore(); + return; + } + + // let text cursor follow mouse + pauseCursor( true ); + placeCursor( e->pos() ); + unpauseCursor(); + + e->acceptAction(); +} + + +void KHexEdit::contentsDragLeaveEvent( QDragLeaveEvent * ) +{ + // bye... and thanks for all the cursor movement... + InDnD = false; +} + + + +void KHexEdit::contentsDropEvent( QDropEvent *e ) +{ + // after drag enter and move check one more time + if( isReadOnly() ) + return; + + // leave state + InDnD = false; + e->acceptAction(); + + if( !KBufferDrag::canDecode(e) ) //TODO: why do we acept the action still? + return; + + // is this an internal dnd? + if( e->source() == this || e->source() == viewport() ) + handleInternalDrag( e ); + else + { + //BufferRanges->removeSelection(); + pasteFromSource( e ); + } +} + + +void KHexEdit::handleInternalDrag( QDropEvent *e ) +{ + KSection ChangedRange; + + // stop ui + pauseCursor(); + + // get drag origin + KSection Selection = BufferRanges->selection(); + int InsertIndex = BufferCursor->realIndex(); + + // is this a move? + if( e->action() == QDropEvent::Move ) + { + // ignore the copy hold in the event but only move + int NewIndex = DataBuffer->move( InsertIndex, Selection ); + if( NewIndex != Selection.start() ) + { + BufferCursor->gotoCIndex( NewIndex+Selection.width() ); + ChangedRange.set( QMIN(InsertIndex,Selection.start()), QMAX(InsertIndex,Selection.end()) ); + } + } + // is a copy + else + { + // get data + QByteArray Data; + if( KBufferDrag::decode(e,Data) && !Data.isEmpty() ) + { + if( OverWrite ) + { + if( !BufferCursor->isBehind() ) + { + ChangedRange.setByWidth( InsertIndex, Data.size() ); + ChangedRange.restrictEndTo( BufferLayout->length()-1 ); + if( ChangedRange.isValid() ) + { + int NoOfReplaced = DataBuffer->replace( ChangedRange, Data.data(), ChangedRange.width() ); + BufferCursor->gotoNextByte( NoOfReplaced ); + } + } + } + else + { + int NoOfInserted = DataBuffer->insert( InsertIndex, Data.data(), Data.size() ); + updateLength(); + if( NoOfInserted > 0 ) + { + BufferCursor->gotoCIndex( InsertIndex + NoOfInserted ); + ChangedRange.set( InsertIndex, DataBuffer->size()-1 ); + } + } + } + } + BufferRanges->addChangedRange( ChangedRange ); + BufferRanges->removeSelection(); + + repaintChanged(); + ensureCursorVisible(); + + // open ui + unpauseCursor(); + + // emit appropriate signals. + emit selectionChanged( -1, -1 ); + if( ChangedRange.isValid() ) emit bufferChanged( ChangedRange.start(), ChangedRange.end() ); + emit cursorPositionChanged( BufferCursor->index() ); +} + + +void KHexEdit::contentsWheelEvent( QWheelEvent *e ) +{ + if( isReadOnly() ) + { + if( e->state() & ControlButton ) + { + if( e->delta() > 0 ) + zoomOut(); + else if( e->delta() < 0 ) + zoomIn(); + return; + } + } + QScrollView::contentsWheelEvent( e ); +} + + +#if 0 +void KHexEdit::contentsContextMenuEvent( QContextMenuEvent *e ) +{ +// clearUndoRedo(); + MousePressed = false; + + e->accept(); + + QPopupMenu *PopupMenu = createPopupMenu( e->pos() ); + if( !PopupMenu ) + PopupMenu = createPopupMenu(); + if( !PopupMenu ) + return; + int r = PopupMenu->exec( e->globalPos() ); + delete PopupMenu; + + if ( r == d->id[ IdClear ] ) + clear(); + else if ( r == d->id[ IdSelectAll ] ) + { + selectAll(); + // if the clipboard support selections, put the newly selected text into the clipboard + if( QApplication::clipboard()->supportsSelection() ) + { + ClipboardMode = QClipboard::Selection; + disconnect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0); + + copy(); + + connect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, SLOT(clipboardChanged()) ); + ClipboardMode = QClipboard::Clipboard; + } + } + else if( r == d->id[IdUndo] ) + undo(); + else if( r == d->id[IdRedo] ) + redo(); + else if( r == d->id[IdCut] ) + cut(); + else if( r == d->id[IdCopy] ) + copy(); + else if( r == d->id[IdPaste] ) + paste(); +} +#endif + +#include "khexedit.moc" diff --git a/khexedit/lib/khexedit.h b/khexedit/lib/khexedit.h new file mode 100644 index 0000000..66059c8 --- /dev/null +++ b/khexedit/lib/khexedit.h @@ -0,0 +1,562 @@ +/*************************************************************************** + khexedit.h - description + ------------------- + begin : Die Mai 13 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KHEXEDIT_H +#define KHE_KHEXEDIT_H + +// qt specific +#include +// lib specific +// #include "khe.h" +#include "khexedit_export.h" +#include "kcolumnsview.h" + +class QTimer; + +namespace KHE +{ + +class KCoordRange; + +class KDataBuffer; + +class KCharColumn; +class KValueColumn; +class KBufferColumn; +class KOffsetColumn; +class KBorderColumn; + +class KBufferCursor; +class KBufferLayout; +class KBufferRanges; + +class KController; +class KTabController; +class KNavigator; +class KValueEditor; +class KCharEditor; + +class KBufferDrag; + +class KCursor; +class KCharCodec; + +class KHexEditPrivate; + + +/** the main widget + * + * The functions split up in helper functions and those that are complete. + * + * Complete functions can be called from the outside and leave the widget in + * a consistent state. They care for exceptions so one can safely call them in all + * situations (like empty buffer, cursor behind end etc.) + * + * Helper functions do only partial tasks and need to be completed. They often do not + * check for exceptions so one has to care for this. + * + *@author Friedrich W. H. Kossebau + */ + +class KHEXEDIT_EXPORT KHexEdit : public KColumnsView +{ + friend class KTabController; + friend class KNavigator; + friend class KEditor; + friend class KValueEditor; + friend class KCharEditor; + + Q_OBJECT + Q_ENUMS( KResizeStyle KCoding ) + Q_PROPERTY( bool OverwriteMode READ isOverwriteMode WRITE setOverwriteMode ) + Q_PROPERTY( bool OverwriteOnly READ isOverwriteOnly WRITE setOverwriteOnly ) + Q_PROPERTY( bool Modified READ isModified WRITE setModified DESIGNABLE false ) + Q_PROPERTY( bool ReadOnly READ isReadOnly WRITE setReadOnly ) + + Q_PROPERTY( int NoOfBytesPerLine READ noOfBytesPerLine WRITE setNoOfBytesPerLine ) + Q_PROPERTY( bool TabChangesFocus READ tabChangesFocus WRITE setTabChangesFocus ) + + //Q_PROPERTY( bool hasSelectedData READ hasSelectedData ) + //Q_PROPERTY( QByteArray SelectedData READ selectedData ) + Q_PROPERTY( KResizeStyle ResizeStyle READ resizeStyle WRITE setResizeStyle ) + Q_PROPERTY( int StartOffset READ startOffset WRITE setStartOffset ) + Q_PROPERTY( int FirstLineOffset READ firstLineOffset WRITE setFirstLineOffset ) + //_PROPERTY( int undoDepth READ undoDepth WRITE setUndoDepth ) + //_PROPERTY( bool undoRedoEnabled READ isUndoRedoEnabled WRITE setUndoRedoEnabled ) + // value column + Q_PROPERTY( KCoding Coding READ coding WRITE setCoding ) + Q_PROPERTY( int ByteSpacingWidth READ byteSpacingWidth WRITE setByteSpacingWidth ) + Q_PROPERTY( int NoOfGroupedBytes READ noOfGroupedBytes WRITE setNoOfGroupedBytes ) + Q_PROPERTY( int GroupSpacingWidth READ groupSpacingWidth WRITE setGroupSpacingWidth ) + Q_PROPERTY( int BinaryGapWidth READ binaryGapWidth WRITE setBinaryGapWidth ) + // char column + Q_PROPERTY( bool ShowUnprintable READ showUnprintable WRITE setShowUnprintable ) + Q_PROPERTY( QChar SubstituteChar READ substituteChar WRITE setSubstituteChar ) + + public: + enum KResizeStyle { NoResize=0, LockGrouping=1, FullSizeUsage=2, MaxResizeStyleId=0xFF }; + enum KCoding { HexadecimalCoding=0, DecimalCoding=1, OctalCoding=2, BinaryCoding=3, MaxCodingId=0xFFFF }; + enum KEncoding { LocalEncoding=0, ISO8859_1Encoding=1, EBCDIC1047Encoding=2, + StartOfOwnEncoding=0x8000, MaxEncodingId=0xFFFF }; + + enum KBufferColumnId { ValueColumnId=1, CharColumnId=2 }; + + + public: + KHexEdit( KDataBuffer *Buffer = 0, QWidget *Parent = 0, const char *Name = 0, WFlags F = 0 ); + virtual ~KHexEdit(); + + + public: // KColumnsView API + virtual void drawContents( QPainter *p, int cx, int cy, int cw, int ch ); + + public: // QWidget API +// void focusInEvent( QFocusEvent *FocusEvent ); // TODO: why don't these work? +// void focusOutEvent( QFocusEvent *FocusEvent ); + virtual bool eventFilter( QObject *O, QEvent *E ); + + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + + + public: // value access + /** returns the index of the cursor position */ + int cursorPosition() const; + /***/ + bool isCursorBehind() const; + KBufferColumnId cursorColumn() const; + + bool isOverwriteMode() const; + bool isOverwriteOnly() const; + bool isReadOnly() const; + bool isModified() const; + + bool tabChangesFocus() const; + + KResizeStyle resizeStyle() const; + int noOfBytesPerLine() const; + int startOffset() const; + int firstLineOffset() const; + + bool offsetColumnVisible() const; + int visibleBufferColumns() const; + + // value column + KCoding coding() const; + int/*KPixelX*/ byteSpacingWidth() const; + int noOfGroupedBytes() const; + int/*KPixelX*/ groupSpacingWidth() const; + int/*KPixelX*/ binaryGapWidth() const; + + // char column + /** reports if "unprintable" chars (value<32) are displayed in the char column + * with their original character. Default is false + * @return @c true if original chars are displayed, otherwise @c false + */ + bool showUnprintable() const; + /** gives the used substitute character for "unprintable" chars, default is '.' + * @return substitute character + */ + QChar substituteChar() const; + /** returns the actually used undefined character for "undefined" chars, default is '?' */ + QChar undefinedChar() const; + /** + * @return encoding used in the char column + */ + KEncoding encoding() const; + /** + * @return name of the encoding used in the char column + */ + const QString &encodingName() const; + + public: // logic value service + /** calculates the number of bytes per line that fit into a widget with the given size + * tests whether a vertical scroll bar is needed at all or not due to the given width + * takes the frame width into account + * @param TestSize Size the widget might have + * @return number of bytes per line that fit into a widget with the given size + */ + int fittingBytesPerLine( const QSize &TestSize ) const; + /** detects the index of the byte at the given point + * @param Point in viewport coordinate system + * @return index of the byte that covers the point + */ + int indexByPoint(const QPoint &Point ) const; + + public: + /** returns true if there is a selected range in the array */ + bool hasSelectedData() const; + /** + * @return deep copy of the selected data + */ + QByteArray selectedData() const; + KSection selection() const; + + public: // modification access + /** puts the cursor to the position of index, handles all drawing + * @param Index + */ + void setCursorPosition( int Index, bool Behind=false ); + /** puts the cursor in the column at the pos of Point (in absolute coord), does not handle the drawing */ + void placeCursor( const QPoint &Point ); + /***/ + void setCursorColumn( KBufferColumnId ); +// void repaintByte( int row, int column, bool Erase = true ); +// void updateByte( int row, int column ); +// void ensureByteVisible( int row, int column ); + + public slots: + /** */ + void setDataBuffer( KDataBuffer *B ); + + /** switches the Offset column on/off */ + void toggleOffsetColumn( bool Visible ); + /** */ + void showBufferColumns( int Columns ); + /** scrolls the view as much as needed to have the cursor fully visible */ + void ensureCursorVisible(); + + // setting parameters + /** sets the resizestyle for the value column. Default is KHE::FullSizeUsage */ + void setResizeStyle( KResizeStyle Style ); + /** sets whether the widget is readonly or not, Default is true. + * If the databuffer which is worked on can't be written the widget stays readonly + */ + virtual void setReadOnly( bool b ); + /** sets whether the widget is overwriteonly or not. Default is false. */ + virtual void setOverwriteOnly( bool b ); + /** sets whether the widget is in overwrite mode or not. Default is true. */ + virtual void setOverwriteMode( bool b ); + /** sets whether the data should be treated modified or not */ + virtual void setModified( bool b ); + /** sets whether on a tab key there should be switched from the char column back to the value column + * or be switched to the next focusable widget. Default is false + */ + virtual void setTabChangesFocus( bool b = true ); + // + /** sets the number of bytes per line, switching the resize style to KHE::NoResize */ + virtual void setNoOfBytesPerLine( int NoCpL ); + /** sets absolut offset of the data */ + void setStartOffset( int SO ); + /** sets offset of the char in the upper left corner */ + void setFirstLineOffset( int FLO ); + // value column parameters + /** sets the spacing between the bytes in the value column + * @param BSW spacing between the bytes in pixels + * default is 3 + */ + void setByteSpacingWidth( int/*KPixelX*/ BSW ) ; + /** sets the number of grouped bytes in the value column + * @param NoGB numbers of grouped bytes, 0 means no grouping + * default is 4 + */ + void setNoOfGroupedBytes( int NoGB ); + /** sets the spacing between the groups of bytes in the value column + * @param GSW spacing between the groups in pixels + * default is 9 + */ + void setGroupSpacingWidth( int/*KPixelX*/ GSW ); + /** sets the spacing in the middle of a binary byte in the value column + * @param BinaryGapW spacing in the middle of a binary in pixels + * returns true if there was a change + */ + void setBinaryGapWidth( int BGW ); + /** sets the spacing in the value column + * @param ByteSpacingWidth spacing between the bytes in pixels + * @param NoOfGroupedBytes numbers of grouped bytes, 0 means no grouping + * @param GroupSpacingWidth spacing between the groups in pixels + * Default is 4 for NoOfGroupedBytes + */ + void setBufferSpacing( KPixelX ByteSpacingWidth, int NoOfGroupedBytes = 0, KPixelX GroupSpacingWidth = 0 ); + /** sets the format of the value column. Default is KHE::HexadecimalCoding */ + void setCoding( KCoding C ); + // char column parameters + /** sets whether "unprintable" chars (>32) should be displayed in the char column + * with their corresponding character. + * @param SU + * returns true if there was a change + */ + void setShowUnprintable( bool SU = true ); + /** sets the substitute character for "unprintable" chars + * returns true if there was a change + */ + void setSubstituteChar( QChar SC ); + /** sets the undefined character for "undefined" chars + * returns true if there was a change + */ + void setUndefinedChar( QChar UC ); + /** sets the encoding of the char column. Default is KHE::LocalEncoding. + * If the encoding is not available the format will not be changed. */ + void setEncoding( KEncoding C ); + /** sets the encoding of the char column. Default is KHE::LocalEncoding. + * If the encoding is not available the format will not be changed. + * @param Encoding name of the encoding + */ + void setEncoding( const QString& Encoding ); + + // interaction + /** de-/selects all data */ + void selectAll( bool select ); + /** de-/selects all data */ + void select( KSection S ); + /** selects word at index, returns true if there is one */ + bool selectWord( /*unsigned*/ int Index /*, Chartype*/ ); + /** removes the selected data, takes care of the cursor */ + virtual void removeSelectedData(); + /** inserts */ + virtual void insert( const QByteArray &D ); + + // clipboard interaction + virtual void copy(); + virtual void cut(); + virtual void paste(); + + // zooming + virtual void zoomIn( int PointInc ); + virtual void zoomIn(); + virtual void zoomOut( int PointInc ); + virtual void zoomOut(); + virtual void zoomTo( int PointSize ); + virtual void unZoom(); + + // cursor control + /** we have focus again, start the timer */ + virtual void startCursor(); + /** we lost focus, stop the timer */ + virtual void stopCursor(); + /** simply pauses any blinking, i.e. ignores any calls to blinkCursor */ + virtual void pauseCursor( bool LeaveEdit = false ); + /** undoes pauseCursor */ + virtual void unpauseCursor(); + + + signals: + /** Index of the byte that was clicked */ + void clicked( int Index ); + /** Index of the byte that was double clicked */ + void doubleClicked( int Index ); + + void cursorPositionChanged( int Index ); + /** selection has changed */ + void selectionChanged( int StartIndex, int EndIndex ); + /** there is a cut available or not */ + void cutAvailable( bool Really ); + /** there is a copy available or not */ + void copyAvailable( bool Really ); + /** there has been a change to the buffer */ + void bufferChanged( int StartIndex, int EndIndex ); + + + protected: // QWidget API + virtual void keyPressEvent( QKeyEvent *KeyEvent ); + virtual void resizeEvent( QResizeEvent *ResizeEvent ); + virtual void showEvent( QShowEvent *e ); + + protected: // QScrollView API + virtual void contentsMousePressEvent( QMouseEvent *e ); + virtual void contentsMouseReleaseEvent( QMouseEvent * e ); + virtual void contentsMouseMoveEvent( QMouseEvent *e ); + virtual void contentsMouseDoubleClickEvent( QMouseEvent * e ); + virtual void contentsDragEnterEvent( QDragEnterEvent *e ); + virtual void contentsDragMoveEvent( QDragMoveEvent *e ); + virtual void contentsDragLeaveEvent( QDragLeaveEvent * ); + virtual void contentsDropEvent( QDropEvent *e ); + virtual void contentsWheelEvent( QWheelEvent *e ); +// virtual void contentsContextMenuEvent( QContextMenuEvent *e ); + + protected: // KColumnsView API + virtual void setNoOfLines( int NewNoOfLines ); + + + protected: // element accessor functions + KValueColumn& valueColumn(); + KCharColumn& charColumn(); + KBufferColumn& activeColumn(); + KBufferColumn& inactiveColumn(); + const KValueColumn& valueColumn() const; + const KCharColumn& charColumn() const; + const KBufferColumn& activeColumn() const; + const KBufferColumn& inactiveColumn() const; + + protected: // atomic ui operations + /** handles screen update in case of a change to any of the width sizes + */ + void updateViewByWidth(); + /** repaints all the parts that are signed as changed */ + void repaintChanged(); + + protected: // drawing related operations + /** recreates the cursor pixmaps and paints active and inactive cursors if doable */ + void updateCursor(); + void createCursorPixmaps(); + void pointPainterToCursor( QPainter &Painter, const KBufferColumn &Column ) const; + /** draws the blinking cursor or removes it */ + void paintActiveCursor( bool CursorOn ); + void paintInactiveCursor( bool CursorOn ); + void paintLine( KBufferColumn *C, int Line, KSection Positions ); + + protected: // partial operations + void handleMouseMove( const QPoint& Point ); + KBufferDrag *dragObject( QWidget *Parent = 0 ) const; + void pasteFromSource( QMimeSource *Source ); + /** removes the section from the databuffer and updates all affected values */ + KSection removeData( KSection Indizes ); + /** sets ChangedRange to the range of VisibleRange that is actually changed + * @return true if there was a change within the visible range + */ + bool hasChanged( const KCoordRange &VisibleRange, KCoordRange *ChangedRange ) const; + void handleInternalDrag( QDropEvent *e ); + + protected: + /** recalcs all dependant values with the actual NoOfBytesPerLine */ + void adjustToLayoutNoOfBytesPerLine(); + /** recalcs a layout due to the resize style that fits into the view size + * and updates the dependant values + */ + void adjustLayoutToSize(); + /** */ + void updateLength(); + /** calls updateContent for the Column */ + void updateColumn( KColumn &Column ); + + protected slots: + /** gets called by the cursor blink timer */ + void blinkCursor(); + /** gets called by the scroll timer (for mouse selection) */ + void autoScrollTimerDone(); + /** */ + void clipboardChanged(); + /** */ + void startDrag(); + + protected slots: // QWidget API + virtual void fontChange( const QFont &OldFont ); + + + protected: + /** Buffer with the data */ + KDataBuffer *DataBuffer; + + /** holds the logical layout */ + KBufferLayout *BufferLayout; + /** */ + KBufferCursor *BufferCursor; + /** */ + KBufferRanges *BufferRanges; + + + protected: + KOffsetColumn *OffsetColumn; + KBorderColumn *FirstBorderColumn; + KValueColumn *ValueColumn; + KBorderColumn *SecondBorderColumn; + KCharColumn *CharColumn; + + /** points to the column with keyboard focus */ + KBufferColumn *ActiveColumn; + /** points to the column without keyboard focus (if there is) */ + KBufferColumn *InactiveColumn; + + /** the actual input controller */ + KController *Controller; + /** */ + KTabController *TabController; + /** */ + KNavigator *Navigator; + /** */ + KValueEditor *ValueEditor; + /** */ + KCharEditor *CharEditor; + + protected: + /** Timer that controls the blinking of the cursor */ + QTimer *CursorBlinkTimer; + /** Timer that triggers ensureCursorVisible function calls */ + QTimer *ScrollTimer; +/* QTimer *ChangeIntervalTimer, */ + /** Timer to start a drag */ + QTimer *DragStartTimer; + /** timer to measure whether the time between a double click and the following counts for a tripleclick */ + QTimer *TrippleClickTimer; + + /** object to store the blinking cursor pixmaps */ + KCursor *CursorPixmaps; + /** */ + KCharCodec *Codec; + + protected: + /** point at which the current double click happended (used by TrippleClick) */ + QPoint DoubleClickPoint; + /** line in which the current double click happended (used by TrippleClick) */ + int DoubleClickLine; + /** point at which the current dragging started */ + QPoint DragStartPoint; + /** */ + QClipboard::Mode ClipboardMode; + /** font size as set by user (used for zooming) */ + int DefaultFontSize; + + protected: // parameters + /** style of resizing */ + KResizeStyle ResizeStyle; + /** */ + KEncoding Encoding; + + /** flag whether the widget is set to readonly. Cannot override the databuffer's setting, of course. */ + bool ReadOnly:1; + /** flag if only overwrite is allowed */ + bool OverWriteOnly:1; + /** flag if overwrite mode is active */ + bool OverWrite:1; + /** flag if a mouse button is pressed */ + bool MousePressed:1; + /** flag if a double click is happening */ + bool InDoubleClick:1; + /** flag if a Drag'n'Drop is happening */ + bool InDnD:1; + /** flag if a drag might have started */ + bool DragStartPossible:1; + /** flag if the cursor should be invisible */ + bool CursorPaused:1; + /** flag if the cursor is visible */ + bool BlinkCursorVisible:1; + /** flag whether the font is changed due to a zooming */ + bool InZooming:1; + + private: + /** the binary compatibility saving helper */ + KHexEditPrivate* d; + + private: // Disabling copy constructor and operator= - not useful + KHexEdit( const KHexEdit & ); + KHexEdit &operator=( const KHexEdit & ); +}; + + +inline const KValueColumn& KHexEdit::valueColumn() const { return *ValueColumn; } +inline const KCharColumn& KHexEdit::charColumn() const { return *CharColumn; } +inline const KBufferColumn& KHexEdit::activeColumn() const { return *ActiveColumn; } +inline const KBufferColumn& KHexEdit::inactiveColumn() const { return *InactiveColumn; } + +inline KValueColumn& KHexEdit::valueColumn() { return *ValueColumn; } +inline KCharColumn& KHexEdit::charColumn() { return *CharColumn; } +inline KBufferColumn& KHexEdit::activeColumn() { return *ActiveColumn; } +inline KBufferColumn& KHexEdit::inactiveColumn() { return *InactiveColumn; } + +} + +#endif diff --git a/khexedit/lib/khexedit_export.h b/khexedit/lib/khexedit_export.h new file mode 100644 index 0000000..f922516 --- /dev/null +++ b/khexedit/lib/khexedit_export.h @@ -0,0 +1,25 @@ +/*************************************************************************** + khexedit_export.h - description + ------------------- + begin : 22 Nov 2004 + copyright : (C) 2004 Dirk Mueller + email : mueller@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHEXEDIT_EXPORT_H +#define KHEXEDIT_EXPORT_H + +#include + +#define KHEXEDIT_EXPORT KDE_EXPORT + +#endif diff --git a/khexedit/lib/koffsetcoltextexport.cpp b/khexedit/lib/koffsetcoltextexport.cpp new file mode 100644 index 0000000..c5644df --- /dev/null +++ b/khexedit/lib/koffsetcoltextexport.cpp @@ -0,0 +1,61 @@ +/*************************************************************************** + koffsetcoltextexport.cpp - description + ------------------- + begin : Sam Aug 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +// lib specific +#include "koffsetcolumn.h" +#include "koffsetcoltextexport.h" + +using namespace KHE; + + +KOffsetColTextExport::KOffsetColTextExport( const KOffsetColumn *OffsetColumn ) + : CodingWidth( OffsetColumn->codingWidth() ), + FirstLineOffset( OffsetColumn->firstLineOffset() ), + Delta( OffsetColumn->delta() ), + printFunction( OffsetColumn->printFunction() ) +{ +} + +int KOffsetColTextExport::charsPerLine() const +{ + return CodingWidth; +} + + +void KOffsetColTextExport::printFirstLine( QString &T, int Line ) const +{ + PrintLine = Line; + print( T ); +} + +void KOffsetColTextExport::printNextLine( QString &T ) const +{ + print( T ); +} + +void KOffsetColTextExport::print( QString &T ) const +{ + // TODO: fix me (no more printFunction) + char *B = new char[CodingWidth+1]; + printFunction( B, FirstLineOffset + Delta*PrintLine ); + T.append( B ); + delete [] B; + + ++PrintLine; +} diff --git a/khexedit/lib/koffsetcoltextexport.h b/khexedit/lib/koffsetcoltextexport.h new file mode 100644 index 0000000..e07e659 --- /dev/null +++ b/khexedit/lib/koffsetcoltextexport.h @@ -0,0 +1,57 @@ +/*************************************************************************** + koffsetcoltextexport.h - description + ------------------- + begin : Sam Aug 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KOFFSETCOLTEXTEXPORT_H +#define KHE_KOFFSETCOLTEXTEXPORT_H + +// lib specific +#include "kcoltextexport.h" +#include "koffsetformat.h" + + +namespace KHE +{ + +class KOffsetColumn; + +class KOffsetColTextExport : public KColTextExport +{ + public: + KOffsetColTextExport( const KOffsetColumn *OC ); + + public: // KColTextExport API + void printFirstLine( QString &T, int Line ) const; + void printNextLine( QString &T ) const; + /** tells how much chars per line are needed */ + int charsPerLine() const; + + protected: + void print( QString &T ) const; + + protected: + const int CodingWidth; + const int FirstLineOffset; + const int Delta; + const KOffsetFormat::print printFunction; + + /** the line we are in */ + mutable int PrintLine; +}; + +} + +#endif diff --git a/khexedit/lib/koffsetcolumn.cpp b/khexedit/lib/koffsetcolumn.cpp new file mode 100644 index 0000000..6bd6d09 --- /dev/null +++ b/khexedit/lib/koffsetcolumn.cpp @@ -0,0 +1,110 @@ +/*************************************************************************** + koffsetcolumn.cpp - description + ------------------- + begin : Mit Mai 14 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + +// qt specific +#include "qpainter.h" +// lib specific +#include "kcolumnsview.h" +#include "koffsetcolumn.h" + +using namespace KHE; + +KOffsetColumn::KOffsetColumn( KColumnsView *V, int FLO, int D, KOffsetFormat::KFormat F ) + : KColumn( V ), + FirstLineOffset( FLO ), + Delta( D ), + Margin( 0 ), + DigitWidth( 0 ), + DigitBaseLine( 0 ), + Format( KOffsetFormat::None ) +{ + setFormat( F ); +} + + +KOffsetColumn::~KOffsetColumn() +{ +} + + +void KOffsetColumn::paintLine( QPainter *P, int Line ) +{ + const QColor &ButtonColor = View->colorGroup().button(); + P->fillRect( 0,0,width(),LineHeight, QBrush(ButtonColor,Qt::SolidPattern) ); + + printFunction()( CodedOffset,FirstLineOffset+Delta*Line ); + P->drawText( 0, DigitBaseLine, QString().append(CodedOffset) ); +} + + +void KOffsetColumn::paintFirstLine( QPainter *P, KPixelXs, int FirstLine ) +{ + PaintLine = FirstLine; + paintLine( P, PaintLine++ ); +} + + +void KOffsetColumn::paintNextLine( QPainter *P ) +{ + paintLine( P, PaintLine++ ); +} + + + +void KOffsetColumn::paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys ) +{ + Xs.restrictTo( XSpan ); + + const QColor &ButtonColor = View->colorGroup().button(); + P->fillRect( Xs.start(), Ys.start(), Xs.width(), Ys.width(), QBrush(ButtonColor,Qt::SolidPattern) ); +} + +void KOffsetColumn::setFormat( KOffsetFormat::KFormat F ) +{ + // no changes? + if( Format == F ) + return; + + Format = F; + + CodingWidth = KOffsetFormat::codingWidth( Format ); + PrintFunction = KOffsetFormat::printFunction( Format ); + + recalcX(); +} + +void KOffsetColumn::setMetrics( KPixelX DW, KPixelY DBL ) +{ + DigitBaseLine = DBL; + setDigitWidth( DW ); +} + +void KOffsetColumn::setDigitWidth( KPixelX DW ) +{ + // no changes? + if( DigitWidth == DW ) + return; + + DigitWidth = DW; + + recalcX(); +} + +void KOffsetColumn::recalcX() +{ + // recalculate depend sizes + setWidth( CodingWidth * DigitWidth ); +} diff --git a/khexedit/lib/koffsetcolumn.h b/khexedit/lib/koffsetcolumn.h new file mode 100644 index 0000000..ae182f9 --- /dev/null +++ b/khexedit/lib/koffsetcolumn.h @@ -0,0 +1,109 @@ +/*************************************************************************** + koffsetcolumn.h - description + ------------------- + begin : Mit Mai 14 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KOFFSETCOLUMN_H +#define KHE_KOFFSETCOLUMN_H + +// lib specific +#include "koffsetformat.h" +#include "kcolumn.h" + +namespace KHE +{ + +/** + *@author Friedrich W. H. Kossebau + */ + +class KOffsetColumn : public KColumn +{ + public: + KOffsetColumn( KColumnsView *V, int FLO, int D, KOffsetFormat::KFormat F ); + virtual ~KOffsetColumn(); + + public: // KColumn API + virtual void paintFirstLine( QPainter *P, KPixelXs Xs, int FirstLine ); + virtual void paintNextLine( QPainter *P ); + virtual void paintEmptyColumn( QPainter *P, KPixelXs Xs, KPixelYs Ys ); + + + public: + void setFirstLineOffset( int FLO ); + void setDelta( int D ); + + void setFormat( KOffsetFormat::KFormat F ); + /** sets width of digits and recalculates depend sizes */ + void setDigitWidth( KPixelX DW ); + /** */ + void setMetrics( KPixelX DW, KPixelY DBL ); + + public: // read access + int delta() const; + int firstLineOffset() const; + int codingWidth() const; + KOffsetFormat::print printFunction() const; + + + protected: + /** recalculates all x values */ + void recalcX(); + /** paints full line */ + void paintLine( QPainter *P, int Line ); + + + protected: // user settings + /** starting offset of the first line + * if different from StartOffset results in leading space + */ + int FirstLineOffset; + /** offset delta per line */ + int Delta; + + protected: // pixel related + /** size of the line margin */ + int Margin; + /** */ + KPixelX DigitWidth; + /** */ + KPixelY DigitBaseLine; + + protected: // general layout + KOffsetFormat::KFormat Format; + + int CodingWidth; + KOffsetFormat::print PrintFunction; + + /** buffer to hold the formatted coding */ + mutable char CodedOffset[KOffsetFormat::MaxFormatWidth+1]; + + protected: // firstnext trips related + /** */ + int PaintLine; +}; + + +inline int KOffsetColumn::firstLineOffset() const { return FirstLineOffset; } +inline void KOffsetColumn::setFirstLineOffset( int FLO ) { FirstLineOffset = FLO; } +inline int KOffsetColumn::delta() const { return Delta; } +inline void KOffsetColumn::setDelta( int D ) { Delta = D; } + +inline int KOffsetColumn::codingWidth() const { return CodingWidth; } +inline KOffsetFormat::print KOffsetColumn::printFunction() const { return PrintFunction; } + +} + +#endif diff --git a/khexedit/lib/koffsetformat.cpp b/khexedit/lib/koffsetformat.cpp new file mode 100644 index 0000000..e82fa9d --- /dev/null +++ b/khexedit/lib/koffsetformat.cpp @@ -0,0 +1,48 @@ +/*************************************************************************** + koffsetformat.cpp - description + ------------------- + begin : Mit Mai 21 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// c specific +#include +// lib specific +#include "koffsetformat.h" + +using namespace KHE; + + +const unsigned int KOffsetFormat::CodingWidth[2] = { 9, 10 }; + +const KOffsetFormat::print KOffsetFormat::PrintFunction[2] = +{ KOffsetFormat::printHexadecimalOffset, KOffsetFormat::printDecimalOffset }; + + + +void KOffsetFormat::printHexadecimalOffset( char *Buffer, unsigned int Offset ) +{ + sprintf( Buffer, "%04X:%04X", Offset>>16, Offset&0x0000FFFF ); +} + + +void KOffsetFormat::printHexadecimalSmallOffset( char *Buffer, unsigned int Offset ) +{ + sprintf( Buffer, "%04x:%04x", Offset>>16, Offset&0x0000FFFF ); +} + + +void KOffsetFormat::printDecimalOffset( char *Buffer, unsigned int Offset ) +{ + sprintf( Buffer, "%010u", Offset ); +} diff --git a/khexedit/lib/koffsetformat.h b/khexedit/lib/koffsetformat.h new file mode 100644 index 0000000..8bd90e2 --- /dev/null +++ b/khexedit/lib/koffsetformat.h @@ -0,0 +1,70 @@ +/*************************************************************************** + koffsetformat.h - description + ------------------- + begin : Mit Mai 21 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KOFFSETFORMAT_H +#define KHE_KOFFSETFORMAT_H + +namespace KHE +{ + +/** + *@author Friedrich W. H. Kossebau + */ + +class KOffsetFormat +{ + public: + /** */ + typedef void (*print)( char *Buffer, unsigned int Offset ); + /** */ + enum KFormat { Hexadecimal=0, Decimal, None }; + /** */ + static const int MaxFormatWidth = 9; + + private: + KOffsetFormat(); + ~KOffsetFormat(); + + public: + /** */ + static unsigned int codingWidth( int i ); + /** */ + static print printFunction( int i ); + + public: + static void printHexadecimalOffset( char *Buffer, unsigned int Offset ); + static void printHexadecimalSmallOffset( char *Buffer, unsigned int Offset ); + static void printDecimalOffset( char *Buffer, unsigned int Offset ); + + protected: + /** */ + static const unsigned int CodingWidth[2]; //TODO: would sizeof(Coding} work? + /** */ + static const print PrintFunction[2]; +}; + + +inline unsigned int KOffsetFormat::codingWidth( int i ) +{ return CodingWidth[i]; } + +inline KOffsetFormat::print KOffsetFormat::printFunction( int i ) +{ return PrintFunction[i]; } + + +} + +#endif diff --git a/khexedit/lib/kplainbuffer.cpp b/khexedit/lib/kplainbuffer.cpp new file mode 100644 index 0000000..63c1db7 --- /dev/null +++ b/khexedit/lib/kplainbuffer.cpp @@ -0,0 +1,344 @@ +/*************************************************************************** + kplainbuffer.cpp - description + ------------------- + begin : Mit Jun 03 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + +//#include +// c specific +#include +#include +// lib specific +#include "kplainbuffer.h" + + +static const unsigned int MinChunkSize = 512; +static const unsigned int MaxChunkSize = 1024*10; // TODO: get max. memory page size + +// TODO: think about realloc & Co. +using namespace KHE; + +KPlainBuffer::KPlainBuffer( char *D, unsigned int S, int RS, bool KM ) + : Data( D ), + Size( S ), + RawSize( RS<(int)S?S:RS ), + MaxSize( -1 ), + KeepsMemory( KM ), + ReadOnly( true ), + Modified( false ) +{ +} + +KPlainBuffer::KPlainBuffer( const char *D, unsigned int S ) + : Data( (char *)D ), + Size( S ), + RawSize( S ), + MaxSize( -1 ), + KeepsMemory( true ), + ReadOnly( true ), + Modified( false ) +{ +} + +KPlainBuffer::KPlainBuffer( int S, int MS ) + : Data( S?new char[S]:0 ), + Size( S ), + RawSize( S ), + MaxSize( MS ), + KeepsMemory( false ), + ReadOnly( true ), + Modified( false ) +{ +} + +KPlainBuffer::~KPlainBuffer() +{ +} + + + +int KPlainBuffer::insert( int Pos, const char* D, int Length ) +{ + // check all parameters + if( Length == 0 ) + return 0; + //kdDebug() << QString("before: Size: %1, RawSize: %2").arg(Size).arg(RawSize) << endl; + // correct for appending + if( Pos > (int)Size ) + Pos = Size; + + Length = addSize( Length, Pos, true ); + + // copy new data to its place + memcpy( &Data[Pos], D, Length ); + + //kdDebug() << QString("after: Size: %1, RawSize: %2").arg(Size).arg(RawSize) << endl; + + Modified = true; + return Length; +} + + +int KPlainBuffer::remove( KSection Remove ) +{ + if( Remove.startsBehind(Size-1) || Remove.width() == 0 ) + return 0; + + Remove.restrictEndTo( Size-1 ); + + unsigned int BehindRemovePos = Remove.end()+1; + // move right data behind the input range + memmove( &Data[Remove.start()], &Data[BehindRemovePos], Size-BehindRemovePos ); + + // set new values + Size -= Remove.width(); + + Modified = true; + return Remove.width(); +} + + +unsigned int KPlainBuffer::replace( KSection Remove, const char* D, unsigned int InputLength ) +{ + // check all parameters + if( Remove.start() >= (int)Size || (Remove.width()==0 && InputLength==0) ) + return 0; + + Remove.restrictEndTo( Size-1 ); + + int SizeDiff = InputLength - Remove.width(); + unsigned int NewSize = Size + SizeDiff; + // check if buffer does not get to big TODO: make algo simplier and less if else + if( MaxSize != -1 && (int)NewSize > MaxSize) + { + if( (int)Size == MaxSize ) + return 0; + InputLength -= NewSize - MaxSize; + NewSize = MaxSize; + } + else if( KeepsMemory && NewSize > RawSize ) + { + if( Size == RawSize ) + return 0; + InputLength -= NewSize - RawSize; + NewSize = RawSize; + } + + int BehindInsertPos = Remove.start() + InputLength; + int BehindRemovePos = Remove.end()+1; + + // raw array not big enough? + if( RawSize < NewSize ) + { + // create new buffer + char *NewData = new char[NewSize]; + if( NewData == 0 ) + return 0; + + // move old data to its (new) places + memcpy( NewData, Data, Remove.start() ); + memcpy( &NewData[BehindInsertPos], &Data[BehindRemovePos], Size-BehindRemovePos ); + + // remove old + delete [] Data; + // set new values + Data = NewData; + RawSize = NewSize; + } + else + // move old data to its (new) places + memmove( &Data[BehindInsertPos], &Data[BehindRemovePos], Size-BehindRemovePos ); + + // copy new data to its place + memcpy( &Data[Remove.start()], D, InputLength ); + + // set new values + Size = NewSize; + + Modified = true; + return InputLength; +} + + +int KPlainBuffer::move( int DestPos, KSection SourceSection ) +{ + // check all parameters + if( SourceSection.start() >= (int)Size || SourceSection.width() == 0 + || DestPos > (int)Size || SourceSection.start() == DestPos ) + return SourceSection.start(); + + SourceSection.restrictEndTo( Size-1 ); + bool ToRight = DestPos > SourceSection.start(); + int MovedLength = SourceSection.width(); + int DisplacedLength = ToRight ? DestPos - SourceSection.end()-1 : SourceSection.start() - DestPos; + + // find out section that is smaller + int SmallPartLength, LargePartLength, SmallPartStart, LargePartStart, SmallPartDest, LargePartDest; + // moving part is smaller? + if( MovedLength < DisplacedLength ) + { + SmallPartStart = SourceSection.start(); + SmallPartLength = MovedLength; + LargePartLength = DisplacedLength; + // moving part moves right? + if( ToRight ) + { + SmallPartDest = DestPos - MovedLength; + LargePartStart = SourceSection.end()+1; + LargePartDest = SourceSection.start(); + } + else + { + SmallPartDest = DestPos; + LargePartStart = DestPos; + LargePartDest = DestPos + MovedLength; + } + } + else + { + LargePartStart = SourceSection.start(); + LargePartLength = MovedLength; + SmallPartLength = DisplacedLength; + // moving part moves right? + if( ToRight ) + { + LargePartDest = DestPos - MovedLength; + SmallPartStart = SourceSection.end()+1; + SmallPartDest = SourceSection.start(); + } + else + { + LargePartDest = DestPos; + SmallPartStart = DestPos; + SmallPartDest = DestPos + MovedLength; + } + } + + // copy smaller part to tempbuffer + char *Temp = new char[SmallPartLength]; + memcpy( Temp, &Data[SmallPartStart], SmallPartLength ); + + // move the larger part + memmove( &Data[LargePartDest], &Data[LargePartStart], LargePartLength ); + + // copy smaller part to its new dest + memcpy( &Data[SmallPartDest], Temp, SmallPartLength ); + delete [] Temp; + + Modified = true; + return MovedLength < DisplacedLength ? SmallPartDest : LargePartDest; +} + + +int KPlainBuffer::fill( const char FChar, int FillLength, unsigned int Pos ) +{ + // nothing to fill + if( Pos >= Size ) + return 0; + + int LengthToEnd = Size - Pos; + + if( FillLength < 0 ) + FillLength = LengthToEnd; + else if( FillLength > LengthToEnd ) + FillLength = addSize( FillLength, Pos, false ); + + memset( &Data[Pos], FChar, FillLength ); + Modified = true; + return FillLength; +} + + +int KPlainBuffer::find( const char* SearchString, int Length, KSection Section ) const +{ + Section.restrictEndTo( Size-1 ); + + for( int i = Section.start(); i <= Section.end(); ++i ) + { + int Result; +// if( IgnoreCase ) +// result = strncasecmp( &data()[i], sc.key.data(), sc.key.size() ); +// else + Result = memcmp( &Data[i], SearchString, Length ); + // found? + if( Result == 0 ) + return i; + } + return -1; +} + +int KPlainBuffer::rfind( const char*, int /*Length*/, int /*Pos*/ ) const { return 0; } + + +int KPlainBuffer::addSize( int AddSize, int SplitPos, bool SaveUpperPart ) +{ + unsigned int NewSize = Size + AddSize; + // check if buffer does not get too big + if( MaxSize != -1 && (int)NewSize > MaxSize ) + { + if( (int)Size == MaxSize ) + return 0; + NewSize = MaxSize; + AddSize = NewSize - Size; + } + else if( KeepsMemory && NewSize > RawSize ) + { + if( Size == RawSize ) + return 0; + NewSize = RawSize; + AddSize = NewSize - Size; + } + + int BehindSplitPos = SplitPos + AddSize; + // raw array not big enough? + if( RawSize < NewSize ) + { + // get new raw size + unsigned int ChunkSize = MinChunkSize; + // find chunk size where newsize fits into + while( ChunkSize < NewSize ) + ChunkSize <<= 1; + // limit to max size + if( ChunkSize > MaxChunkSize ) + ChunkSize = MaxChunkSize; + // find add size + unsigned int NewRawSize = ChunkSize; + while( NewRawSize +class KRange +{ + public: + KRange( T S, T E ) : Start( S ), End( E ) {} + KRange() : Start( null() ), End( null() ) {} + ~KRange() {} + + public: + KRange &operator=( const KRange &R ) { Start = R.Start; End = R.End; return *this; } + + public: + bool operator==( const KRange &R ) const { return Start == R.Start && End == R.End; } + + public: // modification access + /** sets the first and the last index of the range */ + void set( T S, T E ) { Start = S; End = E; } + /** sets the first index of the range */ + void setStart( T S ) { Start = S; } + /** sets the last index of the range */ + void setEnd( T E ) { End = E; } + /** sets the range to null */ + void unset() { Start = End = null(); } + /** restricts the range to Limit. If one of both ranges is invalid the behaviour is undefined */ + void restrictTo( const KRange &Limit ) + { if( Start < Limit.start() ) Start = Limit.start(); if( End > Limit.end() ) End = Limit.end(); } + /** restricts the start to Limit. If the range is invalid the behaviour is undefined */ + void restrictStartTo( T Limit ) { if( Start < Limit ) Start = Limit; } + /** restricts the end to Limit. If the range is invalid the behaviour is undefined */ + void restrictEndTo( T Limit ) { if( End > Limit ) End = Limit; } + /** extends the range to Limit. If one of both is invalid the behaviour is undefined */ + void extendTo( const KRange &Limit ) + { if( Start > Limit.start() ) Start = Limit.start(); if( End < Limit.end() ) End = Limit.end(); } + /** extends the start to Limit. If the range is invalid the behaviour is undefined */ + void extendStartTo( T Limit ) { if( Start > Limit ) Start = Limit; } + /** extends the end to Limit. If the range is invalid the behaviour is undefined */ + void extendEndTo( T Limit ) { if( End < Limit ) End = Limit; } + /** moves the range by D. If the range is invalid the behaviour is undefined */ + void moveBy( T D ) { Start += D; End += D; } + + public: // value access + /** @return start */ + T start() const { return Start; } + /** @return end */ + T end() const { return End; } + + + public: // logic access + /** returns true if Value is covered */ + bool includes( T Value ) const { return Value <= End && Value >= Start; } + /** returns true if range is before index. if range is invalid the behaviour is undefined */ + bool endsBefore( T Value ) const { return End < Value; } + /** returns true if range is behind index. if range is invalid the behaviour is undefined */ + bool startsBehind( T Value ) const { return Start > Value; } + /** returns true is the range starts before index. If the range is invalid the behaviour is undefined */ + bool startsBefore( T Value ) const { return Start < Value; } + /** returns true is the range end later then index. If the range is invalid the behaviour is undefined */ + bool endsBehind( T Value ) const { return End > Value; } + + /** returns true is the range covers R. If one of both is invalid the behaviour is undefined */ + bool includes( const KRange &R ) const { return End >= R.End && Start <= R.Start; } + /** returns true is the range ends before R starts. If one of both is invalid the behaviour is undefined */ + bool endsBefore( const KRange &R ) const { return End < R.Start; } + /** returns true is the range starts later than R ends. If one of both is invalid the behaviour is undefined */ + bool startsBehind( const KRange &R ) const { return Start > R.End; } + /** returns true is the range starts prior than R. If one of both is invalid the behaviour is undefined */ + bool startsBefore( const KRange &R ) const { return Start < R.Start; } + /** returns true is the range ends later than R. If one of both is invalid the behaviour is undefined */ + bool endsBehind( const KRange &R ) const { return End > R.End; } + /** returns true is the range shares at least one index with R. If one of both is invalid the behaviour is undefined */ + bool overlaps( const KRange &R ) const { return Start <= R.End && End >= R.Start; } + + /** returns true if the range covers at least one index */ + bool isValid() const { return Start != null() && Start <= End; } + /** returns true if the range has not been set */ + bool isEmpty() const { return Start == null() && End == null(); } + + + protected: + /** delivers a null element. Should be specialiced for complexer types. */ + const T null () const { return T(-1);} + + protected: + /** first value of the range */ + T Start; + /** last value of the range */ + T End; +}; + +} + +#endif diff --git a/khexedit/lib/kreadonlybuffer.h b/khexedit/lib/kreadonlybuffer.h new file mode 100644 index 0000000..63264b2 --- /dev/null +++ b/khexedit/lib/kreadonlybuffer.h @@ -0,0 +1,45 @@ +/*************************************************************************** + kreadonlybuffer.h - description + ------------------- + begin : Mit Mai 14 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KREADONLYBUFFER_H +#define KHE_KREADONLYBUFFER_H + +#include "kdatabuffer.h" + +namespace KHE +{ + +/** + *@author Friedrich W. H. Kossebau + */ + +class KReadOnlyBuffer : public KDataBuffer +{ + public: + KReadOnlyBuffer() {} + ~KReadOnlyBuffer() {} + + public: // KDataBuffer API + /** is the buffer changeable ?*/ + virtual bool isReadOnly() const { return true; } + /** has the buffer been modified? */ + virtual bool isModified() const { return false; } +}; + +} + +#endif diff --git a/khexedit/lib/ksection.h b/khexedit/lib/ksection.h new file mode 100644 index 0000000..7693219 --- /dev/null +++ b/khexedit/lib/ksection.h @@ -0,0 +1,108 @@ +/*************************************************************************** + ksection.h - description + ------------------- + begin : Sun 22.06.2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de +****************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KSECTION_H +#define KHE_KSECTION_H + + +#include "krange.h" + +namespace KHE +{ + +/** describes a section of indizes + *@author Friedrich W. H. Kossebau + */ +class KSection : public KRange +{ + public: + /** constructs a section + * @param SI starting index + * @param EI end index + */ + KSection( int SI, int EI ); + /** constructs a section + * @param SI starting index + * @param W width of the section + */ + KSection( int SI, int W, bool ); + KSection(); + ~KSection(); + + public: + KSection &operator=( const KSection &S ); + + public: + bool operator==( const KSection &S ) const; + + public: + void setByWidth( int S, int Width ); + /** sets the first index of the section's range one behind the other's end + * If one of both is invalid the behaviour is undefined + */ + void setStartBehind( KSection S ); + /** sets the first index of the section's range one behind the other's end + * If one of both is invalid or the other' start is 0 the behaviour is undefined + */ + void setEndBefore( KSection S ); + /** sets the first index of the section's range to be width-1 before the end + * If the section is invalid the behaviour is undefined + */ + void setStartByWidth( int Width ); + /** sets the last index of the section's range to be width-1 behind the start + * If the section is invalid the behaviour is undefined + */ + void setEndByWidth( int Width ); + /** moves the range defined by a new start. + * If the range is invalid the behaviour is undefined + */ + void moveToStart( int S ); + /** moves the range defined by a new start. + * If the range is invalid the behaviour is undefined + */ + void moveToEnd( int E ); + + public: + /** + * @return the numbered of included indizes or 0, if the section is invalid + */ + int width() const; +}; + + +inline KSection::KSection( int SI, int EI ) : KRange(SI,EI) {} +inline KSection::KSection( int SI, int W, bool ) : KRange(SI,SI+W-1) {} +inline KSection::KSection() {} +inline KSection::~KSection() {} + +inline bool KSection::operator==( const KSection &S ) const { return KRange::operator==(S); } + +inline KSection &KSection::operator=( const KSection &S ) { KRange::operator=(S); return *this; } + +inline int KSection::width() const { return isValid() ? end()-start()+1 : 0; } + +inline void KSection::setByWidth( int S, int Width ) { setStart( S ); setEnd( S+Width-1 ); } +inline void KSection::setStartByWidth( int Width ) { setStart( end()-Width+1 ); } +inline void KSection::setEndByWidth( int Width ) { setEnd( start()+Width-1 ); } +inline void KSection::setStartBehind( KSection S ) { setStart( S.end()+1 ); } +inline void KSection::setEndBefore( KSection S ) { setEnd( S.start()-1 ); } + +inline void KSection::moveToStart( int S ) { setEnd( S+width()-1 ); setStart( S ); } +inline void KSection::moveToEnd( int E ) { setStart( E-width()+1 ); setEnd( E ); } +} + +#endif diff --git a/khexedit/lib/ksectionlist.cpp b/khexedit/lib/ksectionlist.cpp new file mode 100644 index 0000000..eec54e4 --- /dev/null +++ b/khexedit/lib/ksectionlist.cpp @@ -0,0 +1,79 @@ +/*************************************************************************** + ksectionlist.cpp - description + ------------------- + begin : Mon Jun 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "ksectionlist.h" + +using namespace KHE; + +KSectionList::KSectionList() +{ +} + + +KSectionList::~KSectionList() +{ +} + + +void KSectionList::addSection( KSection NewSection ) +{ + if( !NewSection.isValid() ) + return; + + // we try to insert it by ascending indizes + // if sections are overlapping we combine them + iterator S = begin(); + for( ; S!=end(); ++S ) + { + // is new section before the next section? + if( NewSection.endsBefore(*S) ) + { + // put the new before it + insert( S, NewSection ); + return; + } + + // does the next section overlap? + if( (*S).overlaps(NewSection) ) + { + // Start of the combined sections is the smaller one + NewSection.extendStartTo( (*S).start() ); + // next we search all the overlapping sections and keep the highest end index + int End = (*S).end(); + iterator LS = S; + for( ++LS; LS!=end(); ++LS ) + { + if( !(*LS).overlaps(NewSection) ) + break; + End = (*LS).end(); + } + // the higher end is the end of the combined section + NewSection.extendEndTo( End ); + // remove all overlapping sections + S = erase( S, LS ); + // and instead insert the combined one + insert( S, NewSection ); + return; + } + } + + // all others are before the new? + if( S == end() ) + // add it at the end + append( NewSection ); +} diff --git a/khexedit/lib/ksectionlist.h b/khexedit/lib/ksectionlist.h new file mode 100644 index 0000000..7328e42 --- /dev/null +++ b/khexedit/lib/ksectionlist.h @@ -0,0 +1,44 @@ +/*************************************************************************** + ksectionlist.h - description + ------------------- + begin : Mon Jun 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KSECTIONLIST_H +#define KHE_KSECTIONLIST_H + +// qt specific +#include +// lib specific +#include "ksection.h" + +namespace KHE { + +typedef QValueList KSectionBasicList; +/** +@author Friedrich W. H. Kossebau +*/ +class KSectionList : public KSectionBasicList +{ + public: + KSectionList(); + ~KSectionList(); + + public: + void addSection( KSection S ); +}; + +} + +#endif diff --git a/khexedit/lib/kselection.h b/khexedit/lib/kselection.h new file mode 100644 index 0000000..19b8a99 --- /dev/null +++ b/khexedit/lib/kselection.h @@ -0,0 +1,178 @@ +/*************************************************************************** + kbuffersection.h - description + ------------------- + begin : 22.06.2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de +****************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KSELECTION_H +#define KHE_KSELECTION_H + +#include "ksection.h" + +namespace KHE +{ + +/** This class describes a selected section of the buffer. + * As it is used as selection controlled by + * mouse and keyboard commands it offers two ways to set its range: + * - by giving the startposition (of the cursor) of an interactive selection + * and the subsequent end positions (until selection is finished) + * - direct setting (as provided by KSection) + * + * the interactive selection takes care that + * + *@author Friedrich W. H. Kossebau + */ +class KSelection : public KSection +{ + public: + /** creates a selection with a given start. + * @param Index index in front of which the selection begins + */ + KSelection( int Index ); + /** creates an invalid selection */ + KSelection(); + ~KSelection(); + + public: + KSelection &operator=( const KSelection &S ); + KSelection &operator=( const KSection &S ); + + public: // modification access + /** starts the selection. + * For this the anchor, start and end are set to the given index, + * so the initial selection is empty. + * @param Index index in front of which the selection begins + */ + void setStart( int Index ); + /** sets the end of the current selection + * If the end is before the start the selection will reach from the given index + * @param Index index in front of which the selection ends + */ + void setEnd( int Index ); + /** sets the selection to be invalid + */ + void cancel(); + /** sets the anchor to the start + * If the selection has not started the behaviour is undefined. + */ + void setForward(); + /** sets the anchor to the end + * If the selection has not started the behaviour is undefined. + */ + void setBackward(); + /** swaps anchor from start to end or vice versa + * If the selection has not started the behaviour is undefined. + */ + void reverse(); + + public: // value access + /** + * @return anchor value + */ + int anchor() const; + + public: // logic access + /** + * @return @c true if the anchor has been set, otherwise @c false. + */ + bool started() const; + /** + * @return @c true if the anchor has been set and the selection is empty, otherwise @c false. + */ + bool justStarted() const; + /** + * @return @c true if the anchor is at the begin of the selection + */ + bool isForward() const; + + protected: + /** cursor index where the selection starts */ + int Anchor; +}; + + +inline KSelection::KSelection() : Anchor( -1 ) {} +inline KSelection::KSelection( int Index ) : Anchor( Index ) {} +inline KSelection::~KSelection() {} + +inline KSelection &KSelection::operator=( const KSelection &S ) +{ + KSection::operator=(S); + Anchor = S.Anchor; + return *this; +} + +inline KSelection &KSelection::operator=( const KSection &S ) +{ + KSection::operator=(S); + Anchor = start(); + return *this; +} + + +inline void KSelection::setStart( int Index ) +{ + Anchor = Index; + unset(); +} + + +inline void KSelection::setEnd( int Index ) +{ + // nothing selected? + if( Index == Anchor ) + unset(); + // selecting forwards? + else if( Index > Anchor ) + { + KSection::setStart( Anchor ); + KSection::setEnd( Index-1 ); + } + // selecting backwards + else + { + KSection::setStart( Index ); + KSection::setEnd( Anchor-1 ); + } +} + +inline void KSelection::reverse() +{ + Anchor = isForward() ? end()+1 : start(); +} + +inline void KSelection::setForward() +{ + Anchor = start(); +} + +inline void KSelection::setBackward() +{ + Anchor = end()+1; +} + +inline int KSelection::anchor() const { return Anchor; } + +inline void KSelection::cancel() { Anchor = -1; unset(); } + +inline bool KSelection::started() const { return Anchor != -1; } + +inline bool KSelection::justStarted() const { return Anchor != -1 && start() == -1; } + +inline bool KSelection::isForward() const { return Anchor == start(); } + +} + +#endif diff --git a/khexedit/lib/kvaluecoltextexport.cpp b/khexedit/lib/kvaluecoltextexport.cpp new file mode 100644 index 0000000..009ad54 --- /dev/null +++ b/khexedit/lib/kvaluecoltextexport.cpp @@ -0,0 +1,69 @@ +/*************************************************************************** + kvaluecoltextexport.cpp - description + ------------------- + begin : Wed Sep 3 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "kbufferlayout.h" +#include "kvaluecolumn.h" +#include "kvaluecoltextexport.h" +#include "helper.h" + + +using namespace KHE; + +KValueColTextExport::KValueColTextExport( const KValueColumn* HC, const char *D, KCoordRange CR ) + : KBufferColTextExport( HC, D, CR, HC->byteCodec()->encodingWidth() ), + ByteCodec( KByteCodec::createCodec(HC->coding()) ) +{ +} + + +KValueColTextExport::~KValueColTextExport() +{ + delete ByteCodec; +} + + + +void KValueColTextExport::print( QString &T ) const +{ + int p = 0; + int pEnd = NoOfBytesPerLine; + // correct boundaries + if( PrintLine == CoordRange.start().line() ) + p = CoordRange.start().pos(); + if( PrintLine == CoordRange.end().line() ) + pEnd = CoordRange.end().pos()+1; + + QString E; + E.setLength( ByteCodec->encodingWidth() ); + // draw individual chars + uint e = 0; + for( ; pencode( E, 0, *PrintData ); + T.append( E ); + e = t + ByteCodec->encodingWidth(); + } + + T.append( whiteSpace(NoOfCharsPerLine-e) ); + ++PrintLine; +} + diff --git a/khexedit/lib/kvaluecoltextexport.h b/khexedit/lib/kvaluecoltextexport.h new file mode 100644 index 0000000..be6bab4 --- /dev/null +++ b/khexedit/lib/kvaluecoltextexport.h @@ -0,0 +1,47 @@ +/*************************************************************************** + kvaluecoltextexport.h - description + ------------------- + begin : Sam Aug 30 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KVALUECOLTEXTEXPORT_H +#define KHE_KVALUECOLTEXTEXPORT_H + +#include "kbytecodec.h" +#include "kbuffercoltextexport.h" + + +namespace KHE +{ + +class KValueColumn; + + +class KValueColTextExport : public KBufferColTextExport +{ + public: + KValueColTextExport( const KValueColumn* BF, const char *D, KCoordRange CR ); + virtual ~KValueColTextExport(); + + protected: + virtual void print( QString &T ) const; + + + protected: + KByteCodec *ByteCodec; +}; + +} + +#endif diff --git a/khexedit/lib/kvaluecolumn.cpp b/khexedit/lib/kvaluecolumn.cpp new file mode 100644 index 0000000..82da795 --- /dev/null +++ b/khexedit/lib/kvaluecolumn.cpp @@ -0,0 +1,134 @@ +/*************************************************************************** + kvaluecolumn.cpp - description + ------------------- + begin : Mit Sep 3 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +// lib specific +#include "kcolumnsview.h" +#include "kbuffercursor.h" +#include "kbufferlayout.h" +#include "kbufferranges.h" +#include "kvaluecolumn.h" +#include "helper.h" +#include "kcharcodec.h" + +using namespace KHE; + +static const KCoding DefaultCoding = HexadecimalCoding; +static const KCoding NotDefaultCoding = DecimalCoding; +static const int DefaultBinaryGapWidth = 1; + + +KValueColumn::KValueColumn( KColumnsView *CV, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R ) + : KBufferColumn( CV, B, L, R ), + Coding( NotDefaultCoding ), + ByteCodec( 0 ), + BinaryGapWidth( DefaultBinaryGapWidth ) +{ + setCoding( DefaultCoding ); +} + + +KValueColumn::~KValueColumn() +{ +} + + + +bool KValueColumn::setCoding( KCoding C ) +{ + // no changes? + if( Coding == C ) + return false; + + delete ByteCodec; + + Coding = C; + ByteCodec = KByteCodec::createCodec( Coding ); + CodedByte.setLength( ByteCodec->encodingWidth() ); + + // recalculate depend sizes + recalcByteWidth(); + + if( PosX ) + recalcX(); + return true; +} + + +bool KValueColumn::setBinaryGapWidth( KPixelX BGW ) +{ + // no changes? + if( BinaryGapWidth == BGW ) + return false; + + BinaryGapWidth = BGW; + + // recalculate depend sizes + recalcByteWidth(); + + if( PosX ) + recalcX(); + return true; +} + + +void KValueColumn::recalcByteWidth() +{ + ByteWidth = ByteCodec->encodingWidth() * DigitWidth; + + if( Coding == BinaryCoding ) + { + BinaryHalfOffset = 4 * DigitWidth + BinaryGapWidth; + ByteWidth += BinaryGapWidth; + } + recalcVerticalGridX(); +} + + +// perhaps sometimes there will be a grammar +void KValueColumn::paintEditedByte( QPainter *P, char Byte, const QString &EditBuffer ) +{ + KHEChar B = Codec->decode( Byte ); + + const QColorGroup &CG = View->colorGroup(); + + P->fillRect( 0,0,ByteWidth,LineHeight, QBrush(colorForChar(B),Qt::SolidPattern) ); + + drawCode( P, EditBuffer, CG.base() ); +} + + +void KValueColumn::drawByte( QPainter *P, char Byte, KHEChar /*B*/, const QColor &Color ) const +{ + ByteCodec->encode( CodedByte, 0, Byte ); + drawCode( P, CodedByte, Color ); +} + + +void KValueColumn::drawCode( QPainter *P, const QString &Code, const QColor &Color ) const +{ + P->setPen( Color ); + if( Coding == BinaryCoding ) + { + // leave a gap in the middle + P->drawText( 0, DigitBaseLine, Code.left(4) ); + P->drawText( BinaryHalfOffset, DigitBaseLine, Code.right(4) ); + } + else + P->drawText( 0, DigitBaseLine, Code ); +} diff --git a/khexedit/lib/kvaluecolumn.h b/khexedit/lib/kvaluecolumn.h new file mode 100644 index 0000000..cc25929 --- /dev/null +++ b/khexedit/lib/kvaluecolumn.h @@ -0,0 +1,92 @@ +/*************************************************************************** + kvaluecolumn.h - description + ------------------- + begin : Mit Sep 3 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KVALUECOLUMN_H +#define KHE_KVALUECOLUMN_H + +// lib specific +#include "kbytecodec.h" +#include "kbuffercolumn.h" + + +namespace KHE +{ + +class KBufferRanges; + + +/** buffer column which displays the numerical values of the bytes + * + *@author Friedrich W. H. Kossebau + */ +class KValueColumn : public KBufferColumn +{ + public: + KValueColumn( KColumnsView *CV, KDataBuffer *B, KBufferLayout *L, KBufferRanges *R ); + virtual ~KValueColumn(); + + public: + void paintEditedByte( QPainter *P, char Byte, const QString &EditBuffer ); + + public: // modification access + /** + * returns true if there was a change + */ + bool setCoding( KCoding C ); + /** sets the spacing in the middle of a binary byte in the value column + * @param BinaryGapW spacing in the middle of a binary in pixels + * returns true if there was a change + */ + bool setBinaryGapWidth( KPixelX BGW ); + + + public: // value access + KPixelX binaryGapWidth() const; + KCoding coding() const; + const KByteCodec *byteCodec() const; + + + protected: // KBufferColumn API + virtual void drawByte( QPainter *P, char Byte, KHEChar B, const QColor &Color ) const; + virtual void recalcByteWidth(); + + protected: + void drawCode( QPainter *P, const QString &Code, const QColor &Color ) const; + + protected: // set data + /** */ + KCoding Coding; + /** */ + KByteCodec *ByteCodec; + /** */ + KPixelX BinaryGapWidth; + + protected: // buffered data + /** buffer to hold the formatted coding */ + mutable QString CodedByte; + /** calculated: Offset in pixels of the second half of the binary */ + KPixelX BinaryHalfOffset; +}; + + +inline KPixelX KValueColumn::binaryGapWidth() const { return BinaryGapWidth; } +inline KCoding KValueColumn::coding() const { return Coding; } +inline const KByteCodec *KValueColumn::byteCodec() const { return ByteCodec; } + +} + +#endif diff --git a/khexedit/lib/kwordbufferservice.cpp b/khexedit/lib/kwordbufferservice.cpp new file mode 100644 index 0000000..0489139 --- /dev/null +++ b/khexedit/lib/kwordbufferservice.cpp @@ -0,0 +1,209 @@ +/*************************************************************************** + kwordbufferservice.cpp - description + ------------------- + begin : Di Jan 18 2005 + copyright : (C) 2005 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// lib specific +#include "kdatabuffer.h" +#include "kcharcodec.h" +#include "kwordbufferservice.h" + +using namespace KHE; + + +bool KWordBufferService::isWordChar( unsigned int Index ) const +{ + KHEChar C = CharCodec->decode( Buffer->datum(Index) ); + return !C.isUndefined() && C.isLetterOrNumber(); +} + + +int KWordBufferService::indexOfPreviousWordStart( unsigned int Index ) const +{ + unsigned int Size = Buffer->size(); + // already at the start or can the result only be 0? + if( Index == 0 || Size < 3 ) + return 0; + + // search in two rounds: first for the next char, than for the next nonchar + // after that return the index of the one before + bool LookingForFirstWordChar = false; + for( ; Index>0; --Index ) + { + if( !isWordChar(Index-1) ) + { + if( !LookingForFirstWordChar ) + continue; + return( Index ); + } + else if( !LookingForFirstWordChar ) + LookingForFirstWordChar = true; + } + return 0; +} + + +int KWordBufferService::indexOfNextWordStart( unsigned int Index ) const +{ + unsigned int Size = Buffer->size(); + bool LookingForFirstWordChar = false; + for( ; Indexsize(); + bool LookingForFirstWordChar = false; + for( ; Index 0; --Index ) + { + if( !isWordChar(Index-1) ) + return( Index ); + } + return 0; +} + + +int KWordBufferService::indexOfWordEnd( unsigned int Index ) const +{ + unsigned int Size = Buffer->size(); + for( ++Index; Index0; --Index ) + { + if( !isWordChar(Index-1) ) + return Index; + } + // reached start, so return it + return 0; + } + else + { + unsigned int Size = Buffer->size(); + // search for word start to the right + for( ++Index; Index0; --Index ) + { + if( isWordChar(Index-1) ) + return Index; + } + // reached start, so return it + return 0; + } + else + { + unsigned int Size = Buffer->size(); + for( ++Index; Index=0; --Index ) +{ + if( ::isWordChar(datum(Index)) ) + return Index+1; +} + // word reaches the end, so step behind + return 0; +} +*/ diff --git a/khexedit/lib/kwordbufferservice.h b/khexedit/lib/kwordbufferservice.h new file mode 100644 index 0000000..805f064 --- /dev/null +++ b/khexedit/lib/kwordbufferservice.h @@ -0,0 +1,137 @@ +/*************************************************************************** + kwordbufferservice.h - description + ------------------- + begin : Di Jan 18 2005 + copyright : (C) 2005 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KWORDBUFFERSERVICE_H +#define KHE_KWORDBUFFERSERVICE_H + +// lib specific +#include "ksection.h" + +namespace KHE +{ + +class KDataBuffer; +class KCharCodec; + +/** + * + *@author Friedrich W. H. Kossebau + */ + +class KWordBufferService +{ + public: + KWordBufferService( KDataBuffer *B, KCharCodec *C ); + ~KWordBufferService(); + + + public: + /** searches for the start of the word including the given index. + * if no other nonwordchar preceds this is 0; + * If the byte at the given Index is already a nonword char the given index is returned. + * @param Index index to start with + * @param CharType + * @return index of the first char of the current word or the given index if there is none + */ + int indexOfWordStart( unsigned int Index ) const; + int indexOfLeftWordSelect( unsigned int Index ) const; + /** searches for the end of the word including the given index. + * If the byte at the given Index is already a nonword char the given index is returned. + * if no other nonwordchar follows, that of the last byte; + * @param Index index to start with + * @param CharType + * @return index of the last char of the current word or the given index if there is none + */ + int indexOfWordEnd( unsigned int Index ) const; + /** searches for the first char after the end of the word including the given index. + * If the byte at the given Index is already a nonword char the given index is returned. + * if no other nonwordchar follows that of behind the last byte; + * @param Index index to start with + * @param CharType + * @return index of the first char after the current word or the given index if there is none + */ + int indexOfRightWordSelect( unsigned int Index ) const; + /** searches for the first char after the end of the word including the given index. + * If the byte at the given Index is already a nonword char the given index is returned. + * if no other nonwordchar follows that of behind the last byte; + * @param Index index to start with + * @param CharType + * @return index of the first char after the current word or the given index if there is none + */ +// int indexOfBehindLeftWordEnd( unsigned int Index ) const; + /** searches for the first char after the end of the word including the given index. + * If the byte at the given Index is already a nonword char the given index is returned. + * if no other nonwordchar follows that of behind the last byte; + * @param Index index to start with + * @param CharType + * @return index of the first char after the current word or the given index if there is none + */ +// int indexOfBehindRightWordEnd( unsigned int Index ) const; + /** searches the start of the next previous word that does not include the given index, + * if no further word is found 0 is returned. + * if the index is out of range the behaviour is undefined. + * @param Index + * @param CharType + * @return index of the next previous word start or 0 + */ + int indexOfPreviousWordStart( unsigned int Index ) const; + /** searches for the start of the next word not including the given index. + * if there isn't a next word the index behind end is returned + * @param Index + * @param CharType + * @return index of the start of the next word or behind end + */ + int indexOfNextWordStart( unsigned int Index ) const; + /** searches for the start of the next word not including the given index. + * if there isn't a next word the index of the end is returned + * @param Index index to start with + * @param CharType + * @return index of the last nonword char before the next word or the last index + */ + int indexOfBeforeNextWordStart( unsigned int Index ) const; + + /** if Index is out of range the behaviour is undefined + * @param Index + * @param CharType + * @return @c true if the byte at position i is a char of type CharType + */ + bool isWordChar( unsigned int Index ) const; + + /** returns the section with a word around index. + * if there is no word the section is empty + * @param Index + * @param CharType + * @return the section with a word around index. + */ + KSection wordSection( unsigned int Index ) const; + + protected: + KDataBuffer *Buffer; + KCharCodec *CharCodec; +}; + + +inline KWordBufferService::KWordBufferService( KDataBuffer *B, KCharCodec *C ) + : Buffer( B ), CharCodec( C ) {} +inline KWordBufferService::~KWordBufferService() {} + +inline KSection KWordBufferService::wordSection( unsigned int Index ) const +{ return isWordChar(Index) ? KSection( indexOfWordStart(Index), indexOfWordEnd(Index) ) : KSection(); } + +} + +#endif diff --git a/khexedit/lib/kwrappingrobuffer.cpp b/khexedit/lib/kwrappingrobuffer.cpp new file mode 100644 index 0000000..b913c1a --- /dev/null +++ b/khexedit/lib/kwrappingrobuffer.cpp @@ -0,0 +1,61 @@ +/*************************************************************************** + kwrappingrobuffer.cpp - description + ------------------- + begin : Mit Mai 14 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#include "kwrappingrobuffer.h" + +using namespace KHE; + +KWrappingROBuffer::KWrappingROBuffer( const char* D, int L ) +{ + Data = D; + Size = L; +} + +KWrappingROBuffer::KWrappingROBuffer() +{ + Data = 0L; + Size = 0; +} + + +KWrappingROBuffer::~KWrappingROBuffer() +{ +} + + +const char *KWrappingROBuffer::dataSet( KSection S ) const +{ + return &Data[S.start()]; +} + + +void KWrappingROBuffer::set( const char* D, int L ) +{ + Data = D; + Size = L; +} + + +int KWrappingROBuffer::find( const char*/*KeyData*/, int /*Length*/, KSection /*Section*/ ) const +{ + return 0; +} + +int KWrappingROBuffer::rfind( const char*, int /*Length*/, int /*Pos*/ ) const +{ + return 0; +} diff --git a/khexedit/lib/kwrappingrobuffer.h b/khexedit/lib/kwrappingrobuffer.h new file mode 100644 index 0000000..51ee7b8 --- /dev/null +++ b/khexedit/lib/kwrappingrobuffer.h @@ -0,0 +1,85 @@ +/*************************************************************************** + kwrappingrobuffer.h - description + ------------------- + begin : Mit Mai 14 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHE_KWRAPPINGROBUFFER_H +#define KHE_KWRAPPINGROBUFFER_H + +#include "kreadonlybuffer.h" + +namespace KHE +{ + +/** + *@author Friedrich W. H. Kossebau + */ + +class KWrappingROBuffer : public KReadOnlyBuffer +{ + public: + static const int NothingFound = -1; + + public: + KWrappingROBuffer(); + KWrappingROBuffer( const char* D, int L ); + virtual ~KWrappingROBuffer(); + + + public: // KDataBuffer API + virtual bool prepareRange( KSection Range ) const; + virtual const char *dataSet( KSection S ) const; + virtual char datum( unsigned int Offset ) const; + virtual int size() const; + virtual bool isModified() const; + + virtual int insert( int Pos, const char*, int Length ); + virtual int remove( KSection S ); + virtual unsigned int replace( KSection S, const char*, unsigned int Length ); + virtual int fill( const char FillChar, int, int ); + virtual void setDatum( unsigned int Offset, const char Char ); + + virtual void setModified( bool M ); + + virtual int find( const char*KeyData, int Length, KSection Section ) const; + virtual int rfind( const char*, int Length, int Pos = -1 ) const; + + + public: // + void set( const char* D, int L ); + + protected: + const char* Data; + int Size; + bool Modified; +}; + +inline int KWrappingROBuffer::size() const { return Size; } + +inline bool KWrappingROBuffer::isModified() const { return Modified; } + +inline bool KWrappingROBuffer::prepareRange( KSection ) const { return true; } +inline char KWrappingROBuffer::datum( unsigned int Offset ) const { return Data[Offset]; } + +inline int KWrappingROBuffer::insert( int, const char*, int ) { return 0; } +inline int KWrappingROBuffer::remove( KSection ) { return 0; } +inline unsigned int KWrappingROBuffer::replace( KSection, const char*, unsigned int ) { return 0; } +inline int KWrappingROBuffer::fill( const char , int, int ) { return 0; } +inline void KWrappingROBuffer::setDatum( unsigned int, const char ) {} + +inline void KWrappingROBuffer::setModified( bool M ) { Modified = M; } +} + +#endif diff --git a/khexedit/listview.cc b/khexedit/listview.cc new file mode 100644 index 0000000..50de78a --- /dev/null +++ b/khexedit/listview.cc @@ -0,0 +1,54 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + + +#include "listview.h" + + +CListView::CListView( QWidget *parent, const char *name, int visibleItem ) + :KListView( parent, name ), mVisibleItem(QMAX( 1, visibleItem )) +{ + setVisibleItem(visibleItem); +} + +void CListView::setVisibleItem( int visibleItem, bool updateSize ) +{ + mVisibleItem = QMAX( 1, visibleItem ); + if( updateSize == true ) + { + QSize s = sizeHint(); + setMinimumSize( s.width() + verticalScrollBar()->sizeHint().width() + + lineWidth() * 2, s.height() ); + } +} + +QSize CListView::sizeHint( void ) const +{ + QSize s = QListView::sizeHint(); + + int h = fontMetrics().height() + 2*itemMargin(); + if( h % 2 > 0 ) { h++; } + + s.setHeight( h*mVisibleItem + lineWidth()*2 + header()->sizeHint().height()); + return( s ); +} +#include "listview.moc" diff --git a/khexedit/listview.h b/khexedit/listview.h new file mode 100644 index 0000000..253fce9 --- /dev/null +++ b/khexedit/listview.h @@ -0,0 +1,49 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _LISTVIEW_H_ +#define _LISTVIEW_H_ + +#include + +class CListView : public KListView +{ + Q_OBJECT + + public: + CListView( QWidget *parent=0, const char *name=0, int visibleItem=10 ); + + void setVisibleItem( int visibleItem, bool updateSize=true ); + virtual QSize sizeHint( void ) const; + + private: + int mVisibleItem; +}; + + + + +#endif + + + + + + diff --git a/khexedit/main.cc b/khexedit/main.cc new file mode 100644 index 0000000..525868f --- /dev/null +++ b/khexedit/main.cc @@ -0,0 +1,130 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include + +#include +#include +#include +#include + +#include "toplevel.h" +#include "version.h" // Contains khexedit name string and version string + + +static const char description[] = + I18N_NOOP("KDE hex editor"); + +static const char version[] = APP_VERSION_STRING; + +static KCmdLineOptions option[] = +{ + { "offset ", I18N_NOOP("Jump to 'offset'"), 0 }, + { "+[file(s)]", I18N_NOOP("File(s) to open"), 0 }, + KCmdLineLastOption +}; + +static uint parseDecimalOrHexadecimal( char *buf ); + +int main( int argc, char **argv ) +{ + KAboutData aboutData("khexedit", I18N_NOOP("KHexEdit"), + version, description, KAboutData::License_GPL_V2, + "(c) 1999-2000, Espen Sand"); + aboutData.addAuthor("Espen Sand",0, "espensa@online.no", + "http://home.online.no/~espensa/khexedit/" ); + aboutData.addCredit("",I18N_NOOP("\n" + "This program uses modified code and techniques from other KDE programs,\n" + "specifically kwrite, kiconedit and ksysv. Credit goes to authors\n" + "and maintainers.\n" + "\n" + "Leon Lessing, leon@lrlabs.com, has made parts of the bit swapping\n" + "functionality.\n" + "\n" + "Craig Graham, c_graham@hinge.mistral.co.uk, has made parts of\n" + "the bit stream functionality of the conversion field.\n" + "\n" + "Dima Rogozin, dima@mercury.co.il, has extended the string dialog\n" + "list capabilities.\n" + "\n" + "Edward Livingston-Blade, sbcs@bigfoot.com, has given me very good\n" + "reports which removed some nasty bugs.\n")); + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( option ); + + KApplication app; + + if( app.isRestored() != 0 ) + { + RESTORE( KHexEdit ); + } + else + { + KHexEdit *hexEdit = new KHexEdit; + if( hexEdit == 0 ) + { + std::cerr << "Unable to start - Memory exhausted" << std::endl; + return( 1 ); + } + + hexEdit->show(); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + if (args->isSet("offset")) + { + QCString offsetStr = args->getOption("offset"); + uint _offset = parseDecimalOrHexadecimal(offsetStr.data() ); + hexEdit->setStartupOffset( _offset ); + } + + for(int i = 0; i < args->count(); i++) + hexEdit->addStartupFile( args->url(i).url() ); + + args->clear(); + } + + int result = app.exec(); + return( result ); +} + + + +static uint parseDecimalOrHexadecimal( char *buf ) +{ + if( buf == 0 ) { return( 0 ); } + + long int value; + char *end = 0; + + value = strtol( buf, &end, 10 ); + if( *end != 0 ) + { + value = strtol( buf, &end, 16 ); + if( *end != 0 ) + { + value = 0; + } + } + if( value < 0 ) { value = 0; } + return( value ); +} + diff --git a/khexedit/optiondialog.cc b/khexedit/optiondialog.cc new file mode 100644 index 0000000..2038b2d --- /dev/null +++ b/khexedit/optiondialog.cc @@ -0,0 +1,1224 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include // For KFontChooser +#include +#include +#include + +#include "optiondialog.h" +#include +#include + +#if 0 +#include +static void enableWidget( QWidget *w, bool state ) +{ + if( w->children() ) + { + QObjectList *l = (QObjectList*)w->children(); // silence please + for( uint i=0; i < l->count(); i++ ) + { + QObject *o = l->at(i); + if( o->isWidgetType() ) + { + enableWidget( (QWidget*)o, state ); + } + } + } + w->setEnabled( state ); +} +#endif + + + +COptionDialog::COptionDialog( QWidget *parent, char *name, bool modal ) + :KDialogBase( IconList, i18n("Configure"), Help|Default|Apply|Ok|Cancel, + Ok, parent, name, modal, true ) +{ + setHelp( "khexedit/khexedit.html", QString::null ); + + setupLayoutPage(); + setupCursorPage(); + setupFontPage(); + setupColorPage(); + setupFilePage(); + setupMiscPage(); + enableButton( Apply, false ); + configChanged = false; +} + + +COptionDialog::~COptionDialog( void ) +{ +} + +void COptionDialog::slotChanged() +{ + enableButton( Apply, true ); + configChanged = true; +} + +void COptionDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + showPage(0); + mLayout.lineSizeSpin->setFocus(); +} + + +void COptionDialog::setupLayoutPage( void ) +{ + QString text; + QFrame *page = addPage( i18n("Layout"), i18n("Data Layout in Editor"), + BarIcon("khexedit", KIcon::SizeMedium ) ); + + QGridLayout *gbox = new QGridLayout( page, 15, 2, 0, spacingHint() ); + gbox->setColStretch( 1, 10 ); + + mLayout.formatCombo = new QComboBox( false, page ); + QStringList modeList; + modeList.append( i18n("Hexadecimal Mode") ); + modeList.append( i18n("Decimal Mode") ); + modeList.append( i18n("Octal Mode") ); + modeList.append( i18n("Binary Mode") ); + modeList.append( i18n("Text Only Mode") ); + mLayout.formatCombo->insertStringList( modeList ); + connect( mLayout.formatCombo, SIGNAL(activated(int)), + SLOT(slotModeSelectorChanged(int)) ); + connect( mLayout.formatCombo, SIGNAL(activated(int)), + SLOT(slotChanged()) ); + gbox->addWidget( mLayout.formatCombo, 0, 1 ); + + // + // I am setting the min. width for one widget in the second column + // This widtk will be used by every widget in this column. + // + mLayout.lineSizeSpin = new QSpinBox( page ); + mLayout.lineSizeSpin->setMinimumWidth( fontMetrics().width("M") * 10 ); + mLayout.lineSizeSpin->setRange( 1, 10000 ); + connect( mLayout.lineSizeSpin, SIGNAL(valueChanged(int)), + SLOT(slotLineSizeChanged(int) ) ); + connect( mLayout.lineSizeSpin, SIGNAL(valueChanged(int)), + SLOT(slotChanged()) ); + gbox->addWidget( mLayout.lineSizeSpin, 1, 1 ); + + mLayout.columnSizeSpin = new QSpinBox( page ); + mLayout.columnSizeSpin->setRange( 1, 10000 ); + connect( mLayout.columnSizeSpin, SIGNAL(valueChanged(int)), + SLOT(slotColumnSizeChanged(int) ) ); + connect( mLayout.columnSizeSpin, SIGNAL(valueChanged(int)), + SLOT(slotChanged() ) ); + gbox->addWidget( mLayout.columnSizeSpin, 2, 1 ); + + text = i18n("Default l&ine size [bytes]:"); + QLabel *label = new QLabel( mLayout.lineSizeSpin, text, page ); + gbox->addWidget( label, 1, 0 ); + + text = i18n("Colu&mn size [bytes]:"); + label = new QLabel( mLayout.columnSizeSpin, text, page ); + gbox->addWidget( label, 2, 0 ); + + QFrame *hline = new QFrame( page ); + hline->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + gbox->addMultiCellWidget( hline, 3, 3, 0, 1 ); + + text = i18n("Line size is &fixed (use scrollbar when required)"); + mLayout.lockLineCheck = new QCheckBox( text, page ); + gbox->addMultiCellWidget( mLayout.lockLineCheck, 4, 4, 0, 1, AlignLeft ); + connect( mLayout.lockLineCheck, SIGNAL(toggled(bool)), + SLOT(slotChanged()) ); + + text = i18n("Loc&k column at end of line (when column size>1)"); + mLayout.lockColumnCheck = new QCheckBox( text, page ); + gbox->addMultiCellWidget( mLayout.lockColumnCheck, 5, 5, 0, 1 ); + connect( mLayout.lockColumnCheck, SIGNAL(toggled(bool)), + SLOT(slotChanged()) ); + + hline = new QFrame( page ); + hline->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + gbox->addMultiCellWidget( hline, 6, 6, 0, 1 ); + + QStringList gridList; + gridList.append( i18n("None") ); + gridList.append( i18n("Vertical Only") ); + gridList.append( i18n("Horizontal Only") ); + gridList.append( i18n("Both Directions") ); + + mLayout.gridCombo = new QComboBox( false, page ); + mLayout.gridCombo->insertStringList( gridList ); + connect( mLayout.gridCombo, SIGNAL(activated(int)), + SLOT(slotChanged()) ); + + text = i18n("&Gridlines between text:"); + label = new QLabel( mLayout.gridCombo, text, page ); + + gbox->addWidget( label, 7, 0 ); + gbox->addWidget( mLayout.gridCombo, 7, 1 ); + + mLayout.leftSepWidthSpin = new QSpinBox( page ); + mLayout.leftSepWidthSpin->setRange( 0, 20 ); + gbox->addWidget( mLayout.leftSepWidthSpin, 8, 1 ); + connect( mLayout.leftSepWidthSpin, SIGNAL(valueChanged(int)), + SLOT(slotChanged()) ); + + mLayout.rightSepWidthSpin = new QSpinBox( page ); + mLayout.rightSepWidthSpin->setRange( 0, 20 ); + gbox->addWidget( mLayout.rightSepWidthSpin, 9, 1 ); + connect( mLayout.rightSepWidthSpin, SIGNAL(valueChanged(int)), + SLOT(slotChanged()) ); + + text = i18n("&Left separator width [pixels]:"); + mLayout.leftSepLabel = new QLabel( mLayout.leftSepWidthSpin, text, page ); + gbox->addWidget( mLayout.leftSepLabel, 8, 0 ); + + text = i18n("&Right separator width [pixels]:"); + mLayout.rightSepLabel = new QLabel( mLayout.rightSepWidthSpin, text, page ); + gbox->addWidget( mLayout.rightSepLabel, 9, 0 ); + + mLayout.separatorSpin = new QSpinBox( page ); + mLayout.separatorSpin->setRange( 0, 20 ); + gbox->addWidget( mLayout.separatorSpin, 10, 1 ); + connect( mLayout.separatorSpin, SIGNAL(valueChanged(int)), + SLOT(slotChanged()) ); + + mLayout.edgeSpin = new QSpinBox( page ); + mLayout.edgeSpin->setRange( 0, 20 ); + gbox->addWidget( mLayout.edgeSpin, 11, 1 ); + connect( mLayout.edgeSpin, SIGNAL(valueChanged(int)), + SLOT(slotChanged()) ); + + text = i18n("&Separator margin width [pixels]:"); + label = new QLabel( mLayout.separatorSpin, text, page ); + gbox->addWidget( label, 10, 0 ); + + text = i18n("&Edge margin width [pixels]:"); + label = new QLabel( mLayout.edgeSpin, text, page ); + gbox->addWidget( label, 11, 0 ); + + text = i18n("Column separation is e&qual to one character"); + mLayout.columnCheck = new QCheckBox( text, page ); + gbox->addMultiCellWidget( mLayout.columnCheck, 12, 12, 0, 1, AlignLeft ); + connect( mLayout.columnCheck, SIGNAL(toggled(bool)), + SLOT( slotColumnSepCheck(bool))); + connect( mLayout.columnCheck, SIGNAL(toggled(bool)), + SLOT( slotChanged())); + + mLayout.columnSepSpin = new QSpinBox( page ); + mLayout.columnSepSpin->setRange( 1, 100 ); + connect( mLayout.columnSepSpin, SIGNAL(valueChanged(int)), + SLOT(slotChanged()) ); + + text = i18n("Column separa&tion [pixels]:"); + mLayout.columnSepLabel = new QLabel( mLayout.columnSepSpin, text, page ); + + gbox->addWidget( mLayout.columnSepLabel, 13, 0 ); + gbox->addWidget( mLayout.columnSepSpin, 13, 1 ); + + gbox->setRowStretch( 14, 10 ); +} + + +void COptionDialog::setupCursorPage( void ) +{ + QString text; + QFrame *page = addPage( i18n("Cursor"), + i18n("Cursor Behavior (only valid for editor)"), + BarIcon("mouse", KIcon::SizeMedium ) ); + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + + QVButtonGroup *group = new QVButtonGroup( i18n("Blinking"), page ); + group->layout()->setMargin( spacingHint() ); + topLayout->addWidget( group ); + + text = i18n("Do not b&link"); + mCursor.blinkCheck = new QCheckBox( i18n("Do not b&link"), group ); + connect( mCursor.blinkCheck, SIGNAL(toggled(bool)), + SLOT( slotBlinkIntervalCheck(bool))); + connect( mCursor.blinkCheck, SIGNAL(toggled(bool)), + SLOT( slotChanged())); + + QHBox *hbox = new QHBox( group ); + mCursor.blinkLabel = new QLabel( i18n("&Blink interval [ms]:" ), hbox ); + mCursor.blinkSpin = new QSpinBox( hbox ); + mCursor.blinkSpin->setMinimumWidth( fontMetrics().width("M") * 10 ); + mCursor.blinkSpin->setRange( 100, 1000 ); + mCursor.blinkSpin->setSteps( 100, 100 ); + mCursor.blinkSpin->setValue( 500 ); + mCursor.blinkLabel->setBuddy(mCursor.blinkSpin); + connect( mCursor.blinkSpin, SIGNAL(valueChanged(int)), + SLOT( slotChanged())); + + group = new QVButtonGroup( i18n("Shape"), page ); + group->layout()->setMargin( spacingHint() ); + topLayout->addWidget( group ); + + text = i18n("Always &use block (rectangular) cursor"); + mCursor.blockCheck = new QCheckBox( text, group ); + connect( mCursor.blockCheck, SIGNAL(toggled(bool)), + SLOT( slotBlockCursorCheck(bool))); + connect( mCursor.blockCheck, SIGNAL(toggled(bool)), + SLOT( slotChanged())); + text = i18n("Use &thick cursor in insert mode"); + mCursor.thickCheck = new QCheckBox( text, group ); + connect( mCursor.thickCheck, SIGNAL(toggled(bool)), + SLOT( slotChanged())); + + text = i18n("Cursor Behavior When Editor Loses Focus"); + group = new QVButtonGroup( text, page ); + group->layout()->setMargin( spacingHint() ); + topLayout->addWidget( group ); + + text = i18n("&Stop blinking (if blinking is enabled)"); + mCursor.stopRadio = new QRadioButton( text, group, "radio1" ); + mCursor.hideRadio = new QRadioButton( i18n("H&ide"), group, "radio2" ); + text = i18n("Do ¬hing"); + mCursor.nothingRadio = new QRadioButton( text, group, "radio3" ); + connect( mCursor.stopRadio, SIGNAL(toggled(bool)), + SLOT( slotChanged())); + connect( mCursor.hideRadio, SIGNAL(toggled(bool)), + SLOT( slotChanged())); + connect( mCursor.nothingRadio, SIGNAL(toggled(bool)), + SLOT( slotChanged())); + + topLayout->addStretch(10); +} + + +void COptionDialog::setupColorPage( void ) +{ + QString text; + QFrame *page = addPage( i18n("Colors"), + i18n("Editor Colors (system selection color is always used)"), + BarIcon("colorize", KIcon::SizeMedium ) ); + + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + + text = i18n("&Use system colors (as chosen in Control Center)"); + mColor.checkSystem = new QCheckBox( text, page ); + connect( mColor.checkSystem, SIGNAL(toggled(bool)), + SLOT( slotColorSystem(bool))); + connect( mColor.checkSystem, SIGNAL(toggled(bool)), + SLOT( slotChanged())); + topLayout->addWidget( mColor.checkSystem ); + + QFrame *hline = new QFrame( page ); + hline->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + topLayout->addWidget( hline ); + + QStringList modeList; + modeList.append( i18n("First, Third ... Line Background") ); + modeList.append( i18n("Second, Fourth ... Line Background") ); + modeList.append( i18n("Offset Background") ); + modeList.append( i18n("Inactive Background") ); + modeList.append( i18n("Even Column Text") ); + modeList.append( i18n("Odd Column Text") ); + modeList.append( i18n("Non Printable Text") ); + modeList.append( i18n("Offset Text") ); + modeList.append( i18n("Secondary Text") ); + modeList.append( i18n("Marked Background") ); + modeList.append( i18n("Marked Text") ); + modeList.append( i18n("Cursor Background") ); + modeList.append( i18n("Cursor Text (block shape)") ); + modeList.append( i18n("Bookmark Background") ); + modeList.append( i18n("Bookmark Text") ); + modeList.append( i18n("Separator") ); + modeList.append( i18n("Grid Lines") ); + + mColor.colorList = new CColorListBox( page ); + topLayout->addWidget( mColor.colorList, 10 ); + for( uint i=0; i<17; i++ ) + { + CColorListItem *listItem = new CColorListItem( modeList[i] ); + mColor.colorList->insertItem( listItem ); + } + mColor.colorList->setCurrentItem(0); + connect( mColor.colorList, SIGNAL( dataChanged() ), this, SLOT( slotChanged() ) ); +} + + +void COptionDialog::setupFontPage( void ) +{ + QString text; + QFrame *page = addPage( i18n("Font"), + i18n("Font Selection (editor can only use a fixed font)"), + BarIcon("fonts", KIcon::SizeMedium ) ); + + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + + text = i18n("&Use system font (as chosen in Control Center)"); + mFont.checkSystem = new QCheckBox( text, page ); + connect( mFont.checkSystem, SIGNAL(toggled(bool)), + this, SLOT( slotFontSystem(bool))); + connect( mFont.checkSystem, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + topLayout->addWidget( mFont.checkSystem ); + + QFrame *hline = new QFrame( page ); + hline->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + topLayout->addWidget( hline ); + + mFont.chooser = new KFontChooser( page, "font", true, QStringList(), false, 4 ); + topLayout->addWidget( mFont.chooser ); + QFont fixFont( KGlobalSettings::fixedFont() ); + fixFont.setBold(true); + mFont.chooser->setFont( fixFont, true ); + mFont.chooser->setSampleText( i18n("KHexEdit editor font") ); + connect( mFont.chooser, SIGNAL(fontSelected(const QFont &)), + this, SLOT( slotChanged())); + + hline = new QFrame( page ); + hline->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + topLayout->addWidget( hline ); + + QHBoxLayout *hbox = new QHBoxLayout(); + topLayout->addLayout( hbox ); + + mFont.nonPrintInput = new QLineEdit( page ); + mFont.nonPrintInput->setMaxLength( 1 ); + connect( mFont.nonPrintInput, SIGNAL(textChanged(const QString &)), + this, SLOT( slotChanged())); + + text = i18n("&Map non printable characters to:"); + QLabel *nonPrintLabel = new QLabel( mFont.nonPrintInput, text, page ); + + hbox->addWidget( nonPrintLabel, 0, AlignLeft ); + hbox->addSpacing( spacingHint() ); + hbox->addWidget( mFont.nonPrintInput, 10 ); + + topLayout->addStretch(10); +} + + +void COptionDialog::setupFilePage( void ) +{ + QString text; + QFrame *page = addPage( i18n("Files"), i18n("File Management"), + BarIcon("kmultiple", KIcon::SizeMedium ) ); + + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + + QGridLayout *gbox = new QGridLayout( 2, 2, spacingHint() ); + topLayout->addLayout( gbox ); + + mFile.openCombo = new QComboBox( false, page ); + QStringList modeList; + modeList.append( i18n("None") ); + modeList.append( i18n("Most Recent Document") ); + modeList.append( i18n("All Recent Documents") ); + mFile.openCombo->insertStringList( modeList ); + mFile.openCombo->setMinimumWidth( mFile.openCombo->sizeHint().width() ); + connect( mFile.openCombo, SIGNAL(activated(int)), + this, SLOT( slotChanged())); + + text = i18n("Open doc&uments on startup:"); + QLabel *label = new QLabel( mFile.openCombo, text, page ); + + gbox->addWidget( label, 0, 0 ); + gbox->addWidget( mFile.openCombo, 0, 1 ); + + text = i18n("&Jump to previous cursor position on startup"); + mFile.gotoOffsetCheck = new QCheckBox( text, page ); + // ### TODO: this is currently not available. + mFile.gotoOffsetCheck->setChecked( false ); + mFile.gotoOffsetCheck->setEnabled( false ); + // ### END + topLayout->addWidget( mFile.gotoOffsetCheck, 0, AlignLeft ); + connect( mFile.gotoOffsetCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + QFrame *hline = new QFrame( page ); + hline->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + topLayout->addWidget( hline ); + + text = i18n("Open document with &write protection enabled"); + mFile.writeProtectCheck = new QCheckBox( text, page ); + topLayout->addWidget( mFile.writeProtectCheck, 0, AlignLeft ); + connect( mFile.writeProtectCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + text = i18n("&Keep cursor position after reloading document"); + mFile.reloadOffsetCheck = new QCheckBox( text, page ); + topLayout->addWidget( mFile.reloadOffsetCheck, 0, AlignLeft ); + connect( mFile.reloadOffsetCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + text = i18n("&Make a backup when saving document"); + mFile.backupCheck = new QCheckBox( text, page ); + topLayout->addWidget( mFile.backupCheck, 0, AlignLeft ); + connect( mFile.backupCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + hline = new QFrame( page ); + hline->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + topLayout->addWidget( hline ); + + text = i18n("Don't &save \"Recent\" document list on exit"); + mFile.discardRecentCheck = new QCheckBox( text, page ); + topLayout->addWidget( mFile.discardRecentCheck, 0, AlignLeft ); + QWhatsThis::add( mFile.discardRecentCheck, + i18n( "Clicking this check box makes KHexEdit forget his recent document list " + "when the program is closed.\n" + "Note: it will not erase any document of the recent document list " + "created by KDE." ) ); + connect( mFile.discardRecentCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + text = i18n("Cl&ear \"Recent\" Document List"); + QPushButton *discardRecentButton = new QPushButton( page ); + discardRecentButton->setText( text ); + QWhatsThis::add( discardRecentButton, + i18n( "Clicking this button makes KHexEdit forget his recent document list.\n" + "Note: it will not erase any document of the recent document list " + "created by KDE." ) ); + topLayout->addWidget( discardRecentButton, 0, AlignCenter ); + connect( discardRecentButton, SIGNAL(clicked()), + SIGNAL(removeRecentFiles()) ); + + topLayout->addStretch(10); +} + + + +void COptionDialog::setupMiscPage( void ) +{ + QString text; + QLabel *label; + + QFrame *page = addPage( i18n("Miscellaneous"), i18n("Various Properties"), + BarIcon("gear", KIcon::SizeMedium ) ); + + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + + + text = i18n("Auto&matic copy to clipboard when selection is ready"); + mMisc.autoCheck = new QCheckBox( text, page ); + topLayout->addWidget( mMisc.autoCheck, 0, AlignLeft ); + connect( mMisc.autoCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + text = i18n("&Editor starts in \"insert\" mode" ); + mMisc.insertCheck = new QCheckBox( text, page ); + topLayout->addWidget( mMisc.insertCheck, 0, AlignLeft ); + connect( mMisc.insertCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + text = i18n("Confirm &wrapping (to beginning or end) during search"); + mMisc.confirmWrapCheck = new QCheckBox( text, page ); + topLayout->addWidget( mMisc.confirmWrapCheck, 0, AlignLeft ); + connect( mMisc.confirmWrapCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + text = i18n("Cursor jumps to &nearest byte when moved"); + mMisc.cursorJumpCheck = new QCheckBox( text, page ); + topLayout->addWidget( mMisc.cursorJumpCheck, 0, AlignLeft ); + connect( mMisc.cursorJumpCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + QVButtonGroup *group = new QVButtonGroup( i18n("Sounds"), page ); + group->layout()->setMargin( spacingHint() ); + topLayout->addWidget( group ); + text = i18n("Make sound on data &input (eg. typing) failure"); + mMisc.inputCheck = new QCheckBox( text, group ); + connect( mMisc.inputCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + text = i18n("Make sound on &fatal failure"); + mMisc.fatalCheck = new QCheckBox( text, group ); + connect( mMisc.fatalCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + group = new QVButtonGroup( i18n("Bookmark Visibility"), page ); + group->layout()->setMargin( spacingHint() ); + topLayout->addWidget( group ); + text = i18n("Use visible bookmarks in the offset column"); + mMisc.bookmarkColumnCheck = new QCheckBox( text, group ); + connect( mMisc.bookmarkColumnCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + text = i18n("Use visible bookmarks in the editor fields"); + mMisc.bookmarkEditorCheck = new QCheckBox( text, group ); + connect( mMisc.bookmarkEditorCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + + text = i18n("Confirm when number of printed pages will e&xceed limit"); + mMisc.thresholdCheck = new QCheckBox( text, page ); + connect( mMisc.thresholdCheck, SIGNAL(clicked()), + SLOT( slotThresholdConfirm())); + connect( mMisc.thresholdCheck, SIGNAL(toggled(bool)), + this, SLOT( slotChanged())); + topLayout->addWidget( mMisc.thresholdCheck, 0, AlignLeft ); + + QGridLayout *glay = new QGridLayout( 3, 3 ); + glay->setColStretch(2,10); + topLayout->addLayout( glay ); + + mMisc.thresholdSpin = new QSpinBox( page ); + mMisc.thresholdSpin->setMinimumWidth( fontMetrics().width("M") * 10 ); + mMisc.thresholdSpin->setRange( 5, INT_MAX ); + mMisc.thresholdSpin->setSteps( 5, 5 ); + mMisc.thresholdSpin->setValue( 5 ); + connect( mMisc.thresholdSpin, SIGNAL(valueChanged(int)), + this, SLOT( slotChanged())); + + text = i18n("&Threshold [pages]:" ); + mMisc.thresholdLabel = new QLabel( mMisc.thresholdSpin, text, page ); + + glay->addWidget( mMisc.thresholdLabel, 0, 0 ); + glay->addWidget( mMisc.thresholdSpin, 0, 1 ); + + QFrame *hline = new QFrame( page ); + hline->setFrameStyle( QFrame::Sunken | QFrame::HLine ); + glay->addMultiCellWidget( hline, 1, 1, 0, 2 ); + + mMisc.undoSpin = new QSpinBox( page ); + mMisc.undoSpin->setRange( 10, 10000 ); + mMisc.undoSpin->setSteps( 5, 5 ); + mMisc.undoSpin->setValue( 50 ); + connect( mMisc.undoSpin, SIGNAL(valueChanged(int)), + this, SLOT( slotChanged())); + + label = new QLabel( mMisc.undoSpin, i18n("&Undo limit:"), page ); + glay->addWidget( label, 2, 0 ); + glay->addWidget( mMisc.undoSpin, 2, 1 ); + + topLayout->addStretch(10); +} + + + +void COptionDialog::slotModeSelectorChanged( int index ) +{ + int lineSize = mDisplayState.line.getLineSize( index ); + int colSize = mDisplayState.line.getColumnSize( index ); + mLayout.lineSizeSpin->setValue( lineSize ); + mLayout.columnSizeSpin->setValue( colSize ); +} + +void COptionDialog::slotLineSizeChanged( int value ) +{ + int index = mLayout.formatCombo->currentItem(); + mDisplayState.line.setLineSize( index, value ); + if( index == SDisplayLine::textOnly ) + { + mLayout.columnSizeSpin->setValue( value ); + } +} + +void COptionDialog::slotColumnSizeChanged( int value ) +{ + int index = mLayout.formatCombo->currentItem(); + mDisplayState.line.setColumnSize( index, value ); + if( index == SDisplayLine::textOnly ) + { + mLayout.lineSizeSpin->setValue( value ); + } +} + +void COptionDialog::slotColumnSepCheck( bool state ) +{ + state = state == true ? false: true; + mLayout.columnSepLabel->setEnabled( state ); + mLayout.columnSepSpin->setEnabled( state ); +} + + +void COptionDialog::slotBlinkIntervalCheck( bool state ) +{ + state = state == true ? false : true; + mCursor.blinkSpin->setEnabled( state ); + mCursor.blinkLabel->setEnabled( state ); +} + +void COptionDialog::slotBlockCursorCheck( bool state ) +{ + state = state == true ? false : true; + mCursor.thickCheck->setEnabled( state ); +} + +void COptionDialog::slotFontSystem( bool state ) +{ + mFont.chooser->setEnabled( state == true ? false : true ); +} + +void COptionDialog::slotColorSystem( bool state ) +{ + state = state == true ? false : true; + mColor.colorList->setEnabled( state ); +} + + + +void COptionDialog::slotThresholdConfirm( void ) +{ + bool state = mMisc.thresholdCheck->isChecked(); + mMisc.thresholdLabel->setEnabled( state ); + mMisc.thresholdSpin->setEnabled( state ); +} + + +void COptionDialog::slotDefault( void ) +{ + // + // We use the constructor settings as default values + // + switch( activePageIndex() ) + { + case page_layout: + { + SDisplayLayout layout; + SDisplayLine line; + setLayout( layout, line ); + } + break; + + case page_cursor: + { + SDisplayCursor cursor; + setCursor( cursor ); + } + break; + + case page_color: + { + SDisplayColor color; + setColor( color ); + } + break; + + case page_font: + { + SDisplayFont font; + setFont( font ); + } + break; + + case page_file: + { + SDisplayMisc misc; + setFile( misc ); + } + break; + + case page_misc: + { + SDisplayMisc misc; + setMisc( misc ); + } + break; + } +} + + +void COptionDialog::slotOk( void ) +{ + if( configChanged ) + slotApply(); + accept(); +} + +void COptionDialog::slotApply( void ) +{ + switch( activePageIndex() ) + { + case page_layout: + { + int index = mLayout.formatCombo->currentItem(); + mDisplayState.line.setLineSize(index, mLayout.lineSizeSpin->value()); + mDisplayState.line.setColumnSize(index, mLayout.columnSizeSpin->value()); + emit lineSizeChoice( mDisplayState.line ); + + SDisplayLayout &l = mDisplayState.layout; + l.lockLine = mLayout.lockLineCheck->isChecked(); + l.lockColumn = mLayout.lockColumnCheck->isChecked(); + l.leftSeparatorWidth = mLayout.leftSepWidthSpin->value(); + l.rightSeparatorWidth = mLayout.rightSepWidthSpin->value(); + l.separatorMarginWidth = mLayout.separatorSpin->value(); + l.edgeMarginWidth = mLayout.edgeSpin->value(); + l.leftSeparatorWidth = mLayout.leftSepWidthSpin->value(); + l.rightSeparatorWidth = mLayout.rightSepWidthSpin->value(); + l.columnCharSpace = mLayout.columnCheck->isChecked(); + l.columnSpacing = mLayout.columnSepSpin->value(); + + if( mLayout.gridCombo->currentItem() == 0 ) + { + l.horzGridWidth = l.vertGridWidth = 0; + } + else if( mLayout.gridCombo->currentItem() == 1 ) + { + l.horzGridWidth = 0; + l.vertGridWidth = 1; + } + else if( mLayout.gridCombo->currentItem() == 2 ) + { + l.horzGridWidth = 1; + l.vertGridWidth = 0; + } + else + { + l.horzGridWidth = l.vertGridWidth = 1; + } + + emit layoutChoice( mDisplayState.layout ); + } + break; + + + case page_cursor: + { + SDisplayCursor &c = mDisplayState.cursor; + c.alwaysVisible = mCursor.blinkCheck->isChecked(); + c.interval = mCursor.blinkSpin->value(); + c.alwaysBlockShape = mCursor.blockCheck->isChecked(); + c.thickInsertShape = mCursor.thickCheck->isChecked(); + c.focusMode = cursorFocusMode(); + emit cursorChoice( mDisplayState.cursor ); + } + break; + + case page_color: + { + SDisplayColor &c = mDisplayState.color; + c.useSystemColor = mColor.checkSystem->isChecked(); + c.textBg = mColor.colorList->color( SColorWidgets::FirstTextBg ); + c.secondTextBg = mColor.colorList->color( SColorWidgets::SecondTextBg ); + c.offsetBg = mColor.colorList->color( SColorWidgets::OffsetBg ); + c.inactiveBg = mColor.colorList->color( SColorWidgets::InactiveBg ); + c.markBg = mColor.colorList->color( SColorWidgets::MarkedBg ); + c.markFg = mColor.colorList->color( SColorWidgets::MarkedFg ); + c.primaryFg[0] = mColor.colorList->color( SColorWidgets::EvenColumnFg ); + c.primaryFg[1] = mColor.colorList->color( SColorWidgets::OddColumnFg ); + c.offsetFg = mColor.colorList->color( SColorWidgets::OffsetFg ); + c.secondaryFg = mColor.colorList->color( SColorWidgets::SecondaryFg ); + c.cursorBg = mColor.colorList->color( SColorWidgets::CursorBg ); + c.cursorFg = mColor.colorList->color( SColorWidgets::CursorFg ); + c.leftSeparatorFg = mColor.colorList->color(SColorWidgets::SeparatorFg); + c.rightSeparatorFg = mColor.colorList->color(SColorWidgets::SeparatorFg); + c.bookmarkBg = mColor.colorList->color( SColorWidgets::BookmarkBg ); + c.bookmarkFg = mColor.colorList->color( SColorWidgets::BookmarkFg ); + c.nonPrintFg = mColor.colorList->color( SColorWidgets::NonPrintFg ); + c.gridFg = mColor.colorList->color( SColorWidgets::GridFg ); + emit colorChoice( mDisplayState.color ); + } + break; + + case page_font: + { + SDisplayFont &f = mDisplayState.font; + f.useSystemFont = mFont.checkSystem->isChecked(); + f.localFont = mFont.chooser->font(); + + QString nonPrintText = mFont.nonPrintInput->text(); + if( nonPrintText.isEmpty() ) + { + f.nonPrintChar = ' '; + } + else + { + f.nonPrintChar = nonPrintText[0]; + } + + emit fontChoice( mDisplayState.font ); + } + break; + + case page_file: + case page_misc: + { + SDisplayMisc &m = mDisplayState.misc; + m.undoLevel = mMisc.undoSpin->value(); + m.autoCopyToClipboard = mMisc.autoCheck->isChecked(); + m.insertMode = mMisc.insertCheck->isChecked(); + m.inputSound = mMisc.inputCheck->isChecked(); + m.confirmWrap = mMisc.confirmWrapCheck->isChecked(); + m.cursorJump = mMisc.cursorJumpCheck->isChecked(); + m.fatalSound = mMisc.fatalCheck->isChecked(); + m.confirmThreshold = mMisc.thresholdCheck->isChecked(); + m.thresholdValue = mMisc.thresholdSpin->value(); + m.bookmarkOffsetColumn = mMisc.bookmarkColumnCheck->isChecked(); + m.bookmarkEditor = mMisc.bookmarkEditorCheck->isChecked(); + + m.openFile = (SDisplayMisc::EOpenFile)mFile.openCombo->currentItem(); + m.gotoOnStartup = mFile.gotoOffsetCheck->isChecked(); + m.writeProtect = mFile.writeProtectCheck->isChecked(); + m.gotoOnReload = mFile.reloadOffsetCheck->isChecked(); + m.makeBackup = mFile.backupCheck->isChecked(); + m.discardRecent = mFile.discardRecentCheck->isChecked(); + + emit miscChoice( mDisplayState.misc ); + } + break; + } + enableButton( Apply, false ); + configChanged = false; +} + +void COptionDialog::setLayout( SDisplayLayout &layout, SDisplayLine &line ) +{ + mDisplayState.line = line; + mDisplayState.layout = layout; + + slotModeSelectorChanged( mLayout.formatCombo->currentItem() ); + mLayout.lockLineCheck->setChecked( layout.lockLine ); + mLayout.lockColumnCheck->setChecked( layout.lockColumn ); + mLayout.leftSepWidthSpin->setValue( layout.leftSeparatorWidth ); + mLayout.rightSepWidthSpin->setValue( layout.rightSeparatorWidth ); + mLayout.separatorSpin->setValue( layout.separatorMarginWidth ); + mLayout.edgeSpin->setValue( layout.edgeMarginWidth ); + mLayout.leftSepWidthSpin->setValue( layout.leftSeparatorWidth ); + mLayout.rightSepWidthSpin->setValue( layout.rightSeparatorWidth ); + mLayout.columnCheck->setChecked( layout.columnCharSpace ); + slotColumnSepCheck( layout.columnCharSpace ); + mLayout.columnSepSpin->setValue( layout.columnSpacing ); + + if( layout.horzGridWidth == 0 && layout.vertGridWidth == 0 ) + { + mLayout.gridCombo->setCurrentItem(0); + } + else if( layout.horzGridWidth != 0 && layout.vertGridWidth != 0 ) + { + mLayout.gridCombo->setCurrentItem(3); + } + else + { + mLayout.gridCombo->setCurrentItem( layout.vertGridWidth != 0 ? 1 : 2 ); + } + +} + + +void COptionDialog::setCursor( SDisplayCursor &cursor ) +{ + mDisplayState.cursor = cursor; + + mCursor.blinkCheck->setChecked( cursor.alwaysVisible ); + mCursor.blinkSpin->setValue( cursor.interval ); + mCursor.blockCheck->setChecked( cursor.alwaysBlockShape ); + mCursor.thickCheck->setChecked( cursor.thickInsertShape ); + bool state = cursor.focusMode == SDisplayCursor::stopBlinking ? true : false; + mCursor.stopRadio->setChecked( state ); + state = cursor.focusMode == SDisplayCursor::hide ? true : false; + mCursor.hideRadio->setChecked( state ); + state = cursor.focusMode == SDisplayCursor::ignore ? true : false; + mCursor.nothingRadio->setChecked( state ); +} + + +void COptionDialog::setColor( SDisplayColor &color ) +{ + mDisplayState.color = color; + + mColor.checkSystem->setChecked( color.useSystemColor ); + mColor.colorList->setColor( SColorWidgets::FirstTextBg, color.textBg ); + mColor.colorList->setColor( SColorWidgets::SecondTextBg, color.secondTextBg); + mColor.colorList->setColor( SColorWidgets::OffsetBg, color.offsetBg ); + mColor.colorList->setColor( SColorWidgets::InactiveBg, color.inactiveBg ); + mColor.colorList->setColor( SColorWidgets::MarkedBg, color.markBg ); + mColor.colorList->setColor( SColorWidgets::MarkedFg, color.markFg ); + mColor.colorList->setColor( SColorWidgets::EvenColumnFg, color.primaryFg[0]); + mColor.colorList->setColor( SColorWidgets::OddColumnFg, color.primaryFg[1] ); + mColor.colorList->setColor( SColorWidgets::OffsetFg, color.offsetFg ); + mColor.colorList->setColor( SColorWidgets::SecondaryFg, color.secondaryFg ); + mColor.colorList->setColor( SColorWidgets::CursorBg, color.cursorBg ); + mColor.colorList->setColor( SColorWidgets::CursorFg, color.cursorFg ); + mColor.colorList->setColor(SColorWidgets::SeparatorFg,color.leftSeparatorFg); + mColor.colorList->setColor( SColorWidgets::BookmarkBg, color.bookmarkBg ); + mColor.colorList->setColor( SColorWidgets::BookmarkFg, color.bookmarkFg ); + mColor.colorList->setColor( SColorWidgets::NonPrintFg, color.nonPrintFg ); + mColor.colorList->setColor( SColorWidgets::GridFg, color.gridFg ); +} + + +void COptionDialog::setFont( SDisplayFont &font ) +{ + mDisplayState.font = font; + + mFont.checkSystem->setChecked( font.useSystemFont ); + mFont.chooser->setFont( font.localFont, true ); + QString buf = font.nonPrintChar; + mFont.nonPrintInput->setText( buf ); +} + + +void COptionDialog::setMisc( SDisplayMisc &misc ) +{ + mDisplayState.misc.undoLevel = misc.undoLevel; + mDisplayState.misc.inputSound = misc.inputSound; + mDisplayState.misc.fatalSound = misc.fatalSound; + mDisplayState.misc.autoCopyToClipboard = misc.autoCopyToClipboard; + mDisplayState.misc.insertMode = misc.insertMode; + mDisplayState.misc.confirmWrap = misc.confirmWrap; + mDisplayState.misc.cursorJump = misc.cursorJump; + mDisplayState.misc.confirmThreshold = misc.confirmThreshold; + mDisplayState.misc.thresholdValue = misc.thresholdValue; + mDisplayState.misc.bookmarkOffsetColumn = misc.bookmarkOffsetColumn; + mDisplayState.misc.bookmarkEditor = misc.bookmarkEditor; + + mMisc.autoCheck->setChecked( misc.autoCopyToClipboard ); + mMisc.insertCheck->setChecked( misc.insertMode ); + mMisc.confirmWrapCheck->setChecked( misc.confirmWrap ); + mMisc.cursorJumpCheck->setChecked( misc.cursorJump ); + + mMisc.inputCheck->setChecked( misc.inputSound ); + mMisc.fatalCheck->setChecked( misc.fatalSound ); + mMisc.bookmarkColumnCheck->setChecked( misc.bookmarkOffsetColumn ); + mMisc.bookmarkEditorCheck->setChecked( misc.bookmarkEditor ); + + mMisc.thresholdCheck->setChecked( misc.confirmThreshold ); + mMisc.thresholdSpin->setValue( misc.thresholdValue ); + slotThresholdConfirm(); + + mMisc.undoSpin->setValue( misc.undoLevel ); +} + +void COptionDialog::setFile( SDisplayMisc &misc ) +{ + mDisplayState.misc.openFile = misc.openFile; + mDisplayState.misc.gotoOnStartup = misc.gotoOnStartup; + mDisplayState.misc.writeProtect = misc.writeProtect; + mDisplayState.misc.gotoOnReload = misc.gotoOnReload; + mDisplayState.misc.discardRecent = misc.discardRecent; + mDisplayState.misc.makeBackup = misc.makeBackup; + + mFile.openCombo->setCurrentItem( (uint)misc.openFile ); + mFile.gotoOffsetCheck->setChecked( misc.gotoOnStartup ); + mFile.writeProtectCheck->setChecked( misc.writeProtect ); + mFile.reloadOffsetCheck->setChecked( misc.gotoOnReload ); + mFile.discardRecentCheck->setChecked( misc.discardRecent ); + mFile.backupCheck->setChecked( misc.makeBackup ); +} + + +void COptionDialog::setState( SDisplayState &state ) +{ + setLayout( state.layout, state.line ); + setCursor( state.cursor ); + setColor( state.color ); + setFont( state.font ); + setFile( state.misc ); + setMisc( state.misc ); + enableButton( Apply, false ); + configChanged = false; +} + + +SDisplayCursor::EFocusMode COptionDialog::cursorFocusMode( void ) +{ + if( mCursor.stopRadio->isChecked() == true ) + { + return( SDisplayCursor::stopBlinking ); + } + else if( mCursor.hideRadio->isChecked() == true ) + { + return( SDisplayCursor::hide ); + } + else + { + return( SDisplayCursor::ignore ); + } +} + + + +CColorListBox::CColorListBox( QWidget *parent, const char *name, WFlags f ) + :KListBox( parent, name, f ), mCurrentOnDragEnter(-1) +{ + connect( this, SIGNAL(selected(int)), this, SLOT(newColor(int)) ); + setAcceptDrops( true); +} + + +void CColorListBox::setEnabled( bool state ) +{ + if( state == isEnabled() ) + { + return; + } + + QListBox::setEnabled( state ); + for( uint i=0; isetColor(color); + updateItem( colorItem ); + } +} + + +const QColor CColorListBox::color( uint index ) +{ + if( index < count() ) + { + CColorListItem *colorItem = (CColorListItem*)item(index); + return( colorItem->color() ); + } + else + { + return( black ); + } +} + + +void CColorListBox::newColor( int index ) +{ + if( isEnabled() == false ) + { + return; + } + + if( (uint)index < count() ) + { + QColor c = color( index ); + if( KColorDialog::getColor( c, this ) != QDialog::Rejected ) + { + setColor( index, c ); + emit dataChanged(); + } + } +} + + +void CColorListBox::dragEnterEvent( QDragEnterEvent *e ) +{ + if( KColorDrag::canDecode(e) && isEnabled() ) + { + mCurrentOnDragEnter = currentItem(); + e->accept( true ); + } + else + { + mCurrentOnDragEnter = -1; + e->accept( false ); + } +} + + +void CColorListBox::dragLeaveEvent( QDragLeaveEvent * ) +{ + if( mCurrentOnDragEnter != -1 ) + { + setCurrentItem( mCurrentOnDragEnter ); + mCurrentOnDragEnter = -1; + } +} + + +void CColorListBox::dragMoveEvent( QDragMoveEvent *e ) +{ + if( KColorDrag::canDecode(e) && isEnabled() ) + { + CColorListItem *item = (CColorListItem*)itemAt( e->pos() ); + if( item != 0 ) + { + setCurrentItem ( item ); + } + } +} + + +void CColorListBox::dropEvent( QDropEvent *e ) +{ + QColor color; + if( KColorDrag::decode( e, color ) ) + { + int index = currentItem(); + if( index != -1 ) + { + CColorListItem *colorItem = (CColorListItem*)item(index); + colorItem->setColor(color); + triggerUpdate( false ); // Redraw item + } + mCurrentOnDragEnter = -1; + } +} + + + +CColorListItem::CColorListItem( const QString &text, const QColor &color ) + : QListBoxItem(), mColor( color ), mBoxWidth( 30 ) +{ + setText( text ); +} + + +const QColor &CColorListItem::color( void ) +{ + return( mColor ); +} + + +void CColorListItem::setColor( const QColor &color ) +{ + mColor = color; +} + + +void CColorListItem::paint( QPainter *p ) +{ + QFontMetrics fm = p->fontMetrics(); + int h = fm.height(); + + p->drawText( mBoxWidth+3*2, fm.ascent() + fm.leading()/2, text() ); + + p->setPen( Qt::black ); + p->drawRect( 3, 1, mBoxWidth, h-1 ); + p->fillRect( 4, 2, mBoxWidth-2, h-3, mColor ); +} + + +int CColorListItem::height(const QListBox *lb ) const +{ + return( lb->fontMetrics().lineSpacing()+1 ); +} + + +int CColorListItem::width(const QListBox *lb ) const +{ + return( mBoxWidth + lb->fontMetrics().width( text() ) + 6 ); +} + + + + + + +#include "optiondialog.moc" diff --git a/khexedit/optiondialog.h b/khexedit/optiondialog.h new file mode 100644 index 0000000..ba62f62 --- /dev/null +++ b/khexedit/optiondialog.h @@ -0,0 +1,269 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _OPTION_DIALOG_H_ +#define _OPTION_DIALOG_H_ + + +class QComboBox; +class QFrame; +class QCheckBox; +class QLabel; +class QLineEdit; +class QPushbutton; +class QRadioButton; +class QSpinBox; +class QComboBox; +class KFontChooser; + + +#include +#include +#include "hexeditstate.h" + + + +class CColorListBox : public KListBox +{ + Q_OBJECT + + public: + CColorListBox( QWidget *parent=0, const char * name=0, WFlags f=0 ); + void setColor( uint index, const QColor &color ); + const QColor color( uint index ); + + public slots: + virtual void setEnabled( bool state ); + + protected: + void dragEnterEvent( QDragEnterEvent *e ); + void dragLeaveEvent( QDragLeaveEvent *e ); + void dragMoveEvent( QDragMoveEvent *e ); + void dropEvent( QDropEvent *e ); + + private slots: + void newColor( int index ); + + private: + int mCurrentOnDragEnter; + + signals: + void dataChanged(); +}; + + +class CColorListItem : public QListBoxItem +{ + public: + CColorListItem( const QString &text, const QColor &color=Qt::black ); + const QColor &color( void ); + void setColor( const QColor &color ); + + protected: + virtual void paint( QPainter * ); + virtual int height( const QListBox * ) const; + virtual int width( const QListBox * ) const; + + private: + QColor mColor; + int mBoxWidth; +}; + + + + +class COptionDialog : public KDialogBase +{ + Q_OBJECT + + public: + enum EPage + { + page_layout = 0, + page_cursor, + page_font, + page_color, + page_file, + page_misc, + page_max + }; + + COptionDialog( QWidget *parent = 0, char *name = 0, bool modal = false ); + ~COptionDialog( void ); + + void setLayout( SDisplayLayout &layout, SDisplayLine &line ); + void setCursor( SDisplayCursor &cursor ); + void setColor( SDisplayColor &color ); + void setFont( SDisplayFont &font ); + void setFile( SDisplayMisc &misc ); + void setMisc( SDisplayMisc &misc ); + void setState( SDisplayState &state ); + + protected: + virtual void showEvent( QShowEvent *e ); + + protected slots: + void slotModeSelectorChanged( int index ); + void slotLineSizeChanged( int value ); + void slotColumnSizeChanged( int value ); + void slotColumnSepCheck( bool state ); + void slotBlinkIntervalCheck( bool state ); + void slotBlockCursorCheck( bool state ); + void slotFontSystem( bool state ); + void slotColorSystem( bool state ); + void slotThresholdConfirm( void ); + + virtual void slotDefault( void ); + virtual void slotOk( void ); + virtual void slotApply( void ); + void slotChanged(); + + private: + struct SLayoutWidgets + { + QComboBox *formatCombo; + QSpinBox *lineSizeSpin; + QSpinBox *columnSizeSpin; + QCheckBox *lockLineCheck; + QCheckBox *lockColumnCheck; + QCheckBox *columnCheck; + QComboBox *gridCombo; + QLabel *leftSepLabel; + QLabel *rightSepLabel; + QSpinBox *leftSepWidthSpin; + QSpinBox *rightSepWidthSpin; + QSpinBox *separatorSpin; + QSpinBox *edgeSpin; + QLabel *columnSepLabel; + QSpinBox *columnSepSpin; + + }; + struct SCursorWidgets + { + QCheckBox *blinkCheck; + QSpinBox *blinkSpin; + QLabel *blinkLabel; + QCheckBox *blockCheck; + QCheckBox *thickCheck; + QRadioButton *stopRadio; + QRadioButton *hideRadio; + QRadioButton *nothingRadio; + }; + struct SColorWidgets + { + enum colorType + { + FirstTextBg = 0, + SecondTextBg, + OffsetBg, + InactiveBg, + EvenColumnFg, + OddColumnFg, + NonPrintFg, + OffsetFg, + SecondaryFg, + MarkedBg, + MarkedFg, + CursorBg, + CursorFg, + BookmarkBg, + BookmarkFg, + SeparatorFg, + GridFg, + MAX_COLOR + }; + + QCheckBox *checkSystem; + CColorListBox *colorList; + }; + struct SFontWidgets + { + QCheckBox *checkSystem; + KFontChooser *chooser; + QLineEdit *nonPrintInput; + }; + struct SFileWidgets + { + QComboBox *openCombo; + QCheckBox *gotoOffsetCheck; + QCheckBox *reloadOffsetCheck; + QCheckBox *writeProtectCheck; + QCheckBox *backupCheck; + QCheckBox *discardRecentCheck; + }; + struct SMiscWidgets + { + QSpinBox *undoSpin; + QCheckBox *inputCheck; + QCheckBox *fatalCheck; + QCheckBox *autoCheck; + QCheckBox *insertCheck; + QCheckBox *confirmWrapCheck; + QCheckBox *cursorJumpCheck; + QCheckBox *thresholdCheck; + QCheckBox *bookmarkColumnCheck; + QCheckBox *bookmarkEditorCheck; + QLabel *thresholdLabel; + QSpinBox *thresholdSpin; + }; + + private: + void setupLayoutPage( void ); + void setupCursorPage( void ); + void setupColorPage( void ); + void setupFontPage( void ); + void setupFilePage( void ); + void setupMiscPage( void ); + SDisplayCursor::EFocusMode cursorFocusMode( void ); + + + signals: + void lineSizeChoice( const SDisplayLine &lineSize ); + void layoutChoice( const SDisplayLayout &layout ); + void cursorChoice( const SDisplayCursor &cursor ); + void colorChoice( const SDisplayColor &color ); + void fontChoice( const SDisplayFont &font ); + void miscChoice( const SDisplayMisc &misc ); + void removeRecentFiles( void ); + + private: + SDisplayState mDisplayState; + SLayoutWidgets mLayout; + SCursorWidgets mCursor; + SColorWidgets mColor; + SFontWidgets mFont; + SFileWidgets mFile; + SMiscWidgets mMisc; + bool configChanged; + +}; + + + + + +#endif + + + + + + + diff --git a/khexedit/parts/Makefile.am b/khexedit/parts/Makefile.am new file mode 100644 index 0000000..7e2726b --- /dev/null +++ b/khexedit/parts/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = kbytesedit kpart diff --git a/khexedit/parts/README b/khexedit/parts/README new file mode 100644 index 0000000..a484f1e --- /dev/null +++ b/khexedit/parts/README @@ -0,0 +1,3 @@ +hex editor parts +================== +in each subdirectory one part based on the KHexEdit2 library diff --git a/khexedit/parts/kbytesedit/Makefile.am b/khexedit/parts/kbytesedit/Makefile.am new file mode 100644 index 0000000..b8be127 --- /dev/null +++ b/khexedit/parts/kbytesedit/Makefile.am @@ -0,0 +1,15 @@ +kde_module_LTLIBRARIES = libkbyteseditwidget.la + +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +noinst_HEADERS = kbyteseditwidget.h + +METASOURCES = AUTO + +libkbyteseditwidget_la_SOURCES = kbyteseditwidget.cpp + +libkbyteseditwidget_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module -avoid-version -no-undefined +libkbyteseditwidget_la_LIBADD = ../../lib/libkhexeditcommon.la $(LIB_KPARTS) + +service_DATA = kbyteseditwidget.desktop +servicedir = $(kde_servicesdir) diff --git a/khexedit/parts/kbytesedit/README b/khexedit/parts/kbytesedit/README new file mode 100644 index 0000000..e3aa164 --- /dev/null +++ b/khexedit/parts/kbytesedit/README @@ -0,0 +1,23 @@ +KBytesEdit widget modul +======================= +part of the KHexEdit 2 project (kdenonbeta/khexedit2) +Author/Maintainer: Friedrich W. H. Kossebau + + +description: +------------ +This module delivers a service for the service type "KHexEdit/KBytesEdit". +It is a hex edit widget that operates on an array of chars given by +the programmer. +It serves right now the interfaces +HexColumnInterface, TextColumnInterface, ZoomInterface, ClipBoardInterface. + + +installing: +----------- +Installs the .desktop file describing the service and the module library. + + +usage: +------ +Only official known usage is by KPilot (kdepim/kpilot) for now. \ No newline at end of file diff --git a/khexedit/parts/kbytesedit/kbyteseditwidget.cpp b/khexedit/parts/kbytesedit/kbyteseditwidget.cpp new file mode 100644 index 0000000..4cc91ab --- /dev/null +++ b/khexedit/parts/kbytesedit/kbyteseditwidget.cpp @@ -0,0 +1,319 @@ +/*************************************************************************** + kbyteseditwidget.cpp - description + ------------------- + begin : Fri Aug 29 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +// kde specific +#include +#include +#include +// lib specific +#include "kbytesedit.h" +#include "kbyteseditwidget.h" + + +KBytesEditWidget::KBytesEditWidget( QWidget *parent, const char *name, const QStringList & ) + : QWidget( parent, name) +{ + QHBoxLayout* Layout = new QHBoxLayout( this ); + BytesEdit = new KHE::KBytesEdit( this, "BytesEdit" ); + Layout->addWidget( BytesEdit ); +// connect( _editor, SIGNAL( canUndo(bool) ), this, SIGNAL( canUndo(bool) ) ); + connect( BytesEdit, SIGNAL(copyAvailable( bool )), this, SIGNAL(copyAvailable( bool )) ); +} + + + +void KBytesEditWidget::setData( char *D, int S, int RS, bool KM ) +{ + BytesEdit->setData( D, S, RS, KM ); +} + + +void KBytesEditWidget::setReadOnly( bool RO ) +{ + BytesEdit->setReadOnly( RO ); +} + +void KBytesEditWidget::setMaxDataSize( int MS ) +{ + BytesEdit->setMaxDataSize( MS ); +} + +void KBytesEditWidget::setAutoDelete( bool AD ) +{ + BytesEdit->setAutoDelete( AD ); +} + + +void KBytesEditWidget::setKeepsMemory( bool KM ) +{ + BytesEdit->setKeepsMemory( KM ); +} + + +void KBytesEditWidget::setCursorPosition( int Index ) +{ + BytesEdit->setCursorPosition( Index ); +} + +void KBytesEditWidget::setCoding( KCoding C ) +{ + BytesEdit->setCoding( (KHE::KHexEdit::KCoding) C ); +} + +void KBytesEditWidget::setResizeStyle( KResizeStyle Style ) +{ + BytesEdit->setResizeStyle( (KHE::KHexEdit::KResizeStyle) Style ); +} +int KBytesEditWidget::noOfBytesPerLine() const +{ + return BytesEdit->noOfBytesPerLine(); +} + +KBytesEditWidget::KResizeStyle KBytesEditWidget::resizeStyle() const +{ + return (KResizeStyle)BytesEdit->resizeStyle(); +} +void KBytesEditWidget::setNoOfBytesPerLine( int NoCpL ) +{ + BytesEdit->setNoOfBytesPerLine( NoCpL ); +} + + + +void KBytesEditWidget::setOverwriteOnly( bool b ) +{ + BytesEdit->setOverwriteOnly( b ); +} + + +void KBytesEditWidget::setOverwriteMode( bool b ) +{ + BytesEdit->setOverwriteMode( b ); +} + + +void KBytesEditWidget::setModified( bool b ) +{ + BytesEdit->setModified( b ); +} + + +void KBytesEditWidget::setByteSpacingWidth( int BSW ) +{ + BytesEdit->setByteSpacingWidth( BSW ); +} + +void KBytesEditWidget::setNoOfGroupedBytes( int NoGB ) +{ + BytesEdit->setNoOfGroupedBytes( NoGB ); +} + +void KBytesEditWidget::setGroupSpacingWidth( int GSW ) +{ + BytesEdit->setGroupSpacingWidth( GSW ); +} + +void KBytesEditWidget::setBinaryGapWidth( int BGW ) +{ + BytesEdit->setBinaryGapWidth( BGW ); +} + +void KBytesEditWidget::setEncoding( KEncoding C ) +{ + BytesEdit->setEncoding( (KHE::KHexEdit::KEncoding)C ); +} + +void KBytesEditWidget::setShowUnprintable( bool SU ) +{ + BytesEdit->setShowUnprintable( SU ); +} + +void KBytesEditWidget::setSubstituteChar( QChar SC ) +{ + BytesEdit->setSubstituteChar( SC ); +} + + +char *KBytesEditWidget::data() const +{ + return BytesEdit->data(); +} + +int KBytesEditWidget::dataSize() const +{ + return BytesEdit->dataSize(); +} +int KBytesEditWidget::maxDataSize () const +{ + return BytesEdit->maxDataSize(); +} +bool KBytesEditWidget::isAutoDelete() const +{ + return BytesEdit->isAutoDelete(); +} + +bool KBytesEditWidget::keepsMemory() const +{ + return BytesEdit->keepsMemory(); +} + +bool KBytesEditWidget::isOverwriteMode() const +{ + return BytesEdit->isOverwriteMode(); +} + +bool KBytesEditWidget::isOverwriteOnly() const +{ + return BytesEdit->isOverwriteOnly(); +} + +bool KBytesEditWidget::isModified() const +{ + return BytesEdit->isModified(); +} + +bool KBytesEditWidget::isReadOnly() const +{ + return BytesEdit->isReadOnly(); +} + + +// bool KBytesEditWidget::tabChangesFocus() const +// { +// } + + + +KBytesEditWidget::KCoding KBytesEditWidget::coding() const +{ + return (KCoding)BytesEdit->coding(); +} + +int KBytesEditWidget::byteSpacingWidth() const +{ + return BytesEdit->byteSpacingWidth(); +} + +int KBytesEditWidget::noOfGroupedBytes() const +{ + return BytesEdit->noOfGroupedBytes(); +} + +int KBytesEditWidget::groupSpacingWidth() const +{ + return BytesEdit->groupSpacingWidth(); +} + +int KBytesEditWidget::binaryGapWidth() const +{ + return BytesEdit->binaryGapWidth(); +} + +bool KBytesEditWidget::showUnprintable() const +{ + return BytesEdit->showUnprintable(); +} + +QChar KBytesEditWidget::substituteChar() const +{ + return BytesEdit->substituteChar(); +} + +KBytesEditWidget::KEncoding KBytesEditWidget::encoding() const +{ + return (KEncoding)BytesEdit->encoding(); +} + + +bool KBytesEditWidget::hasSelectedData() const +{ + return BytesEdit->hasSelectedData(); +} + + +void KBytesEditWidget::repaintRange( int i1, int i2 ) +{ + BytesEdit->repaintRange( i1, i2 ); +} + + +void KBytesEditWidget::insert( const QByteArray &D ) +{ + BytesEdit->insert( D ); +} + + +void KBytesEditWidget::selectAll( bool Select ) +{ + BytesEdit->selectAll( Select ); +} + + // clipboard interface +void KBytesEditWidget::copy() +{ + BytesEdit->copy(); +} + +void KBytesEditWidget::cut() +{ + BytesEdit->cut(); +} + +void KBytesEditWidget::paste() +{ + BytesEdit->paste(); +} + +// zooming interface +void KBytesEditWidget::zoomIn( int PointInc ) +{ + BytesEdit->zoomIn( PointInc ); +} + +void KBytesEditWidget::zoomIn() +{ + BytesEdit->zoomIn(); +} + +void KBytesEditWidget::zoomOut( int PointDec ) +{ + BytesEdit->zoomOut( PointDec ); +} + +void KBytesEditWidget::zoomOut() +{ + BytesEdit->zoomOut(); +} + +void KBytesEditWidget::zoomTo( int PointSize ) +{ + BytesEdit->zoomTo( PointSize ); +} + +void KBytesEditWidget::unZoom() +{ + BytesEdit->unZoom(); +} + + +typedef K_TYPELIST_1( KBytesEditWidget ) Product; +K_EXPORT_COMPONENT_FACTORY( libkbyteseditwidget, KGenericFactory( "kbytesedit" ) ) +//K_EXPORT_COMPONENT_FACTORY( libkbyteseditwidget, KGenericFactory ) + +#include "kbyteseditwidget.moc" diff --git a/khexedit/parts/kbytesedit/kbyteseditwidget.desktop b/khexedit/parts/kbytesedit/kbyteseditwidget.desktop new file mode 100644 index 0000000..4a050a6 --- /dev/null +++ b/khexedit/parts/kbytesedit/kbyteseditwidget.desktop @@ -0,0 +1,52 @@ +[Desktop Entry] +Type=Service +Name=BytesEdit Widget +Name[ar]=كائن BytesEdit +Name[bg]=Модул за двоично редактиране на файлове +Name[bs]=BytesEdit grafički element +Name[ca]=Estri BytesEdit +Name[cy]=Celfigyn GolyguBeit +Name[de]=BytesEdit-Bedienelement +Name[el]=Γραφικό συστατικό BytesEdit +Name[eo]=BytesEdit-fenestraĵo +Name[es]=Ventana de edición de bytes +Name[et]=Baitide redigeerimise komponent +Name[eu]=Byteak Editatzeko Widget-a +Name[fa]=عنصر ویرایش بایت +Name[fi]=BytesEdit käyttöliittymäkomponentti +Name[fr]=Composant éditeur binaire +Name[ga]=Giuirléid BytesEdit +Name[he]=פריט עורך הביטויים הסדירים +Name[hi]=बाइट्स-एडिट विजेट +Name[hu]=BytesEdit grafikus elem +Name[is]=Græja til að sýsla með bætaskrár +Name[it]=Elemento grafico editor di byte +Name[ja]=バイトエディットウィジェット +Name[kk]=Бинарлы деректерді өңдеу бөлшегі +Name[km]=វត្ថុមើលឃើញ BytesEdit +Name[lt]=BytesEdit valdiklis +Name[mk]=BytesEdit - графичка контрола +Name[nb]=BytesEdit skjermelement +Name[nds]=BytesEdit-Bedeenelement +Name[ne]=बाइट सम्पादन विजेट +Name[nn]=BytesEdit-skjermelement +Name[pa]=ਬਾਈਟ ਸੋਧ ਸਹਾਇਕ +Name[pl]=Okienko BytesEdit +Name[pt]=Editor de Bytes +Name[pt_BR]=Widget do Editor de Bytes +Name[ro]=Componentă de editare octeţi +Name[ru]=Виджет редактирования двоичных данных +Name[sk]=Prvok BytesEdit +Name[sl]=Gradnik BytesEdit +Name[sr]=Контрола за бинарно уређивање +Name[sr@Latn]=Kontrola za binarno uređivanje +Name[sv]=Grafisk komponent för att redigera binärdata +Name[ta]= பைட்ஸ்தொகுப்பு சாளரம் +Name[tg]=Элементи Таҳрири Додаҳои Дуӣ +Name[uk]=Віджет побайтового редагування +Name[zh_CN]=字节编辑部件 +Name[zh_TW]=位元編輯器元件 +X-KDE-Library=libkbyteseditwidget +InitialPreference=2 +ServiceTypes=KHexEdit/KBytesEdit + diff --git a/khexedit/parts/kbytesedit/kbyteseditwidget.h b/khexedit/parts/kbytesedit/kbyteseditwidget.h new file mode 100644 index 0000000..78e4dba --- /dev/null +++ b/khexedit/parts/kbytesedit/kbyteseditwidget.h @@ -0,0 +1,185 @@ +/*************************************************************************** + kbyteseditwidget.h - description + ------------------- + begin : Fri Aug 29 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KBYTESEDITWIDGET_H +#define KBYTESEDITWIDGET_H + +// qt specific +#include +// kde specific +#include +#include +#include +#include +#include + + +namespace KHE { +class KBytesEdit; +} + +/** + hex editor/viewer. + + @author Friedrich W. H. Kossebau + @version 0.1 + **/ +class KBytesEditWidget : public QWidget, public KHE::BytesEditInterface, + public KHE::ValueColumnInterface, public KHE::CharColumnInterface, + public KHE::ZoomInterface, public KHE::ClipboardInterface +{ + Q_OBJECT + + public: + /** constructor API as demanded by KGenericFactory */ + KBytesEditWidget( QWidget *parent, const char *name, const QStringList & = QStringList() ); + + public: // bytesedit interface + /** hands over to the editor a new byte array. + * If there exists an old one and autodelete is set the old one gets deleted. + * @param D pointer to memory + * @param DS_ size of used memory + * @param RS_ real size of the memory + * @param KM keep the memory on resize (RS_ is the maximum size) + */ + virtual void setData( char *D, int DS_, int RS_ = -1, bool KM = true ); + + /** sets the maximal size of the actual byte array. If the actual array is already larger + * it will not be modified but there can be only done non-inserting actions + * until the array's is below the limit + */ + virtual void setMaxDataSize( int MS ); + /** sets whether the array should be deleted on the widget's end or if a new array is set. + * Default is false + */ + virtual void setAutoDelete( bool AD = true ); + /** sets whether the memory given by setData or in the constructor should be kept on resize + */ + virtual void setKeepsMemory( bool KM = true ); + /** */ + virtual char *data() const; + /** returns the size of the actual byte array */ + virtual int dataSize() const; + /** returns the maximal allowed size for the byte array */ + virtual int maxDataSize () const; + /** returns whether autodelete is set for the byte array */ + virtual bool isAutoDelete() const; + /** returns whether the memory of the byte array is kept */ + virtual bool keepsMemory() const; + /** */ + virtual bool isOverwriteMode() const; + virtual bool isOverwriteOnly() const; + virtual bool isReadOnly() const; + virtual bool isModified() const; + /** repaint the indizes from i1 to i2 */ + virtual void repaintRange( int i1, int i2 ); + + public: // cursor interface + /** */ + virtual void setCursorPosition( int Index ); +// virtual bool tabChangesFocus() const; + + public: // layout interface ?? + /** sets the resizestyle for the value column. Default is KHE::FullSizeUsage */ + virtual void setResizeStyle( KResizeStyle Style ); + /** sets the number of bytes per line, switching the resize style to KHE::NoResize */ + virtual void setNoOfBytesPerLine( int NoCpL ); + + virtual int noOfBytesPerLine() const; + virtual KResizeStyle resizeStyle() const; + + public: // value column + /** sets the format of the value column. Default is KHE::HexadecimalCoding */ + virtual void setCoding( KCoding C ); + /** sets the spacing between the bytes in pixels */ + virtual void setByteSpacingWidth( int BSW ); + /** sets the numbers of grouped bytes, 0 means no grouping, Default is 4 */ + virtual void setNoOfGroupedBytes( int NoGB ); + /** sets the spacing between the groups in pixels */ + virtual void setGroupSpacingWidth( int GSW ); + /** sets the spacing in the middle of a binary byte in the value column + * @param BGW spacing in the middle of a binary in pixels + */ + virtual void setBinaryGapWidth( int BGW ); + + virtual KCoding coding() const; + virtual int byteSpacingWidth() const; + + virtual int noOfGroupedBytes() const; + virtual int groupSpacingWidth() const; + virtual int binaryGapWidth() const; + + public: // char column + /** sets whether "unprintable" chars (>32) should be displayed in the char column + * with their corresponding character. + * @param SU + * returns true if there was a change + */ + virtual void setShowUnprintable( bool SU = true ); + /** sets the substitute character for "unprintable" chars + * returns true if there was a change + */ + virtual void setSubstituteChar( QChar SC ); + /** sets the encoding of the char column. Default is KHE::LocalEncoding. + * If the encoding is not available the format will not be changed. */ + virtual void setEncoding( KEncoding C ); + /** returns true if "unprintable" chars (>32) are displayed in the char column + * with their corresponding character, default is false + */ + virtual bool showUnprintable() const; + /** returns the actually used substitute character for "unprintable" chars, default is '.' */ + virtual QChar substituteChar() const; + /** */ + virtual KEncoding encoding() const; + + public: // edit interface + /** */ + virtual void insert( const QByteArray &D ); + /** de-/selects all data */ + virtual void selectAll( bool select ); + /** returns true if there is a selected range in the array */ + virtual bool hasSelectedData() const; + + public slots: + // bytesedit interface + virtual void setReadOnly( bool RO = true ); + virtual void setOverwriteOnly( bool b ); + virtual void setOverwriteMode( bool b ); + virtual void setModified( bool b ); + + // clipboard interface + virtual void copy(); + virtual void cut(); + virtual void paste(); + + // zooming interface + virtual void zoomIn( int PointInc ); + virtual void zoomIn(); + virtual void zoomOut( int PointDec ); + virtual void zoomOut(); + virtual void zoomTo( int PointSize ); + virtual void unZoom(); + + signals: + // clipboard interface + virtual void copyAvailable( bool Really ); + + protected: + KHE::KBytesEdit* BytesEdit; +}; + +#endif diff --git a/khexedit/parts/kpart/Makefile.am b/khexedit/parts/kpart/Makefile.am new file mode 100644 index 0000000..42d9c77 --- /dev/null +++ b/khexedit/parts/kpart/Makefile.am @@ -0,0 +1,21 @@ +kde_module_LTLIBRARIES = libkhexedit2part.la + +INCLUDES = -I$(srcdir)/../../lib $(all_includes) + +noinst_HEADERS = khepart.h khebrowserextension.h khepartfactory.h + +METASOURCES = AUTO + +libkhexedit2part_la_SOURCES = khepart.cpp khebrowserextension.cpp khepartfactory.cpp + +libkhexedit2part_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module -no-undefined +libkhexedit2part_la_LIBADD = ../../lib/libkhexeditcommon.la $(LIB_KPARTS) $(LIB_KIO) + +partdesktop_DATA = khexedit2part.desktop +partdesktopdir = $(kde_servicesdir) + +partrc_DATA = khexedit2partui.rc +partrcdir = $(kde_datadir)/khexedit2part + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/khexedit2part.pot diff --git a/khexedit/parts/kpart/khebrowserextension.cpp b/khexedit/parts/kpart/khebrowserextension.cpp new file mode 100644 index 0000000..d4fc3f3 --- /dev/null +++ b/khexedit/parts/kpart/khebrowserextension.cpp @@ -0,0 +1,95 @@ +/*************************************************************************** + khebrowserextension.cpp - description + ------------------- + begin : Di Nov 16 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// qt specific +#include +// app specific +#include "khexedit.h" +#include "khepart.h" +#include "khebrowserextension.h" + +using namespace KHE; + + +KHexEditBrowserExtension::KHexEditBrowserExtension( KHexEditPart *P ) + : KParts::BrowserExtension( P, "khexeditpartbrowserextension" ), + HexEditPart( P ) +{ + connect( HexEditPart->HexEdit, SIGNAL( selectionChanged() ), this, SLOT( slotSelectionChanged() ) ); +} + +void KHexEditBrowserExtension::copy() +{ + HexEditPart->HexEdit->copy(); +} + + +void KHexEditBrowserExtension::slotSelectionChanged() +{ + emit enableAction( "copy", HexEditPart->HexEdit->hasSelectedData() ); +} + + +void KHexEditBrowserExtension::saveState( QDataStream &stream ) +{ + KParts::BrowserExtension::saveState( stream ); + + KHexEdit *HexEdit = HexEditPart->HexEdit; + + stream << (int)HexEdit->offsetColumnVisible() << HexEdit->visibleBufferColumns() + << (int)HexEdit->resizeStyle() << (int)HexEdit->coding() + << HexEdit->encodingName() << (int)HexEdit->showUnprintable() + << HexEdit->contentsX() << HexEdit->contentsY() + << HexEdit->cursorPosition() << (int)HexEdit->isCursorBehind() + << HexEdit->cursorColumn(); +} + + +void KHexEditBrowserExtension::restoreState( QDataStream &stream ) +{ + KParts::BrowserExtension::restoreState( stream ); + + int OffsetColumnVisible; + int VisibleBufferColumns; + int ResizeStyle; + int Coding; + QString EncodingName; + int ShowUnprintable; + int x, y; + int Position; + int CursorBehind; + int CursorColumn; + + stream >> OffsetColumnVisible >> VisibleBufferColumns >> ResizeStyle >> Coding >> EncodingName >> ShowUnprintable + >> x >> y >> Position >> CursorBehind >> CursorColumn; + + KHexEdit *HexEdit = HexEditPart->HexEdit; + + HexEdit->toggleOffsetColumn( OffsetColumnVisible ); + HexEdit->showBufferColumns( VisibleBufferColumns ); + HexEdit->setResizeStyle( (KHexEdit::KResizeStyle)ResizeStyle ); + HexEdit->setCoding( (KHexEdit::KCoding)Coding ); + HexEdit->setEncoding( EncodingName ); + HexEdit->setShowUnprintable( ShowUnprintable ); + HexEdit->setContentsPos( x, y ); + HexEdit->setCursorPosition( Position, CursorBehind ); + HexEdit->setCursorColumn( (KHexEdit::KBufferColumnId)CursorColumn ); + + HexEditPart->fitActionSettings(); +} + +#include "khebrowserextension.moc" diff --git a/khexedit/parts/kpart/khebrowserextension.h b/khexedit/parts/kpart/khebrowserextension.h new file mode 100644 index 0000000..4638944 --- /dev/null +++ b/khexedit/parts/kpart/khebrowserextension.h @@ -0,0 +1,58 @@ +/*************************************************************************** + khebrowserextension.h - description + ------------------- + begin : Di Nov 16 2004 + copyright : (C) 2004 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHEBROWSEREXTENSION_H +#define KHEBROWSEREXTENSION_H + +// kde specific +#include + +namespace KHE +{ + +// forward declaration +class KHexEditPart; + +/** + * @short Extension for better support for embedding in browsers + * @author Friedrich W. H. Kossebau + */ +class KHexEditBrowserExtension : public KParts::BrowserExtension +{ + Q_OBJECT + + public: + KHexEditBrowserExtension( KHexEditPart *P ); + + public: // KParts::BrowserExtension API + virtual void saveState( QDataStream &stream ); + virtual void restoreState( QDataStream &stream ); + + public slots: + /** copy text to clipboard */ + void copy(); + + /** selection has changed */ + void slotSelectionChanged(); + + protected: + KHexEditPart *HexEditPart; +}; + +} + +#endif diff --git a/khexedit/parts/kpart/khepart.cpp b/khexedit/parts/kpart/khepart.cpp new file mode 100644 index 0000000..e9b9ed5 --- /dev/null +++ b/khexedit/parts/kpart/khepart.cpp @@ -0,0 +1,213 @@ +/*************************************************************************** + khepart.cpp - description + ------------------- + begin : Don Jun 19 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// kde specific +#include +//#include +#include +#include +//#include +// app specific +#include "khexedit.h" +#include "kcharcodec.h" +#include "khepartfactory.h" +#include "khebrowserextension.h" +#include "khepart.h" + +using namespace KHE; + +static const char RCFileName[] = "khexedit2partui.rc"; + +KHexEditPart::KHexEditPart( QWidget *ParentWidget, const char *WidgetName, + QObject *Parent, const char *Name, + bool BrowserViewWanted ) + : KParts::ReadOnlyPart( Parent, Name ) +{ + setInstance( KHexEditPartFactory::instance() ); + + HexEdit = new KHexEdit( &Wrapping, ParentWidget, WidgetName ); + HexEdit->setNoOfBytesPerLine( 16 ); + HexEdit->setBufferSpacing( 3, 4, 10 ); + HexEdit->setShowUnprintable( false ); + + // notify the part that this is our internal widget + setWidget( HexEdit ); + + setupActions( BrowserViewWanted ); + + if( CopyAction ) + { + connect( HexEdit, SIGNAL(copyAvailable(bool)), CopyAction,SLOT(setEnabled(bool)) ); + connect( HexEdit, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()) ); + CopyAction->setEnabled( false ); + } + + // plugin to browsers + if( BrowserViewWanted ) + new KHexEditBrowserExtension( this ); +} + + +KHexEditPart::~KHexEditPart() +{ +} + +/* +void KHexEditPart::setupTools( bool BrowserViewWanted ) +{ + if( !BrowserViewWanted ) new KClipboardTool( this ); + + new KZoomToolet( this ); + new KSelectToolet( this ); + new KHEValueCodingToolet( this ); + new KHECharEncodingToolet( this ); + new KHEResizeStyleToolet( this ); + new KHEColumnToggleToolet( this ); +} +*/ +void KHexEditPart::setupActions( bool BrowserViewWanted ) +{ + KActionCollection *AC = actionCollection(); + // create our actions + CopyAction = BrowserViewWanted ? 0 : KStdAction::copy( HexEdit, SLOT(copy()), AC ); + + KStdAction::selectAll( this, SLOT(slotSelectAll()), AC ); + KStdAction::deselect( this, SLOT(slotUnselect()), AC ); + + // value encoding + CodingAction = new KSelectAction( i18n("&Value Coding"), 0, AC, "view_valuecoding" ); + QStringList List; + List.append( i18n("&Hexadecimal") ); + List.append( i18n("&Decimal") ); + List.append( i18n("&Octal") ); + List.append( i18n("&Binary") ); + CodingAction->setItems( List ); + connect( CodingAction, SIGNAL(activated(int)), this, SLOT(slotSetCoding(int)) ); + + // document encoding + EncodingAction = new KSelectAction( i18n("&Char Encoding"), 0, AC, "view_charencoding" ); + EncodingAction->setItems( KCharCodec::codecNames() ); + connect( EncodingAction, SIGNAL(activated(int)), this, SLOT(slotSetEncoding(int)) ); + + ShowUnprintableAction = new KToggleAction( i18n("Show &Unprintable Chars (<32)"), 0, this, SLOT(slotSetShowUnprintable()), actionCollection(), "view_showunprintable" ); + + KStdAction::zoomIn( HexEdit, SLOT(zoomIn()), actionCollection() ); + KStdAction::zoomOut( HexEdit, SLOT(zoomOut()), actionCollection() ); + + // resize style + ResizeStyleAction = new KSelectAction( i18n("&Resize Style"), 0, AC, "resizestyle" ); + List.clear(); + List.append( i18n("&No Resize") ); + List.append( i18n("&Lock Groups") ); + List.append( i18n("&Full Size Usage") ); + ResizeStyleAction->setItems( List ); + connect( ResizeStyleAction, SIGNAL(activated(int)), this, SLOT(slotSetResizeStyle(int)) ); + + ShowOffsetColumnAction = new KToggleAction( i18n("&Line Offset"), Key_F11, this, SLOT(slotToggleOffsetColumn()), AC, "view_lineoffset" ); + + // show buffer columns + ToggleColumnsAction = new KSelectAction( i18n("&Columns"), 0, AC, "togglecolumns" ); + List.clear(); + List.append( i18n("&Values Column") ); + List.append( i18n("&Chars Column") ); + List.append( i18n("&Both Columns") ); + ToggleColumnsAction->setItems( List ); + connect( ToggleColumnsAction, SIGNAL(activated(int)), this, SLOT(slotToggleValueCharColumns(int)) ); + + fitActionSettings(); + + // set our XML-UI resource file + setXMLFile( RCFileName ); +} + + +void KHexEditPart::fitActionSettings() +{ + ShowOffsetColumnAction->setChecked( HexEdit->offsetColumnVisible() ); + ShowUnprintableAction->setChecked( HexEdit->showUnprintable() ); + + CodingAction->setCurrentItem( (int)HexEdit->coding() ); + EncodingAction->setCurrentItem( KCharCodec::codecNames().findIndex(HexEdit->encodingName()) ); + + ResizeStyleAction->setCurrentItem( (int)HexEdit->resizeStyle() ); + + ToggleColumnsAction->setCurrentItem( (int)HexEdit->visibleBufferColumns()-1 ); +} + + +bool KHexEditPart::openFile() +{ + Wrapping.open( m_file ); + HexEdit->setDataBuffer( &Wrapping ); + HexEdit->setCursorPosition( 0 ); + HexEdit->selectAll( false ); + + return true; +} + + + +void KHexEditPart::slotSelectionChanged() +{ + bool State = HexEdit->hasSelectedData(); + CopyAction->setEnabled( State ); +} + + +void KHexEditPart::slotSelectAll() +{ + HexEdit->selectAll( true ); +} + + +void KHexEditPart::slotUnselect() +{ + HexEdit->selectAll( false ); +} + + +void KHexEditPart::slotSetCoding( int Coding ) +{ + HexEdit->setCoding( (KHexEdit::KCoding)Coding ); +} + +void KHexEditPart::slotSetShowUnprintable() +{ + HexEdit->setShowUnprintable( ShowUnprintableAction->isChecked() ); +} + +void KHexEditPart::slotToggleOffsetColumn() +{ + HexEdit->toggleOffsetColumn( ShowOffsetColumnAction->isChecked() ); +} + +void KHexEditPart::slotSetResizeStyle( int ResizeStyle ) +{ + HexEdit->setResizeStyle( (KHexEdit::KResizeStyle)ResizeStyle ); +} + +void KHexEditPart::slotSetEncoding( int Encoding ) +{ + HexEdit->setEncoding( KCharCodec::codecNames()[Encoding] ); +} + +void KHexEditPart::slotToggleValueCharColumns( int VisibleColumns) +{ + HexEdit->showBufferColumns( VisibleColumns+1 ); +} + +#include "khepart.moc" diff --git a/khexedit/parts/kpart/khepart.h b/khexedit/parts/kpart/khepart.h new file mode 100644 index 0000000..54befa0 --- /dev/null +++ b/khexedit/parts/kpart/khepart.h @@ -0,0 +1,95 @@ +/*************************************************************************** + khepart.h - description + ------------------- + begin : Don Jun 19 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHEPART_H +#define KHEPART_H + +// kde specific +#include +// app specific +#include "kbigbuffer.h" + +// forward declarations +class KRadioAction; +class KToggleAction; +class KSelectAction; + +namespace KHE +{ + +// forward declarations +class KHexEdit; + +/** + * This is a "Part". It that does all the real work in a KPart + * application. + * + * @short Main Part + * @author Friedrich W. H. Kossebau + * @version 0.1.0 + */ +class KHexEditPart : public KParts::ReadOnlyPart +{ + Q_OBJECT + + friend class KHexEditBrowserExtension; + + public: + KHexEditPart( QWidget *ParentWidget, const char *WidgetName, QObject *Parent, const char *Name, + bool BrowserViewWanted ); + virtual ~KHexEditPart(); + + + protected: // KParts::ReadOnlyPart API + virtual bool openFile(); + + protected: + void setupActions( bool BrowserViewWanted ); + void fitActionSettings(); + + protected slots: + // used to catch changes in the HexEdit widget + void slotSelectionChanged(); + protected slots: // action slots + void slotSelectAll(); + void slotUnselect(); + void slotSetCoding( int Coding ); + void slotSetEncoding( int Encoding ); + void slotSetShowUnprintable(); + void slotSetResizeStyle( int Style ); + void slotToggleOffsetColumn(); + void slotToggleValueCharColumns( int VisibleColunms ); + + private: + KHexEdit *HexEdit; + KBigBuffer Wrapping; + + // edit menu + KAction *CopyAction; + // view menu + KSelectAction *CodingAction; + KSelectAction *EncodingAction; + KToggleAction *ShowUnprintableAction; + // settings menu + KSelectAction *ResizeStyleAction; + KToggleAction *ShowOffsetColumnAction; + KSelectAction *ToggleColumnsAction; +}; + +} + +#endif diff --git a/khexedit/parts/kpart/khepartfactory.cpp b/khexedit/parts/kpart/khepartfactory.cpp new file mode 100644 index 0000000..f85d8a9 --- /dev/null +++ b/khexedit/parts/kpart/khepartfactory.cpp @@ -0,0 +1,90 @@ +/*************************************************************************** + khepartfactory.h - description + ------------------- + begin : Don Jun 19 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +// kde specific +#include +#include +#include +// app specific +#include "khepart.h" +#include "khepartfactory.h" + +using namespace KHE; + +// Part +static const char PartId[] = "khexedit2part"; +static const char PartName[] = I18N_NOOP("KHexEdit2Part"); +static const char PartDescription[] = I18N_NOOP("Embedded hex editor"); +static const char PartVersion[] = "0.2.0"; +static const char PartCopyright[] = "(C) 2003-2004 Friedrich W. H. Kossebau"; +// Author +static const char FWHKName[] = "Friedrich W. H. Kossebau"; +static const char FWHKTask[] = I18N_NOOP("Author"); +static const char FWHKEmailAddress[] = "Friedrich.W.H@Kossebau.de"; +// static const char FWHKWebAddress[] = "http://www.kossebau.de"; + + +KInstance* KHexEditPartFactory::s_instance = 0L; +KAboutData* KHexEditPartFactory::s_about = 0L; + + +KHexEditPartFactory::KHexEditPartFactory() + : KParts::Factory() +{ +} + + +KHexEditPartFactory::~KHexEditPartFactory() +{ + delete s_instance; + delete s_about; + + s_instance = 0; +} + + +KParts::Part* KHexEditPartFactory::createPartObject( QWidget *ParentWidget, const char *WidgetName, + QObject *Parent, const char *Name, + const char *CN, const QStringList &/*args*/ ) +{ + QCString Classname( CN ); + bool BrowserViewWanted = ( Classname == "Browser/View" ); + //bool ReadOnlyWanted = (BrowserViewWanted || ( Classname == "KParts::ReadOnlyPart" )); + + // Create an instance of our Part + KHexEditPart* HexEditPart = new KHexEditPart( ParentWidget, WidgetName, Parent, Name, BrowserViewWanted ); + + return HexEditPart; +} + + +KInstance* KHexEditPartFactory::instance() +{ + if( !s_instance ) + { + s_about = new KAboutData( PartId, PartName, PartVersion, PartDescription, + KAboutData::License_GPL_V2, PartCopyright, 0, 0, FWHKEmailAddress ); + s_about->addAuthor( FWHKName, FWHKTask, FWHKEmailAddress ); + s_instance = new KInstance( s_about ); + } + return s_instance; +} + + +K_EXPORT_COMPONENT_FACTORY( libkhexedit2part, KHexEditPartFactory ) + +#include "khepartfactory.moc" diff --git a/khexedit/parts/kpart/khepartfactory.h b/khexedit/parts/kpart/khepartfactory.h new file mode 100644 index 0000000..7cd6c7e --- /dev/null +++ b/khexedit/parts/kpart/khepartfactory.h @@ -0,0 +1,47 @@ +/*************************************************************************** + khepartfactory.h - description + ------------------- + begin : Don Jun 19 2003 + copyright : (C) 2003 by Friedrich W. H. Kossebau + email : Friedrich.W.H@Kossebau.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License version 2 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + + +#ifndef KHEPARTFACTORY_H +#define KHEPARTFACTORY_H + +#include + +class KInstance; +class KAboutData; + + +class KHexEditPartFactory : public KParts::Factory +{ + Q_OBJECT + + public: + KHexEditPartFactory(); + virtual ~KHexEditPartFactory(); + + public: + virtual KParts::Part* createPartObject( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const char *classname, const QStringList &args ); + static KInstance* instance(); + + + private: + static KInstance* s_instance; + static KAboutData* s_about; +}; + +#endif diff --git a/khexedit/parts/kpart/khexedit2part.desktop b/khexedit/parts/kpart/khexedit2part.desktop new file mode 100644 index 0000000..60f4132 --- /dev/null +++ b/khexedit/parts/kpart/khexedit2part.desktop @@ -0,0 +1,101 @@ +[Desktop Entry] +Type=Service +Icon=khexedit +Name=Embedded Binary Viewer +Name[ar]=عارض ثنائى مدمج +Name[bg]=Вграден двоичен преглед +Name[br]=Gweler HTML enframmus +Name[bs]=Ugrađeni preglednik binarnih datoteka +Name[ca]=Visor binari encastat +Name[cs]=Zabudovaný binární prohlížeč +Name[da]=Indlejret binær fremviser +Name[de]=Eingebettetes Anzeigeprogramm für Binärdateien +Name[el]=Ενσωματωμένος προβολέας δυαδικών αρχείων +Name[eo]=Enkonstruita duum-rigardilo +Name[es]=Visor binario empotrado +Name[et]=Põimitud binaarfailide näitaja +Name[eu]=Ikusgailu binario txertagarria +Name[fa]=مشاهده‌گر دوگانی نهفته +Name[fi]=Sulautettu binääritiedostojen näytin +Name[fr]=Afficheur de binaires intégré +Name[ga]=Amharcán Leabaithe Dénártha +Name[he]=עורך הקסאדצימלי משובץ +Name[hu]=Beágyazott nézegető bináris fájlokhoz +Name[is]=Innbyggður tvíundakerfisskoðari +Name[it]=Visore binario integrabile +Name[ja]=埋め込みバイナリビューア +Name[kk]=Ендірілетін бинарлық қарау құралы +Name[km]=កម្មវិធី​មើល​គោលពីរ​ដែល​បាន​បង្កប់ +Name[lt]=Įdedama dvejetainių duomenų žiūryklė +Name[nb]=Innebygget Binærfremviser +Name[nds]=Inbett Bineerdaten-Kieker +Name[ne]=सम्मिलित बाइनरी दर्शक +Name[nl]=Ingebedde binaire viewer +Name[nn]=Innebygd binærframvisar +Name[pa]=ਸ਼ਾਮਲ ਬਾਈਨਰੀ ਦਰਸ਼ਕ +Name[pl]=Wbudowana przeglądarka binarna +Name[pt]=Visualizador Binário Incorporado +Name[pt_BR]=Visualizador Binário Embutido +Name[ru]=Компонент просмотра двоичных данных +Name[sk]=Vložený binárny prezerač +Name[sl]=Vgrajen binarni pregledovalnik +Name[sr]=Уградиви приказивач бинарног +Name[sr@Latn]=Ugradivi prikazivač binarnog +Name[sv]=Inbäddad binärvisning +Name[ta]=உட்பொதிந்த இருநிலை காட்சியாளன் +Name[tr]=Gömülü İkili dosya Görüntüleyici +Name[uk]=Вбудований переглядач для двійкових даних +Name[zh_CN]=嵌入式二进制查看器 +Name[zh_TW]=嵌入式二進位顯示器 +Comment=Embedded Binary Viewer +Comment[ar]=عارض ثنائى مدمج +Comment[bg]=Вградена програма за преглед на двоични файлове +Comment[br]=Gweler HTML enframmus +Comment[bs]=Ugrađeni preglednik binarnih datoteka +Comment[ca]=Visor binari encastat +Comment[cs]=Zabudovaný binární prohlížeč +Comment[da]=Indlejret binær fremviser +Comment[de]=Eingebettetes Anzeigeprogramm für Binärdateien +Comment[el]=Ενσωματωμένος προβολέας δυαδικών αρχείων +Comment[eo]=Enkonstruita duum-rigardilo +Comment[es]=Visor binario empotrado +Comment[et]=Põimitud binaarfailide näitaja +Comment[eu]=Ikusgailu binario txertagarria +Comment[fa]=مشاهده‌گر دوگانی نهفته +Comment[fi]=Sulautettu binääritiedostojen näytin +Comment[fr]=Afficheur de binaires intégré +Comment[ga]=Amharcán Leabaithe Dénártha +Comment[he]=עורך הקסאדצימלי משובץ +Comment[hu]=Beágyazott fájlmegjelenítő bináris fájlokhoz +Comment[is]=Innbyggður tvíundakerfisskoðari +Comment[it]=Visore binario integrabile +Comment[ja]=埋め込みバイナリビューア +Comment[ka]=ჩაშენებული ბინარული დამთვალიერებელი +Comment[kk]=Ендірілетін бинарлық қарау құралы +Comment[km]=កម្មវិធី​មើល​គោលពីរ​ដែល​បាន​បង្កប់ +Comment[lt]=Įdedama dvejetainių duomenų žiūryklė +Comment[nb]=Innebygget Binærfremviser +Comment[nds]=Inbett Bineerdaten-Kieker +Comment[ne]=सम्मिलित बाइनरी दर्शक +Comment[nl]=Ingebedde binaire viewer +Comment[nn]=Innebygd binærframvisar +Comment[pa]=ਸ਼ਾਮਲ ਬਾਈਨਰੀ ਦਰਸ਼ਕ +Comment[pl]=Wbudowana przeglądarka binarna +Comment[pt]=Visualizador Binário Incorporado +Comment[pt_BR]=Visualizador Binário Embutido +Comment[ru]=Компонент просмотра двоичных данных +Comment[sk]=Vložený binárny prezerač +Comment[sl]=Vgrajen binarni pregledovalnik +Comment[sr]=Уградиви приказивач бинарног +Comment[sr@Latn]=Ugradivi prikazivač binarnog +Comment[sv]=Inbäddad binärvisning +Comment[ta]=உட்பொதிந்த இருநிலை காட்சியாளன் +Comment[tr]=Gömülü İkili dosya Görüntüleyici +Comment[uk]=Вбудований переглядач для двійкових даних +Comment[zh_CN]=嵌入式二进制查看器 +Comment[zh_TW]=嵌入式二進位顯示器 +#MimeType=all/allfiles +MimeType=application/octet-stream +ServiceTypes=KParts/ReadOnlyPart,Browser/View +#,KParts/ReadWritePart +X-KDE-Library=libkhexedit2part diff --git a/khexedit/parts/kpart/khexedit2partui.rc b/khexedit/parts/kpart/khexedit2partui.rc new file mode 100644 index 0000000..82b40eb --- /dev/null +++ b/khexedit/parts/kpart/khexedit2partui.rc @@ -0,0 +1,42 @@ + + + + &Edit + + + + + &View + + + + + + + + + + + &Settings + + + + + + +Main Toolbar + + + + + + + + + + + + + + + diff --git a/khexedit/pics/Makefile.am b/khexedit/pics/Makefile.am new file mode 100644 index 0000000..0dd7a3f --- /dev/null +++ b/khexedit/pics/Makefile.am @@ -0,0 +1,3 @@ +toolbar_DATA = hexwrite.png hexdrag.png hexmask.png +toolbardir = $(kde_datadir)/khexedit/pics + diff --git a/khexedit/pics/hexdrag.png b/khexedit/pics/hexdrag.png new file mode 100644 index 0000000..1459f4f Binary files /dev/null and b/khexedit/pics/hexdrag.png differ diff --git a/khexedit/pics/hexmask.png b/khexedit/pics/hexmask.png new file mode 100644 index 0000000..69e71e5 Binary files /dev/null and b/khexedit/pics/hexmask.png differ diff --git a/khexedit/pics/hexwrite.png b/khexedit/pics/hexwrite.png new file mode 100644 index 0000000..a408a03 Binary files /dev/null and b/khexedit/pics/hexwrite.png differ diff --git a/khexedit/printdialogpage.cc b/khexedit/printdialogpage.cc new file mode 100644 index 0000000..ecc0a90 --- /dev/null +++ b/khexedit/printdialogpage.cc @@ -0,0 +1,386 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + + +#include "printdialogpage.h" + +LayoutDialogPage::LayoutDialogPage( QWidget *parent, const char *name ) + : KPrintDialogPage( parent, name ) +{ + mConfig = 0; + setTitle( i18n( "Page Layout" ) ); + setupLayoutPage(); + + readConfiguration(); +} + + +LayoutDialogPage::~LayoutDialogPage( void ) +{ + writeConfiguration(); + + delete mConfig; mConfig = 0; +} + + +void LayoutDialogPage::setupLayoutPage( void ) +{ + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( this, 0, 6 /*KDialog::mSpacingSize*/ ); + if( topLayout == 0 ) { return; } + + text = i18n("Margins [millimeter]"); + QButtonGroup *group = new QButtonGroup( text, this ); + if( group == 0 ) { return; } + topLayout->addWidget( group ); + + QGridLayout *gbox = new QGridLayout( group, 3, 6, 6 /*KDialog::mSpacingSize*/ ); + if( gbox == 0 ) { return; } + gbox->addRowSpacing( 0, group->fontMetrics().height() ); + gbox->setColStretch( 5, 10 ); + + QString name[4]; + int i; + + name[0] = i18n("&Top:"); + name[1] = i18n("&Bottom:"); + name[2] = i18n("&Left:"); + name[3] = i18n("&Right:"); + + for( i=0; i<4; i++ ) + { + mLayout.marginSpin[i] = new QSpinBox( group ); + mLayout.marginSpin[i]->setFixedHeight( + mLayout.marginSpin[i]->sizeHint().height() ); + mLayout.marginSpin[i]->setMinimumWidth( + mLayout.marginSpin[i]->fontMetrics().width("M")*10 ); + mLayout.marginSpin[i]->setRange( 0, INT_MAX ); + + QLabel *label = new QLabel( mLayout.marginSpin[i], name[i], group ); + label->setFixedHeight( mLayout.marginSpin[i]->sizeHint().height() ); + label->setFixedWidth( label->sizeHint().width() ); + + if( i < 2 ) + { + gbox->addWidget( label, i+1, 0, AlignLeft ); + gbox->addWidget( mLayout.marginSpin[i], i+1, 1, AlignLeft ); + } + else + { + gbox->addWidget( label, i-1, 3, AlignLeft ); + gbox->addWidget( mLayout.marginSpin[i], i-1, 4, AlignLeft ); + } + } + + text = i18n("Draw h&eader above text"); + mLayout.headerCheck = new QCheckBox( text, this ); + mLayout.headerCheck->setFixedSize( mLayout.headerCheck->sizeHint() ); + connect( mLayout.headerCheck, SIGNAL( toggled(bool)), + SLOT( slotDrawHeader(bool))); + topLayout->addWidget( mLayout.headerCheck, 0, AlignLeft ); + + gbox = new QGridLayout( 5, 6, 0 ); + if( gbox == 0 ) { return; } + topLayout->addLayout( gbox ); + + gbox->setColStretch ( 5, 10 ); + gbox->addColSpacing( 1, 6 /*KDialog::mSpacingSize*/ ); + gbox->addColSpacing( 3, 6 /*KDialog::mSpacingSize*/ ); + gbox->addRowSpacing( 2, 6 /*KDialog::mSpacingSize*/ ); + + name[0] = i18n("Left:"); + name[1] = i18n("Center:"); + name[2] = i18n("Right:"); + name[3] = i18n("Border:"); + + QStringList textList; + textList.append(i18n("None")); + textList.append(i18n("Date & Time")); + textList.append(i18n("Page Number")); + textList.append(i18n("Filename")); + + QStringList lineList; + lineList.append(i18n("None")); + lineList.append(i18n("Single Line")); + lineList.append(i18n("Rectangle")); + + for( i=0; i<4; i++ ) + { + mLayout.headerCombo[i] = new QComboBox( false, this ); + mLayout.headerCombo[i]->setFixedHeight( + mLayout.headerCombo[i]->sizeHint().height() ); + mLayout.headerCombo[i]->setMinimumWidth( + mLayout.headerCombo[i]->fontMetrics().width("M")*10 ); + + mLayout.headerLabel[i] = new QLabel( mLayout.headerCombo[i], name[i], + this ); + mLayout.headerLabel[i]->setFixedHeight( + mLayout.headerLabel[i]->sizeHint().height() ); + mLayout.headerLabel[i]->setFixedWidth( + mLayout.headerLabel[i]->sizeHint().width() ); + + if( i<3 ) + { + mLayout.headerCombo[i]->insertStringList( textList ); + gbox->addWidget( mLayout.headerLabel[i], 0, i*2, AlignLeft ); + gbox->addWidget( mLayout.headerCombo[i], 1, i*2, AlignLeft ); + } + else + { + mLayout.headerCombo[i]->insertStringList( lineList ); + gbox->addWidget( mLayout.headerLabel[i], 3, 0, AlignLeft ); + gbox->addWidget( mLayout.headerCombo[i], 4, 0, AlignLeft ); + } + } + + + text = i18n("Draw &footer below text"); + mLayout.footerCheck = new QCheckBox( text, this ); + mLayout.footerCheck->setFixedSize( mLayout.footerCheck->sizeHint() ); + connect( mLayout.footerCheck, SIGNAL( toggled(bool)), + SLOT( slotDrawFooter(bool))); + topLayout->addWidget( mLayout.footerCheck, 0, AlignLeft ); + + gbox = new QGridLayout( 5, 6, 0 ); + if( gbox == 0 ) { return; } + topLayout->addLayout( gbox ); + + gbox->setColStretch ( 5, 10 ); + gbox->addColSpacing( 1, 6 /*KDialog::mSpacingSize*/ ); + gbox->addColSpacing( 3, 6 /*KDialog::mSpacingSize*/ ); + gbox->addRowSpacing( 2, 6 /*KDialog::mSpacingSize*/ ); + + for( i=0; i<4; i++ ) + { + mLayout.footerCombo[i] = new QComboBox( false, this ); + mLayout.footerCombo[i]->setFixedHeight( + mLayout.footerCombo[i]->sizeHint().height() ); + mLayout.footerCombo[i]->setMinimumWidth( + mLayout.footerCombo[i]->fontMetrics().width("M")*10 ); + + mLayout.footerLabel[i] = new QLabel( mLayout.footerCombo[i], name[i], + this ); + mLayout.footerLabel[i]->setFixedHeight( + mLayout.footerLabel[i]->sizeHint().height() ); + mLayout.footerLabel[i]->setFixedWidth( + mLayout.footerLabel[i]->sizeHint().width() ); + + if( i<3 ) + { + mLayout.footerCombo[i]->insertStringList( textList ); + gbox->addWidget( mLayout.footerLabel[i], 0, i*2, AlignLeft ); + gbox->addWidget( mLayout.footerCombo[i], 1, i*2, AlignLeft ); + } + else + { + mLayout.footerCombo[i]->insertStringList( lineList ); + gbox->addWidget( mLayout.footerLabel[i], 3, 0, AlignLeft ); + gbox->addWidget( mLayout.footerCombo[i], 4, 0, AlignLeft ); + } + } + + for( i=0; i<4; i++ ) + { + mLayout.marginSpin[i]->setValue( 15 ); + } + mLayout.headerCheck->setChecked( true ); + slotDrawHeader( true ); + mLayout.footerCheck->setChecked( true ); + slotDrawFooter( true ); + + topLayout->addStretch(10); +} + + +void LayoutDialogPage::readConfiguration( void ) +{ + if( mConfig != 0 ) { return; } + + mConfig = new KSimpleConfig( QString("hexprinter") ); + if( mConfig == 0 ) { return; } + + mConfig->setGroup( "PageLayout" ); + int val = mConfig->readNumEntry( "MarginTop", 15 ); + mLayout.marginSpin[0]->setValue( val ); + val = mConfig->readNumEntry( "MarginBottom", 15 ); + mLayout.marginSpin[1]->setValue( val ); + val = mConfig->readNumEntry( "MarginLeft", 15 ); + mLayout.marginSpin[2]->setValue( val ); + val = mConfig->readNumEntry( "MarginRight", 15 ); + mLayout.marginSpin[3]->setValue( val ); + bool state = mConfig->readBoolEntry( "DrawHeader", true ); + mLayout.headerCheck->setChecked( state ); + slotDrawHeader( state ); + state = mConfig->readBoolEntry( "DrawFooter", true ); + mLayout.footerCheck->setChecked( state ); + slotDrawFooter( state ); + + mLayout.headerCombo[0]->setCurrentItem( + headerTextIndex( mConfig->readEntry("HeaderLeft","DateTime"))); + mLayout.headerCombo[1]->setCurrentItem( + headerTextIndex( mConfig->readEntry("HeaderCenter"))); + mLayout.headerCombo[2]->setCurrentItem( + headerTextIndex( mConfig->readEntry("HeaderRight","FileName"))); + mLayout.headerCombo[3]->setCurrentItem( + headerLineIndex( mConfig->readEntry("HeaderLine","SingleLine"))); + + mLayout.footerCombo[0]->setCurrentItem( + headerTextIndex( mConfig->readEntry("FooterLeft"))); + mLayout.footerCombo[1]->setCurrentItem( + headerTextIndex( mConfig->readEntry("FooterCenter","PageNumber"))); + mLayout.footerCombo[2]->setCurrentItem( + headerTextIndex( mConfig->readEntry("FooterRight"))); + mLayout.footerCombo[3]->setCurrentItem( + headerLineIndex( mConfig->readEntry("FooterLine","SingleLine"))); + +} + + +void LayoutDialogPage::writeConfiguration( void ) +{ + if( mConfig == 0 ) + { + return; + } + + mConfig->setGroup( "PageLayout" ); + mConfig->writeEntry( "MarginTop", mLayout.marginSpin[0]->value() ); + mConfig->writeEntry( "MarginBottom", mLayout.marginSpin[1]->value() ); + mConfig->writeEntry( "MarginLeft", mLayout.marginSpin[2]->value() ); + mConfig->writeEntry( "MarginRight", mLayout.marginSpin[3]->value() ); + mConfig->writeEntry( "DrawHeader", mLayout.headerCheck->isChecked() ); + mConfig->writeEntry( "DrawFooter", mLayout.footerCheck->isChecked() ); + + mConfig->writeEntry( "HeaderLeft", + headerText( mLayout.headerCombo[0]->currentItem() ) ); + mConfig->writeEntry( "HeaderCenter", + headerText( mLayout.headerCombo[1]->currentItem() ) ); + mConfig->writeEntry( "HeaderRight", + headerText( mLayout.headerCombo[2]->currentItem() ) ); + mConfig->writeEntry( "HeaderLine", + headerLine( mLayout.headerCombo[3]->currentItem() ) ); + + mConfig->writeEntry( "FooterLeft", + headerText( mLayout.footerCombo[0]->currentItem() ) ); + mConfig->writeEntry( "FooterCenter", + headerText( mLayout.footerCombo[1]->currentItem() ) ); + mConfig->writeEntry( "FooterRight", + headerText( mLayout.footerCombo[2]->currentItem() ) ); + mConfig->writeEntry( "FooterLine", + headerLine( mLayout.footerCombo[3]->currentItem() ) ); + + mConfig->sync(); +} + + +QString LayoutDialogPage::headerText( uint index ) +{ + static const QString text[4] = {"None","DateTime","PageNumber","FileName"}; + return( text[ index > 3 ? 0 : index ] ); +} + + +int LayoutDialogPage::headerTextIndex( const QString & headerText ) +{ + static const QString text[4] = {"None","DateTime","PageNumber","FileName"}; + if( headerText != 0 ) + { + for( int i=0; i<4; i++ ) + { + if( headerText == text[i] ) { return( i ); } + } + } + return( 0 ); +} + + +QString LayoutDialogPage::headerLine( uint index ) +{ + static const QString text[3] = {"None","SingleLine","Rectangle"}; + return( text[ index > 2 ? 0 : index ] ); +} + + +int LayoutDialogPage::headerLineIndex( const QString & headerLine ) +{ + static const QString text[3] = {"None","SingleLine","Rectangle"}; + if( headerLine != 0 ) + { + for( int i=0; i<3; i++ ) + { + if( headerLine == text[i] ) { return( i ); } + } + } + return( 0 ); +} + + +void LayoutDialogPage::slotDrawHeader( bool state ) +{ + for( int i=0; i<4; i++ ) + { + mLayout.headerLabel[i]->setEnabled( state ); + mLayout.headerCombo[i]->setEnabled( state ); + } +} + + +void LayoutDialogPage::slotDrawFooter( bool state ) +{ + for( int i=0; i<4; i++ ) + { + mLayout.footerLabel[i]->setEnabled( state ); + mLayout.footerCombo[i]->setEnabled( state ); + } +} + + +void LayoutDialogPage::getOptions( QMap& opts, bool /*incldef*/ ) +{ + opts[ "kde-khexedit-topmarginmm" ] = QString::number( mLayout.marginSpin[0]->value() ); + opts[ "kde-khexedit-bottommarginmm" ] = QString::number( mLayout.marginSpin[1]->value() ); + opts[ "kde-khexedit-leftmarginmm" ] = QString::number( mLayout.marginSpin[2]->value() ); + opts[ "kde-khexedit-rightmarginmm" ] = QString::number( mLayout.marginSpin[3]->value() ); + + opts[ "kde-khexedit-headercheck" ] = (mLayout.headerCheck->isChecked() ? "true" : "false"); + opts[ "kde-khexedit-headercombo0" ] = QString::number( mLayout.headerCombo[0]->currentItem() ); + opts[ "kde-khexedit-headercombo1" ] = QString::number( mLayout.headerCombo[1]->currentItem() ); + opts[ "kde-khexedit-headercombo2" ] = QString::number( mLayout.headerCombo[2]->currentItem() ); + opts[ "kde-khexedit-headercombo3" ] = QString::number( mLayout.headerCombo[3]->currentItem() ); + + opts[ "kde-khexedit-footercheck" ] = (mLayout.footerCheck->isChecked() ? "true" : "false"); + opts[ "kde-khexedit-footercombo0" ] = QString::number( mLayout.footerCombo[0]->currentItem() ); + opts[ "kde-khexedit-footercombo1" ] = QString::number( mLayout.footerCombo[1]->currentItem() ); + opts[ "kde-khexedit-footercombo2" ] = QString::number( mLayout.footerCombo[2]->currentItem() ); + opts[ "kde-khexedit-footercombo3" ] = QString::number( mLayout.footerCombo[3]->currentItem() ); +} + + +#include "printdialogpage.moc" diff --git a/khexedit/printdialogpage.h b/khexedit/printdialogpage.h new file mode 100644 index 0000000..bdc58f6 --- /dev/null +++ b/khexedit/printdialogpage.h @@ -0,0 +1,73 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * This file is based on the work by F. Zigterman, fzr@dds.nl + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _PRINT_DIALOG_PAGE_H_ +#define _PRINT_DIALOG_PAGE_H_ + +class QCheckBox; +class QComboBox; +class QLabel; +class QSpinBox; + +#include +#include + +class LayoutDialogPage : public KPrintDialogPage +{ + Q_OBJECT + + public: + LayoutDialogPage( QWidget *parent = 0, const char *name = 0 ); + ~LayoutDialogPage( void ); + + void getOptions( QMap& opts, bool incldef = false ); + + private slots: + void slotDrawHeader( bool state ); + void slotDrawFooter( bool state ); + + private: + void setupLayoutPage( void ); + + void readConfiguration( void ); + void writeConfiguration( void ); + + QString headerText( uint index ); + QString headerLine( uint index ); + int headerTextIndex( const QString & headerText ); + int headerLineIndex( const QString & headerLine ); + + struct SLayoutWidgets + { + QSpinBox *marginSpin[4]; + QCheckBox *headerCheck; + QCheckBox *footerCheck; + QLabel *headerLabel[4]; + QComboBox *headerCombo[4]; + QLabel *footerLabel[4]; + QComboBox *footerCombo[4]; + }; + + KSimpleConfig *mConfig; + SLayoutWidgets mLayout; +}; + +#endif diff --git a/khexedit/progress.h b/khexedit/progress.h new file mode 100644 index 0000000..fa6e8a3 --- /dev/null +++ b/khexedit/progress.h @@ -0,0 +1,130 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * This file is based on the work by F. Zigterman, fzr@dds.nl + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _PROGRESS_H_ +#define _PROGRESS_H_ + +#include +#include "hexerror.h" + + +struct SProgressData +{ + SProgressData( float f ) + { + useFraction = 1; + fraction = f; + } + + SProgressData( int cPage, int mPage ) + { + useFraction = 0; + curPage = cPage; + maxPage = mPage; + } + + int valid( void ) const + { + return( (useFraction == 1 && fraction >= 0) || + (useFraction == 0 && curPage >= 0) ? 1 : 0 ); + } + + int useFraction; + float fraction; + int curPage; + int maxPage; +}; + + + +typedef int (*ProgressFunc)( void *clientData, SProgressData &pd ); + +class CProgress +{ + public: + CProgress( void ) + { + define( 0, 0 ); + mInterruptTimer.start(); + } + + CProgress( ProgressFunc progressFunc, void *clientData ) + { + define( progressFunc, clientData ); + mInterruptTimer.start(); + } + + void define( ProgressFunc progressFunc, void *clientData ) + { + mProgressFunc = progressFunc; + mClientData = clientData; + } + + void finish( void ) const + { + if( mProgressFunc == 0 ) + { + return; + } + SProgressData pd( -1.0 ); + mProgressFunc( mClientData, pd ); + } + + bool expired( void ) + { + return( mInterruptTimer.elapsed() > 200 ); + } + + int step( float fraction ) + { + mInterruptTimer.start(); + + if( mProgressFunc == 0 ) + { + return( Err_Success ); + } + SProgressData pd( fraction ); + int errCode = mProgressFunc( mClientData, pd ); + return( errCode ); + } + + int step( int curPage, int maxPage ) + { + mInterruptTimer.start(); + + if( mProgressFunc == 0 ) + { + return( Err_Success ); + } + SProgressData pd( curPage, maxPage ); + int errCode = mProgressFunc( mClientData, pd ); + return( errCode ); + } + + private: + ProgressFunc mProgressFunc; + void *mClientData; + QTime mInterruptTimer; +}; + +#endif + + diff --git a/khexedit/searchbar.cc b/khexedit/searchbar.cc new file mode 100644 index 0000000..44d4944 --- /dev/null +++ b/khexedit/searchbar.cc @@ -0,0 +1,188 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include + +#include "dialog.h" +#include "hexvalidator.h" +#include "searchbar.h" +#include + +// crappy X11 headers +#undef KeyPress + +static const char * close_xpm[] = { +"16 16 3 1", +" s None c None", +". c #ffffff", +"X c #707070", +" ", +" ", +" .X .X ", +" .XX .XX ", +" .XX .XX ", +" .XX .XX ", +" .XX.XX ", +" .XXX ", +" .XXX ", +" .XX.XX ", +" .XX .XX ", +" .XX .XX ", +" .XX .XX ", +" .X .X ", +" ", +" "}; + +CSearchBar::CSearchBar( QWidget *parent, const char *name, WFlags f ) + :QFrame( parent, name, f ) +{ + setFrameStyle( QFrame::Panel | QFrame::Raised ); + setLineWidth( 1 ); + + mTypeCombo = new QComboBox( this ); + connect( mTypeCombo, SIGNAL(activated(int)), SLOT(selectorChanged(int)) ); + QStringList list; + list << i18n("Hex") << i18n("Dec") << i18n("Oct") << i18n("Bin") + << i18n("Txt"); + mTypeCombo->insertStringList( list ); + + mInputEdit = new QLineEdit( this ); + connect( mInputEdit, SIGNAL(textChanged(const QString&)), + SLOT(textChanged(const QString&)) ); + mValidator = new CHexValidator( this, CHexValidator::regularText ); + mInputEdit->setValidator( mValidator ); + + mFindButton = new QPushButton( i18n("Find"), this ); + mFindButton->setAutoDefault(false); + connect( mFindButton, SIGNAL(clicked()), this, SLOT(start()) ); + connect(mInputEdit,SIGNAL(returnPressed()),mFindButton,SLOT(animateClick())); + mFindButton->setFixedHeight( mTypeCombo->sizeHint().height() ); + + mBackwards = new QCheckBox( i18n("Backwards"), this ); + mIgnoreCase = new QCheckBox( i18n("Ignore case"), this ); + + mCloseButton = new QPushButton( this ); + mCloseButton->setAutoDefault(false); + mCloseButton->setPixmap( QPixmap( close_xpm ) ); + connect( mCloseButton, SIGNAL(clicked()), this, SLOT(hideWidget()) ); + + // + // Make layout + // + QHBoxLayout *hlay = new QHBoxLayout( this, 4, 6 ); + hlay->addWidget( mTypeCombo ); + hlay->addWidget( mInputEdit ); + hlay->addWidget( mFindButton ); + hlay->addWidget( mBackwards ); + hlay->addWidget( mIgnoreCase ); + hlay->addWidget( mCloseButton ); + + // + // Read below why I do this. + // + mInputEdit->installEventFilter( this ); + selectorChanged(0); +} + + +// +// Espen 2000-04-21 +// Qt 2.1: Seems like the QLineEdit::returnPressed() does not work when +// I install a validator. So I catch the event manually +// +bool CSearchBar::eventFilter( QObject *o, QEvent *e ) +{ + if( o == mInputEdit && e->type() == QEvent::KeyPress ) + { + QKeyEvent *ke = (QKeyEvent*)e; + if( ke->key() == Key_Return ) + { + mFindButton->animateClick(); + return true; + } + } + return QFrame::eventFilter( o, e ); +} + +// +// Seach for te first item each time the curso has moved. Note: The cursor +// will move when we search and get a match, but (in start() below) the +// mSearchMode is set to Find_Next after this slot has been called so it +// will work. +// +void CSearchBar::cursorMoved() +{ + mSearchMode = Find_First; +} + + +void CSearchBar::selectorChanged( int index ) +{ + mValidator->setState( (CHexValidator::EState)index ); + mInputEdit->setText( mFindString[ index ] ); + mIgnoreCase->setEnabled( index == 4 ? true : false ); + mSearchMode = Find_First; +} + + +void CSearchBar::textChanged( const QString &text ) +{ + mFindString[ mTypeCombo->currentItem() ] = text; + mValidator->convert( mFindData, mFindString[ mTypeCombo->currentItem() ] ); + mSearchMode = Find_First; +} + + +void CSearchBar::hideWidget() +{ + hide(); + emit hidden(); +} + + +void CSearchBar::start( void ) +{ + if( mFindData.isEmpty() == true ) + { + showEntryFailure( this, QString("") ); + return; + } + + SSearchControl sc; + sc.key = mFindData; + sc.keyType = mTypeCombo->currentItem(); + sc.fromCursor = true; + sc.inSelection = false; + sc.forward = !mBackwards->isChecked(); + sc.ignoreCase = mIgnoreCase->isEnabled() && mIgnoreCase->isChecked(); + emit findData( sc, mSearchMode, false ); + mSearchMode = Find_Next; +} + + +void CSearchBar::showEvent( QShowEvent *e ) +{ + QFrame::showEvent(e); + mInputEdit->setFocus(); +} + + +#include "searchbar.moc" diff --git a/khexedit/searchbar.h b/khexedit/searchbar.h new file mode 100644 index 0000000..c11f652 --- /dev/null +++ b/khexedit/searchbar.h @@ -0,0 +1,73 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +#ifndef _SEARCHBAR_H_ +#define _SEARCHBAR_H_ + +#include + +#include "hexbuffer.h" + +class QComboBox; +class QLineEdit; +class QPushButton; +class QCheckBox; +class CHexValidator; + +class CSearchBar : public QFrame +{ + Q_OBJECT + + public: + CSearchBar( QWidget *parent=0, const char *name=0, WFlags f=0 ); + virtual bool eventFilter( QObject *o, QEvent *e ); + + public slots: + void cursorMoved(); + + protected: + virtual void showEvent( QShowEvent * ); + + private slots: + void hideWidget(); + void selectorChanged( int index ); + void textChanged( const QString &text ); + void start(); + + signals: + void hidden(); + void findData( SSearchControl &sc, uint mode, bool navigator ); + + private: + QPushButton *mCloseButton; + QPushButton *mFindButton; + QComboBox *mTypeCombo; + QLineEdit *mInputEdit; + QCheckBox *mBackwards; + QCheckBox *mIgnoreCase; + + QString mFindString[5]; + QByteArray mFindData; + CHexValidator *mValidator; + uint mSearchMode; +}; + +#endif + + diff --git a/khexedit/statusbarprogress.cc b/khexedit/statusbarprogress.cc new file mode 100644 index 0000000..6e45cf2 --- /dev/null +++ b/khexedit/statusbarprogress.cc @@ -0,0 +1,374 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * This file is based on the work by Martynas Kunigelis (KProgress) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "statusbarprogress.h" + +#include + +#include +#include +#include +#include + +CStatusBarProgress::CStatusBarProgress( QWidget *parent, const char *name ) + : QFrame(parent, name), QRangeControl(0, 100, 1, 10, 0), + mOrientation( Horizontal ) +{ + initialize(); +} + +CStatusBarProgress::CStatusBarProgress( Orientation orientation, + QWidget *parent, const char *name ) + : QFrame(parent, name), QRangeControl(0, 100, 1, 10, 0), + mOrientation( orientation ) +{ + initialize(); +} + +CStatusBarProgress::CStatusBarProgress( int minValue, int maxValue, int value, + Orientation orientation, + QWidget *parent, const char *name ) + : QFrame(parent, name), QRangeControl(minValue, maxValue, 1, 10, value), + mOrientation(orientation) +{ + initialize(); +} + +CStatusBarProgress::~CStatusBarProgress() +{ + delete mBarPixmap; +} + +void CStatusBarProgress::advance( int offset ) +{ + setValue(value() + offset); +} + +void CStatusBarProgress::initialize( void ) +{ + mBarPixmap = 0; + mBarStyle = Solid; + + mBarColor = palette().active().highlight(); + mBarTextColor = palette().active().highlightedText(); + mTextColor = palette().active().text(); + setBackgroundColor( palette().active().background() ); + + QFont font( KGlobalSettings::generalFont() ); + font.setBold( true ); + setFont( font ); + + mTextEnabled = false; + adjustStyle(); +} + + +void CStatusBarProgress::setBarPixmap( const QPixmap &pixmap ) +{ + if( pixmap.isNull() == true ) + { + return; + } + + delete mBarPixmap; + mBarPixmap = new QPixmap( pixmap ); +} + +void CStatusBarProgress::setBarColor( const QColor &color ) +{ + mBarColor = color; + delete mBarPixmap; + mBarPixmap = 0; +} + +void CStatusBarProgress::setBarStyle( BarStyle style ) +{ + if( mBarStyle != style ) + { + mBarStyle = style; + update(); + } +} + +void CStatusBarProgress::setOrientation( Orientation orientation ) +{ + if( mOrientation != orientation ) + { + mOrientation = orientation; + update(); + } +} + +void CStatusBarProgress::setValue(int value) +{ + mCurPage = mMaxPage = -1; + QRangeControl::setValue(value); +} + +void CStatusBarProgress::setValue( int curPage, int maxPage ) +{ + if( curPage <= 0 || maxPage <= 0 || curPage > maxPage ) + { + mCurPage = mMaxPage = -1; + QRangeControl::setValue(0); + } + else + { + mCurPage = curPage; + mMaxPage = maxPage; + float fraction = (float)curPage/(float)maxPage; + QRangeControl::setValue( (int)(fraction*100.0) ); + } +} + + +void CStatusBarProgress::setTextEnabled( bool state ) +{ + if( mTextEnabled != state ) + { + mTextEnabled = state; + update(); + } +} + +void CStatusBarProgress::setText( const QString &msg ) +{ + mMsg = msg; + if( mTextEnabled == true ) + { + update(); + } +} + + + + +const QColor & CStatusBarProgress::barColor( void ) const +{ + return( mBarColor ); +} + +const QPixmap * CStatusBarProgress::barPixmap( void ) const +{ + return( mBarPixmap ); +} + +bool CStatusBarProgress::textEnabled( void ) const +{ + return( mTextEnabled ); +} + +QSize CStatusBarProgress::sizeHint( void ) const +{ + QSize s( size() ); + + if( orientation() == CStatusBarProgress::Vertical ) + { + s.setWidth( fontMetrics().lineSpacing() ); + } + else + { + s.setHeight( fontMetrics().lineSpacing() ); + } + + return( s ); +} + + +CStatusBarProgress::Orientation CStatusBarProgress::orientation( void ) const +{ + return( mOrientation ); +} + +CStatusBarProgress::BarStyle CStatusBarProgress::barStyle() const +{ + return( mBarStyle ); +} + +int CStatusBarProgress::recalcValue(int range) +{ + int abs_value = value() - minValue(); + int abs_range = maxValue() - minValue(); + return range * abs_value / abs_range; +} + +void CStatusBarProgress::valueChange() +{ + repaint(contentsRect(), FALSE); + emit percentageChanged(recalcValue(100)); +} + +void CStatusBarProgress::rangeChange() +{ + repaint(contentsRect(), FALSE); + emit percentageChanged(recalcValue(100)); +} + +void CStatusBarProgress::styleChange( GUIStyle ) +{ + adjustStyle(); +} + +void CStatusBarProgress::adjustStyle( void ) +{ + switch( style().SH_GUIStyle) + { + case WindowsStyle: + setFrameStyle( QFrame::NoFrame ); + break; + + case MotifStyle: + default: + setFrameStyle( QFrame::Panel|QFrame::Sunken ); + setLineWidth( 1 ); + break; + } + update(); +} + +void CStatusBarProgress::paletteChange( const QPalette & ) +{ + mBarColor = palette().active().highlight(); + mBarTextColor = palette().active().highlightedText(); + mTextColor = palette().active().text(); + setBackgroundColor( palette().active().background() ); +} + +void CStatusBarProgress::drawText( QPainter *p ) +{ + QRect r(contentsRect()); + QString s; + + if( mMsg.isEmpty() == true ) + { + s = QString("%1%").arg(recalcValue(100)); + } + else + { + if( mCurPage > 0 ) + { + s = i18n("%1... %2 of %3").arg(mMsg).arg(mCurPage).arg(mMaxPage); + } + else + { + s = i18n("%1... %2%").arg(mMsg).arg(recalcValue(100)); + } + } + + p->setPen( mTextColor ); + p->drawText( r, AlignCenter, s ); + p->setClipRegion( fr ); + p->setPen( mBarTextColor ); + p->drawText( r, AlignCenter, s ); +} + +void CStatusBarProgress::drawContents(QPainter *p) +{ + QRect cr = contentsRect(), er = cr; + fr = cr; + QBrush fb(mBarColor), eb(backgroundColor() ); + + if( mBarPixmap != 0 ) + { + fb.setPixmap( *mBarPixmap ); + } + + if (backgroundPixmap()) + eb.setPixmap(*backgroundPixmap()); + + switch( mBarStyle ) + { + case Solid: + if( mOrientation == Horizontal ) + { + fr.setWidth(recalcValue(cr.width())); + er.setLeft(fr.right() + 1); + } + else + { + fr.setTop(cr.bottom() - recalcValue(cr.height())); + er.setBottom(fr.top() - 1); + } + + p->setBrushOrigin(cr.topLeft()); + p->fillRect(fr, fb); + p->fillRect(er, eb); + + if( mTextEnabled == true ) + drawText(p); + break; + + case Blocked: + const int margin = 2; + int max, num, dx, dy; + if( mOrientation == Horizontal ) + { + fr.setHeight(cr.height() - 2 * margin); + fr.setWidth((int)(0.67 * fr.height())); + fr.moveTopLeft(QPoint(cr.left() + margin, cr.top() + margin)); + dx = fr.width() + margin; + dy = 0; + max = (cr.width() - margin) / (fr.width() + margin) + 1; + num = recalcValue(max); + } + else + { + fr.setWidth(cr.width() - 2 * margin); + fr.setHeight((int)(0.67 * fr.width())); + fr.moveBottomLeft(QPoint(cr.left() + margin, cr.bottom() - margin)); + dx = 0; + dy = - (fr.height() + margin); + max = (cr.height() - margin) / (fr.height() + margin) + 1; + num = recalcValue(max); + } + p->setClipRect(cr.x() + margin, cr.y() + margin, + cr.width() - margin, cr.height() - margin); + for (int i = 0; i < num; i++) + { + p->setBrushOrigin(fr.topLeft()); + p->fillRect(fr, fb); + fr.moveBy(dx, dy); + } + + if (num != max) + { + if( mOrientation == Horizontal ) + er.setLeft(fr.right() + 1); + else + er.setBottom(fr.bottom() + 1); + if (!er.isNull()) + { + p->setBrushOrigin(cr.topLeft()); + p->fillRect(er, eb); + } + } + break; + } + +} + + +void CStatusBarProgress::mousePressEvent( QMouseEvent */*e*/ ) +{ + emit pressed(); +} + +#include "statusbarprogress.moc" diff --git a/khexedit/statusbarprogress.h b/khexedit/statusbarprogress.h new file mode 100644 index 0000000..ca605f3 --- /dev/null +++ b/khexedit/statusbarprogress.h @@ -0,0 +1,159 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * This file is based on the work by Martynas Kunigelis (KProgress) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _STATUSBAR_PROGRESS_H_ +#define _STATUSBAR_PROGRESS_H_ + +#include +#include + +class CStatusBarProgress : public QFrame, public QRangeControl +{ + Q_OBJECT + + public: + /** + * Possible values for orientation + */ + enum Orientation { Horizontal, Vertical }; + + /** + * Possible values for bar style. + * + * Solid means one continuous progress bar, Blocked means a + * progress bar made up of several blocks. + */ + enum BarStyle { Solid, Blocked }; + + /** + * Construct a default progress bar. Orientation is horizontal. + */ + CStatusBarProgress(QWidget *parent=0, const char *name=0); + + /** + * Construct a KProgress bar with an orientation. + */ + CStatusBarProgress(Orientation, QWidget *parent=0, const char *name=0); + + /** + * Construct a KProgress bar with minimum, maximum and initial value. + */ + CStatusBarProgress(int minValue, int maxValue, int value, Orientation, + QWidget *parent=0, const char *name=0); + + /** + * Destructor + */ + ~CStatusBarProgress( void ); + + /** + * Set the progress bar style. Allowed values are Solid and Blocked. + */ + void setBarStyle(BarStyle style); + + /** + * Set the color of the progress bar. + */ + void setBarColor(const QColor &); + + /** + * Set a pixmap to be shown in the progress bar. + */ + void setBarPixmap(const QPixmap &); + + /** + * Set the orientation of the progress bar. + * Allowed values are Horizonzal and Vertical. + */ + void setOrientation(Orientation); + + /** + * Retrieve the bar style. + */ + BarStyle barStyle() const; + + /** + * Retrieve the bar color. + */ + const QColor &barColor() const; + + /** + * Retrieve the bar pixmap. + */ + const QPixmap *barPixmap() const; + + /** + * Retrieve the orientation. + */ + Orientation orientation() const; + + /** + * Returns TRUE if progress text will be displayed, FALSE otherwise. + */ + bool textEnabled() const; + + /** + * Returns the recommended width for vertical progress bars or + * the recommended height for vertical progress bars + */ + virtual QSize sizeHint() const; + + + public slots: + void setValue( int ); + void setValue( int, int); + void advance( int ); + void setTextEnabled( bool state ); + void setText( const QString &msg ); + + signals: + void percentageChanged(int); + void pressed( void ); + + protected: + void valueChange(); + void rangeChange(); + void styleChange( GUIStyle ); + void paletteChange( const QPalette & ); + void drawContents( QPainter * ); + void mousePressEvent( QMouseEvent *e ); + + private: + QPixmap *mBarPixmap; + QColor mBarColor; + QColor mBarTextColor; + QColor mTextColor; + QRect fr; + BarStyle mBarStyle; + Orientation mOrientation; + bool mTextEnabled; + QString mMsg; + int mCurPage; + int mMaxPage; + + void initialize( void ); + int recalcValue( int ); + void drawText( QPainter * ); + void adjustStyle( void ); +}; + + +#endif diff --git a/khexedit/stringdialog.cc b/khexedit/stringdialog.cc new file mode 100644 index 0000000..dff774c --- /dev/null +++ b/khexedit/stringdialog.cc @@ -0,0 +1,412 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "listview.h" +#include "stringdialog.h" +#include + + +CStringDialog::CStringDialog( QWidget *parent, const char *name, bool modal ) + : KDialogBase( Plain, i18n("Extract Strings"), Help|User1|Cancel, User1, + parent, name, modal, true, i18n("&Update") ), + mMaxLength(0), mBusy(false), mDirty(false) +{ + setHelp( "khexedit/khexedit.html", QString::null ); + + QString text; + QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() ); + + QGridLayout *glay = new QGridLayout( 3, 3, spacingHint() ); + topLayout->addLayout( glay ); + glay->setColStretch( 1, 10 ); + + mLengthSpin = new QSpinBox( plainPage() ); + mLengthSpin->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mLengthSpin->setRange( 1, 1000000 ); + mLengthSpin->setValue( 4 ); + glay->addMultiCellWidget( mLengthSpin, 0, 0, 1, 2 ); + + text = i18n("&Minimum length:"); + QLabel *label = new QLabel( mLengthSpin, text, plainPage() ); + glay->addWidget( label, 0, 0, AlignRight ); + + mFilter = new QLineEdit( plainPage() ); + mFilter->setMinimumWidth( fontMetrics().maxWidth()*17 ); + mFilter->setText("*"); + glay->addWidget( mFilter, 1, 1 ); + + text = i18n("&Filter:"); + label = new QLabel( mFilter, text, plainPage() ); + glay->addWidget( label, 1, 0, AlignRight ); + + QPushButton *useButton = new QPushButton( plainPage(), "use" ); + useButton->setText( i18n("&Use") ); + useButton->setAutoDefault( false ); + connect( useButton, SIGNAL(clicked()),this,SLOT(slotUser1()) ); + glay->addWidget( useButton, 1, 2 ); + + QWidget *helper = new QWidget( plainPage() ); + glay->addMultiCellWidget( helper, 2, 2, 1, 2 ); + QHBoxLayout *hlay = new QHBoxLayout( helper, 0, spacingHint() ); + + text = i18n("&Ignore case"); + mIgnoreCaseCheck = new QCheckBox( text, helper ); + hlay->addWidget( mIgnoreCaseCheck ); + + text = i18n("Show offset as &decimal"); + mOffsetDecimalCheck = new QCheckBox( text, helper ); + hlay->addWidget( mOffsetDecimalCheck ); + + hlay->addStretch(10); + + // + // Using listview as suggested by Dima Rogozin + // + mStringList = new CListView( plainPage(), "stringList" ); + mStringList->setFont( KGlobalSettings::fixedFont() ); + mStringList->addColumn( i18n("Offset") ); + mStringList->addColumn( i18n("String") ); + mStringList->setAllColumnsShowFocus( true ); + mStringList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken ); + + connect( mStringList, SIGNAL(selectionChanged()), + SLOT(selectionChanged())); + topLayout->addWidget( mStringList, 10 ); + + hlay = new QHBoxLayout( topLayout ); + + text = i18n("Number of strings:"); + label = new QLabel( text, plainPage() ); + hlay->addWidget( label, AlignLeft ); + + mListSizeLabel = new QLabel( QString(), plainPage() ); + mListSizeLabel->setFixedWidth( fontMetrics().maxWidth()*10 ); + hlay->addWidget( mListSizeLabel, AlignLeft|AlignHCenter ); + + text = i18n("Displayed:"); + label = new QLabel( text, plainPage() ); + hlay->addWidget( label, AlignLeft ); + + mDisplaySizeLabel = new QLabel( QString(""), plainPage() ); + mDisplaySizeLabel->setFixedWidth( fontMetrics().maxWidth()*10 ); + hlay->addWidget( mDisplaySizeLabel, AlignLeft|AlignHCenter); + + hlay->addStretch( 10 ); + + mDirtyLabel = new QLabel( plainPage() ); + topLayout->addWidget( mDirtyLabel ); + + readConfiguration(); + + // + // The initial width of the columns are set in updateListInfo() + // + updateListInfo(); + mStringList->setVisibleItem( 15 ); + startTimer(100); +} + + +CStringDialog::~CStringDialog( void ) +{ + writeConfiguration(); +} + + +void CStringDialog::showEvent( QShowEvent *e ) +{ + KDialogBase::showEvent(e); + mLengthSpin->setFocus(); +} + + +void CStringDialog::readConfiguration( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup( "String Dialog" ); + + mLengthSpin->setValue( config.readNumEntry("MinimumLength", 4) ); + mFilter->setText( config.readEntry("FilterText", "*") ); + mIgnoreCaseCheck->setChecked( config.readBoolEntry("IgnoreCase", false) ); + mOffsetDecimalCheck->setChecked( + config.readBoolEntry("OffsetAsDecimal", false ) ); +} + + +void CStringDialog::writeConfiguration( void ) +{ + KConfig &config = *kapp->config(); + config.setGroup( "String Dialog" ); + + config.writeEntry( "MinimumLength", mLengthSpin->value() ); + config.writeEntry( "FilterText", mFilter->text() ); + config.writeEntry( "IgnoreCase", mIgnoreCaseCheck->isChecked() ); + config.writeEntry( "OffsetAsDecimal", mOffsetDecimalCheck->isChecked() ); + config.sync(); +} + + +void CStringDialog::slotUser1( void ) // Start +{ + if( mBusy == true ) + { + return; + } + + mRegExp.setCaseSensitive( mIgnoreCaseCheck->isChecked() == false ); + mRegExp.setWildcard( true ); + if( mFilter->text().isEmpty() == true ) + { + mRegExp.setPattern("*"); + } + else + { + mRegExp.setPattern(mFilter->text()); + } + + if( mRegExp.isValid() == false ) + { + QString msg = i18n("" + "The filter expression you have specified is illegal. " + "You must specify a valid regular expression.\n" + "Continue without filter?"); + int reply = KMessageBox::warningContinueCancel( this, msg, i18n("Extract Strings")); + if( reply != KMessageBox::Continue ) + { + return; + } + mRegExp.setPattern( "*"); + } + + + mStringData.minLength = mLengthSpin->value(); + mStringData.decimalOffset = mOffsetDecimalCheck->isChecked(); + + removeList(); + + mBusy = true; + emit collect(); + mBusy = false; +} + + +void CStringDialog::startGoto( QListViewItem *item ) +{ + QString str_offset = item->text(0); + QString string = item->text(1); + + uint offset; + if( stringData().decimalOffset == true ) + { + // sscanf( str_offset.ascii(), "%u", &offset ); + offset = str_offset.toInt(); + } + else + { + uint val1,val2; + // #### Rewrite it do it doesn't need the .ascii() call + sscanf( str_offset.ascii(), "%X:%X", &val1, &val2 ); + offset = (val1<<16) + val2; + } + + uint size = string.length(); + + emit markText( offset, size, true ); +} + + +void CStringDialog::setDirty( void ) +{ + if( mDirty == true ) + { + return; + } + + mDirtyLabel->setText( + i18n("Warning: Document has been modified since last update")); + mDirty = true; +} + + +void CStringDialog::setClean( void ) +{ + if( mDirty == false ) + { + return; + } + + mDirtyLabel->setText(""); + mDirty = false; +} + + +void CStringDialog::selectionChanged() +{ + killTimers(); + startTimer( 200 ); +} + + +void CStringDialog::timerEvent( QTimerEvent * ) +{ + killTimers(); + + QListViewItem *item = mStringList->currentItem(); + if( item == 0 ) + { + slotUser1(); + return; + } + startGoto( item ); +} + + +void CStringDialog::resizeEvent( QResizeEvent * ) +{ + setColumnWidth(); +} + + + +int CStringDialog::updateList( CProgress &p ) +{ + clearList(); + enableList( false ); + + int offsetLen = stringData().offsetLen(); + + QPtrList &list = stringData().list(); + for( const QString *str = list.first(); str != 0; str = list.next() ) + { + appendListItem( *str, offsetLen ); + mMaxLength = QMAX( mMaxLength, str->length() ); + + if( p.expired() == true ) + { + int errCode = p.step( (float)list.at()/(float)list.count() ); + if( errCode == Err_Stop ) + { + p.finish(); + return( Err_Success ); + } + } + } + + p.finish(); + updateListInfo(); + enableList( true ); + + return( Err_Success ); +} + + + + +void CStringDialog::clearList( void ) +{ + if( mStringList->childCount() > 0 ) + { + mStringList->clear(); + mStringList->update(); + } + mMaxLength = 0; + + updateListInfo(); + setClean(); +} + + +void CStringDialog::removeList( void ) +{ + mStringData.clear(); + clearList(); +} + + +void CStringDialog::enableList( bool state ) +{ + mStringList->setEnabled( state ); + if( state == true ) + { + mStringList->update(); + } +} + + +void CStringDialog::appendListItem( const QString &str, uint offsetLen ) +{ + if( mRegExp.search ( str, offsetLen ) != -1 ) + { + new QListViewItem( mStringList, str.left(offsetLen), str.mid(offsetLen) ); + } +} + + +void CStringDialog::updateListInfo( void ) +{ + mListSizeLabel->setText( QString("%1").arg(mStringData.count()) ); + mDisplaySizeLabel->setText( QString("%1").arg(mStringList->childCount()) ); + setColumnWidth(); +} + + + +void CStringDialog::setColumnWidth( void ) +{ + const QFontMetrics &fm = mStringList->fontMetrics(); + + if( mStringData.count() == 0 ) + { + int w1 = fm.maxWidth() * (stringData().offsetLen() + 2); + int w2 = mStringList->viewport()->width() - w1; + mStringList->setColumnWidth( 0, w1 ); + mStringList->setColumnWidth( 1, w2 ); + } + else + { + int w1 = fm.maxWidth() * (stringData().offsetLen() + 2); + int w2 = fm.maxWidth() * mMaxLength - w1; + if( w2 < 0 ) + { + w2 = mStringList->viewport()->width() - w1; + } + + mStringList->setColumnWidth( 0, w1 ); + mStringList->setColumnWidth( 1, w2 ); + } +} + + + + + + +#include "stringdialog.moc" diff --git a/khexedit/stringdialog.h b/khexedit/stringdialog.h new file mode 100644 index 0000000..ec731e4 --- /dev/null +++ b/khexedit/stringdialog.h @@ -0,0 +1,110 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _STRING_DIALOG_H_ +#define _STRING_DIALOG_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +class QCheckBox; +class QLabel; +class QLineEdit; +class QListView; +class QSpinBox; + +#include +#include + +class CListView; +#include "hexbuffer.h" +#include "progress.h" + +class CStringDialog : public KDialogBase +{ + Q_OBJECT + + public: + CStringDialog( QWidget *parent=0, const char *name = 0, bool modal=false ); + ~CStringDialog( void ); + + int updateList( CProgress &p ); + inline CStringCollectControl &stringData( void ); + + signals: + void markText( uint offset, uint size, bool moveCursor ); + void collect( void ); + + public slots: + void clearList( void ); // Removes list entries + void removeList( void ); // Removes list entries and the string list. + void setDirty( void ); + void setClean( void ); + + protected slots: + virtual void slotUser1( void ); + virtual void startGoto( QListViewItem * ); + virtual void selectionChanged( ); + + protected: + virtual void timerEvent( QTimerEvent *e ); + virtual void resizeEvent( QResizeEvent *e ); + virtual void showEvent( QShowEvent *e ); + + private: + void enableList( bool state ); + void appendListItem( const QString &str, uint offsetSize ); + void updateListInfo( void ); + void setColumnWidth( void ); + void readConfiguration( void ); + void writeConfiguration( void ); + + private: + CStringCollectControl mStringData; + QRegExp mRegExp; + uint mMaxLength; + bool mBusy; + bool mDirty; + + QSpinBox *mLengthSpin; + QLineEdit *mFilter; + QCheckBox *mIgnoreCaseCheck; + QCheckBox *mOffsetDecimalCheck; + CListView *mStringList; + QLabel *mListSizeLabel; + QLabel *mDisplaySizeLabel; + QLabel *mDirtyLabel; +}; + + +CStringCollectControl &CStringDialog::stringData( void ) +{ + return( mStringData ); +} + +#endif + + + + + + + diff --git a/khexedit/toplevel.cc b/khexedit/toplevel.cc new file mode 100644 index 0000000..733173e --- /dev/null +++ b/khexedit/toplevel.cc @@ -0,0 +1,1366 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +// kate: space-indent on; indent-width 2; replace-tabs on; + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dialog.h" +#include "draglabel.h" +#include "hexerror.h" +#include "toplevel.h" + + +QPtrList KHexEdit::mWindowList; + +KHexEdit::KHexEdit( void ) + : KMainWindow(0, "toplevel"), mStartupOffset(0), + mIsModified(0) +{ + mWindowList.append( this ); + + // + // Create main widget and register it. + // + mManager = new CHexManagerWidget( this, "manager" ); + setCentralWidget( mManager ); + + // + // I use an eventfilter to catch all drag/drop events for the + // area outside the editor window. It will only accept KURLDrag. + // (The editor window will catch KURLDrag, QTextDrag and CHexDrag) + // + installEventFilter( this ); + setAcceptDrops(true); + + // + // Prepare menus and status bar + // + mAction.bookmarkMapper = new QSignalMapper(this); + connect(mAction.bookmarkMapper, SIGNAL(mapped(int)), editor(), SLOT(gotoBookmark(int))); + setupActions(); + setupStatusBar(); + + connect( hexView(), SIGNAL( cursorChanged( SCursorState & ) ), + this, SLOT( cursorChanged( SCursorState & ) ) ); + connect( hexView(), SIGNAL( editMode( CHexBuffer::EEditMode ) ), + this, SLOT( editMode( CHexBuffer::EEditMode ) ) ); + connect( hexView(), SIGNAL( encodingChanged( const SEncodeState &)), + this, SLOT( encodingChanged( const SEncodeState & )) ); + connect( hexView(), SIGNAL( textWidth( uint ) ), + this, SLOT( textWidth( uint ) ) ); + connect( hexView(), SIGNAL( fileState( SFileState & ) ), + this, SLOT( fileState( SFileState & ) ) ); + connect( hexView(), SIGNAL( layoutChanged( const SDisplayLayout & ) ), + this, SLOT( layoutChanged( const SDisplayLayout & ) ) ); + connect( hexView(), SIGNAL( inputModeChanged( const SDisplayInputMode & ) ), + this, SLOT( inputModeChanged( const SDisplayInputMode & ) ) ); + connect( hexView(), SIGNAL( bookmarkChanged( QPtrList &)), + this, SLOT( bookmarkChanged( QPtrList & ) ) ); + connect( hexView(), SIGNAL( fileName( const QString &, bool ) ), + this, SLOT( fileActive( const QString &, bool ) ) ); + connect( hexView(), SIGNAL( fileRename( const QString &, const QString & )), + this, SLOT( fileRename( const QString &, const QString & ) ) ); + connect( hexView(), SIGNAL( fileClosed( const QString & ) ), + this, SLOT( fileClosed( const QString & ) ) ); + connect( editor(), SIGNAL( errorLoadFile( const QString & ) ), + this, SLOT( removeRecentFile( const QString & ) ) ); + connect( editor(), SIGNAL( operationChanged( bool ) ), + this, SLOT( operationChanged( bool ) ) ); + connect( editor(), SIGNAL( removeRecentFiles() ), + this, SLOT( removeRecentFiles() ) ); + connect( mManager, SIGNAL( conversionClosed() ), + this, SLOT(conversionClosed()) ); + connect( mManager, SIGNAL( searchBarClosed() ), + this, SLOT(searchBarClosed()) ); + + // + // Read configuration from file and set the default editor size. + // Open files if this is the first toplevel window. + // + readConfiguration(); + initialize( mWindowList.count() == 1 ? true : false ); + setAutoSaveSettings(); +} + + +KHexEdit::~KHexEdit( void ) +{ + delete mAction.bookmarkMapper; + delete mManager; +} + + +void KHexEdit::setupActions( void ) +{ + KStdAction::openNew( editor(), SLOT(newFile()), actionCollection() ); + KStdAction::open( editor(), SLOT(open()), actionCollection() ); + KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), +actionCollection()); + + mAction.insert = new KAction( i18n("&Insert..."), CTRL+Key_I, + editor(), SLOT(insertFile()), actionCollection(), "insert_file" ); + mAction.openRecent = KStdAction::openRecent( this, SLOT( slotFileOpenRecent( const KURL& ) ), actionCollection() ); + mAction.save = KStdAction::save( editor(), SLOT(save()), actionCollection() ); + mAction.saveAs = KStdAction::saveAs( editor(), SLOT(saveAs()), actionCollection() ); + mAction.revert = KStdAction::revert( editor(), SLOT(reload()), actionCollection() ); + //mAction.revert = KStdAction::revert( this, SLOT(resizeTest()), actionCollection() ); + + mAction.close = KStdAction::close( editor(), SLOT(close()), actionCollection() ); + mAction.print = KStdAction::print( editor(), SLOT(print()), actionCollection() ); + mAction.exportData = new KAction( i18n("E&xport..."), 0, + editor(), SLOT(exportDialog()), actionCollection(), "export" ); + mAction.cancel = new KAction( i18n("&Cancel Operation"), + "stop", 0, editor(), SLOT(stop()), actionCollection(), "cancel" ); + mAction.readOnly = new KToggleAction( i18n("&Read Only"), + 0, editor(), SLOT(toggleWriteProtection()),actionCollection(), "read_only" ); + mAction.resizeLock = new KToggleAction( i18n("&Allow Resize"), + 0, editor(), SLOT(toggleResizeLock()),actionCollection(), "resize_lock" ); + mAction.newWindow = new KAction( i18n("N&ew Window"), + 0, this, SLOT(newWindow()),actionCollection(), "new_window" ); + mAction.closeWindow= new KAction( i18n("Close &Window"), + 0, this, SLOT(closeWindow()),actionCollection(), "close_window" ); + mAction.quit = KStdAction::quit( this, SLOT(closeProgram()), actionCollection() ); + + mAction.undo = KStdAction::undo( editor(), SLOT(undo()), actionCollection() ); + mAction.redo = KStdAction::redo( editor(), SLOT(redo()), actionCollection() ); + mAction.cut = KStdAction::cut( editor(), SLOT(cut()), actionCollection() ); + mAction.copy = KStdAction::copy( editor(), SLOT(copy()), actionCollection() ); + mAction.paste = KStdAction::paste( editor(), SLOT(paste()), actionCollection() ); + mAction.selectAll = KStdAction::selectAll(editor(), SLOT(selectAll()),actionCollection() ); + mAction.unselect = KStdAction::deselect(editor(), SLOT(unselect()), actionCollection()); + mAction.find = KStdAction::find( editor(), SLOT(find()), actionCollection() ); + mAction.findNext = KStdAction::findNext(editor(), SLOT(findNext()), actionCollection() ); + mAction.findPrev = KStdAction::findPrev(editor(),SLOT(findPrevious()),actionCollection() ); + mAction.replace = KStdAction::replace( editor(), SLOT(replace()), actionCollection() ); + mAction.gotoOffset = new KAction( i18n("&Goto Offset..."), CTRL+Key_G, + editor(), SLOT(gotoOffset()),actionCollection(), "goto_offset" ); + mAction.insertPattern = new KAction( i18n("&Insert Pattern..."), CTRL+Key_Insert, + editor(), SLOT(insertPattern()), actionCollection(), "insert_pattern" ); + + mAction.copyAsText = new KAction( i18n("Copy as &Text"), 0, + editor(), SLOT(copyText()), actionCollection(), "copy_as_text" ); + mAction.pasteToNewFile = new KAction( i18n("Paste into New &File"), 0, + editor(), SLOT(pasteNewFile()), actionCollection(), "paste_into_new_file" ); + mAction.pasteToNewWindow = new KAction( i18n("Paste into New &Window"), 0, + this, SLOT(pasteNewWindow()), actionCollection(), "paste_into_new_window" ); + + mAction.hexadecimal = new KRadioAction( i18n("&Hexadecimal"), + 0, this, SLOT(setDisplayMode()), actionCollection(), "mode_hex" ); + mAction.decimal = new KRadioAction( i18n("&Decimal"), + 0, this, SLOT(setDisplayMode()), actionCollection(), "mode_dec" ); + mAction.octal = new KRadioAction( i18n("&Octal"), + 0, this, SLOT(setDisplayMode()), actionCollection(), "mode_oct" ); + mAction.binary = new KRadioAction( i18n("&Binary"), + 0, this, SLOT(setDisplayMode()), actionCollection(), "mode_bin" ); + mAction.textOnly = new KRadioAction( i18n("&Text"), + 0, this, SLOT(setDisplayMode()), actionCollection(), "mode_text" ); + mAction.hexadecimal->setExclusiveGroup( "displayMode" ); + mAction.decimal->setExclusiveGroup( "displayMode" ); + mAction.octal->setExclusiveGroup( "displayMode" ); + mAction.binary->setExclusiveGroup( "displayMode" ); + mAction.textOnly->setExclusiveGroup( "displayMode" ); + + mAction.showOffsetColumn = new KToggleAction( i18n("Show O&ffset Column"), + 0, editor(), SLOT(toggleOffsetColumnVisibility()),actionCollection(), "show_offset_column" ); + mAction.showTextColumn = new KToggleAction( i18n("Show Te&xt Field"), + 0, editor(), SLOT(toggleTextColumnVisibility()),actionCollection(), "show_text_field" ); + mAction.offsetAsDecimal = new KToggleAction( i18n("Off&set as Decimal"), + 0, editor(), SLOT(toggleOffsetAsDecimal()),actionCollection(), "offset_as_decimal" ); + mAction.dataUppercase = new KToggleAction( i18n("&Upper Case (Data)"), + 0, editor(), SLOT(toggleDataUppercase()),actionCollection(), "upper_case_data" ); + mAction.offsetUppercase = new KToggleAction( i18n("Upper &Case (Offset)"), + 0, editor(), SLOT(toggleOffsetUppercase()),actionCollection(), "upper_case_offset" ); + + mAction.defaultEncoding = new KRadioAction( i18n("&Default encoding", "&Default"), + 0, this, SLOT( setEncoding()), actionCollection(), "enc_default" ); + mAction.usAsciiEncoding = new KRadioAction( i18n("US-&ASCII (7 bit)"), + 0, this, SLOT( setEncoding()), actionCollection(), "enc_ascii"); + mAction.ebcdicEncoding = new KRadioAction( i18n("&EBCDIC"), + 0, this, SLOT( setEncoding()), actionCollection(), "enc_ebcdic" ); +// mAction.customEncoding = new KAction( i18n("&Custom..."), +// 0, editor(), SLOT( encoding()), actionCollection(), "enc_custom" ); + mAction.defaultEncoding->setExclusiveGroup( "encodingMode" ); + mAction.usAsciiEncoding->setExclusiveGroup( "encodingMode" ); + mAction.ebcdicEncoding->setExclusiveGroup( "encodingMode" ); + + mAction.strings = new KAction( i18n("&Extract Strings..."), 0, + editor(), SLOT(strings()), actionCollection(), "extract_strings" ); +// mAction.recordViewer = new KAction( i18n("&Record Viewer"), 0, +// editor(), SLOT(recordView()), actionCollection(), "record_viewer" ); + mAction.filter = new KAction( i18n("&Binary Filter..."), 0, + editor(), SLOT(filter()), actionCollection(), "binary_filter" ); + mAction.characterTable = new KAction( i18n("&Character Table"), 0, + editor(), SLOT(chart()), actionCollection(), "char_table" ); + mAction.converter = new KAction( i18n("C&onverter"), 0, + editor(), SLOT(converter()), actionCollection(), "converter" ); + mAction.statistics = new KAction( i18n("&Statistics"), 0, + editor(), SLOT(statistics()), actionCollection(), "statistics" ); + + mAction.addBookmark = KStdAction::addBookmark( editor(), + SLOT(addBookmark()), actionCollection() ); + mAction.replaceBookmark = new KAction( i18n("&Replace Bookmark"), CTRL+Key_E, + editor(), SLOT(replaceBookmark()), actionCollection(), "replace_bookmark"); + mAction.removeBookmark = new KAction( i18n("R&emove Bookmark"), CTRL+Key_U, + editor(), SLOT(removeBookmark()), actionCollection(), "remove_bookmark" ); + mAction.removeAllBookmark = new KAction( i18n("Re&move All"), 0, + editor(), SLOT(removeAllBookmark()), actionCollection(), "remove_all_bookmarks" ); + mAction.nextBookmark = new KAction( i18n("Goto &Next Bookmark"), + ALT+Key_Down, editor(), + SLOT(gotoNextBookmark()), actionCollection(), "next_bookmark" ); + mAction.prevBookmark = new KAction( i18n("Goto &Previous Bookmark"), + ALT+Key_Up, editor(), + SLOT(gotoPrevBookmark()), actionCollection(), "prev_bookmark" ); + + createStandardStatusBarAction(); + setStandardToolBarMenuEnabled(true); + mAction.showFullPath = new KToggleAction( i18n("Show F&ull Path"), + 0, this, SLOT(showFullPath()), actionCollection(), "show_full_path" ); + + mAction.tabHide = new KRadioAction( i18n("&Hide"), + 0, this, SLOT(showDocumentTabs()), actionCollection(), "doctab_hide" ); + mAction.tabShowAboveEditor = new KRadioAction( i18n("&Above Editor"), + 0, this, SLOT(showDocumentTabs()), actionCollection(), "doctab_above" ); + mAction.tabShowBelowEditor = new KRadioAction( i18n("&Below Editor"), + 0, this, SLOT(showDocumentTabs()), actionCollection(), "doctab_below" ); + mAction.tabHide->setExclusiveGroup( "editorTab" ); + mAction.tabShowAboveEditor->setExclusiveGroup( "editorTab" ); + mAction.tabShowBelowEditor->setExclusiveGroup( "editorTab" ); + + mAction.conversionHide = new KRadioAction( i18n("&Hide"), + 0, this, SLOT(showConversionField()), actionCollection(), "conversion_field_hide"); + mAction.conversionFloat = new KRadioAction( i18n("&Floating"), + 0, this, SLOT(showConversionField()), actionCollection(), "conversion_field_float"); + mAction.conversionEmbed = new KRadioAction( i18n("&Embed in Main Window"), + 0, this, SLOT(showConversionField()), actionCollection(), "conversion_field_embed"); + mAction.conversionHide->setExclusiveGroup( "conversionField" ); + mAction.conversionFloat->setExclusiveGroup( "conversionField" ); + mAction.conversionEmbed->setExclusiveGroup( "conversionField" ); + + mAction.searchHide = new KRadioAction( i18n("&Hide"), + 0, this, SLOT(showSearchBar()), actionCollection(), "searchbar_hide" ); + mAction.searchShowAboveEditor = new KRadioAction( i18n("&Above Editor"), + Key_F5, this, SLOT(showSearchBar()), actionCollection(), "searchbar_above" ); + mAction.searchShowBelowEditor = new KRadioAction( i18n("&Below Editor"), + Key_F6, this, SLOT(showSearchBar()), actionCollection(), "searchbar_below" ); + mAction.searchHide->setExclusiveGroup( "searchBar" ); + mAction.searchShowAboveEditor->setExclusiveGroup( "searchBar" ); + mAction.searchShowBelowEditor->setExclusiveGroup( "searchBar" ); + + KStdAction::saveOptions(this, SLOT(writeConfiguration()), actionCollection()); + KStdAction::preferences(editor(),SLOT(options()),actionCollection() ); +// mAction.favorites = new KAction( i18n("P&rofiles..."), 0, +// editor(), SLOT(favorites()), actionCollection(), "favorites" ); + + KStdAction::help( this, SLOT(appHelpActivated()), actionCollection() ); + + mDragLabel = new CDragLabel(this); + mDragLabel->setPixmap( UserIcon( "hexdrag" ) ); + mDragLabel->setDragMask( UserIcon( "hexmask" ) ); + mDragLabel->setEnabled( false ); // Enabled once we open a document + QToolTip::add( mDragLabel, i18n("Drag document") ); + (void) new KWidgetAction(mDragLabel, i18n("Drag Document"), 0, editor(), SLOT(options()), actionCollection(), "drag_document"); + + createGUI("khexeditui.rc", false); + + QPopupMenu *popup = (QPopupMenu *)factory()->container("editor_popup", this); + hexView()->setPopupMenu( popup ); + + int id = 100; + toolBar(0)->insertButton( MainBarIcon("lock"), id, SIGNAL(clicked()), + editor(), SLOT(toggleWriteProtection()), true, + i18n("Toggle write protection") ); + toolBar(0)->alignItemRight( id ); + mWriteProtectButton = toolBar(0)->getButton(id); + + QPopupMenu *documentMenu = (QPopupMenu *)factory()->container("documents", this); + hexView()->setDocumentMenu(documentMenu); + connect(documentMenu, SIGNAL(activated(int)), SLOT(documentMenuCB(int))); + +} + + +void KHexEdit::setupStatusBar( void ) +{ + CStatusBarProgress *progess = new CStatusBarProgress( statusBar() ); + statusBar()->addWidget( progess, 10 ); + connect( progess, SIGNAL(pressed()), editor(), SLOT(stop()) ); + connect( editor(), SIGNAL( setProgress( int ) ), + progess, SLOT( setValue( int ) ) ); + connect( editor(), SIGNAL( setProgress( int, int ) ), + progess, SLOT( setValue( int, int ) ) ); + connect( editor(), SIGNAL( enableProgressText( bool ) ), + progess, SLOT( setTextEnabled( bool ) ) ); + connect( editor(), SIGNAL( setProgressText( const QString & ) ), + progess, SLOT( setText( const QString & ) ) ); + + statusBar()->insertFixedItem( i18n("Selection: 0000:0000 0000:0000"), + status_Selection ); + statusBar()->insertFixedItem( i18n("M"), status_Modified ); + statusBar()->insertFixedItem( i18n("OVR"), status_Ovr ); + statusBar()->insertFixedItem( i18n("Size: FFFFFFFFFF"), status_Size ); + statusBar()->insertFixedItem( i18n("Offset: FFFFFFFFFF-F"), status_Offset ); + statusBar()->insertFixedItem( i18n("FFF"), status_Layout ); + statusBar()->insertFixedItem( i18n("RW"), status_WriteProtect ); + + statusBar()->setItemAlignment( status_Selection, AlignLeft|AlignVCenter ); + statusBar()->setItemAlignment( status_Size, AlignLeft|AlignVCenter ); + statusBar()->setItemAlignment( status_Offset, AlignLeft|AlignVCenter ); + + // + // Some good default strings we can use after the fields have got + // their fixed width. + // + statusBar()->changeItem( i18n("Offset:"), status_Offset ); + statusBar()->changeItem( i18n("Size:"), status_Size ); + statusBar()->changeItem( "", status_Modified ); + statusBar()->changeItem( "", status_Selection ); + connect( statusBar(),SIGNAL(pressed(int)),this,SLOT(statusBarPressed(int)) ); +} + + +void KHexEdit::removeRecentFiles( void ) +{ + mAction.openRecent->clearURLList(); +} + + +void KHexEdit::initialize( bool openFiles ) +{ + mUndoState = CHexBuffer::UndoOk; // Reset in function below + setUndoState( 0 ); + + mSelectionOffset = 0; + mSelectionSize = 1; + mSelectionAsHexadecimal = true; + setSelectionState( 0, 0 ); + + operationChanged( false ); + + editor()->initialize(); + + mAction.showFullPath->setChecked( mShowFullPath ); + showFullPath(); + + if ( openFiles && editor()->openFile() != SDisplayMisc::none ) + { + // Code modified from kdelibs/kdeui/kactionclasses.cpp KRecentFilesAction::loadEntries + + KConfig* config = kapp->config(); + + const QString oldGroup = config->group(); + + const QString groupname = "RecentFiles"; + config->setGroup( groupname ); + + // read file list + unsigned int maxItems = mAction.openRecent->maxItems(); + if ( editor()->openFile() == SDisplayMisc::mostRecent ) + maxItems = 1; + for( unsigned int i = 1 ; i <= maxItems ; i++ ) + { + const QString key = QString( "File%1" ).arg( i ); + const QString value = config->readPathEntry( key ); + + if (!value.isEmpty()) + { + mStartupFileList.append( value ); + mStartupOffsetList.append( "0" ); // ### TODO find a way to still have kept offsets + } + } + + config->setGroup( oldGroup ); + + } + + // + // Open file(s) after editor has been displayed. + // Main reason: If anything goes wrong and an error dialog box + // is displayed, then the editor will not be visible until the error + // is confirmed and the (modal) dialog is closed. + // + QTimer::singleShot( 100, this, SLOT(delayedStartupOpen()) ); +} + + +void KHexEdit::delayedStartupOpen( void ) +{ + open( mStartupFileList, mStartupOffsetList ); + mStartupFileList.clear(); + mStartupOffsetList.clear(); +} + + +void KHexEdit::statusBarPressed( int id ) +{ + if( id == status_WriteProtect ) + { + editor()->toggleWriteProtection(); + } + else if( id == status_Ovr ) + { + editor()->toggleInsertMode(); + } + else if( id == status_Offset ) + { + editor()->toggleOffsetAsDecimal(); + } + else if( id == status_Selection ) + { + if( mSelectionSize > 0 ) + { + mSelectionAsHexadecimal = mSelectionAsHexadecimal == true ? false : true; + setSelectionText( mSelectionOffset, mSelectionSize ); + } + } + +} + + + +void KHexEdit::open( QStringList &fileList, QStringList &offsetList ) +{ + // + // We load in reverse to allow the first document in + // the list to become the active one. + // + + uint offset; + for( uint i = fileList.count(); i>0; i-- ) + { + if( i <= offsetList.count() ) + { + offset = (*offsetList.at(i-1)).toUInt(0,16); + } + else + { + offset = 0; + } + editor()->open( *fileList.at(i-1), true, offset ); + } +} + +void KHexEdit::addRecentFile( const QString &fileName ) +{ + if( fileName.isEmpty() == true ) + { + return; + } + + if( fileName.contains( i18n( "Untitled" ), false ) ) + { + return; + } + + const KURL url( KURL::fromPathOrURL( fileName ) ); + kdDebug(1501) << k_funcinfo << " adding recent " << fileName << " => " << url.prettyURL() << endl; + mAction.openRecent->addURL( url ); + +} + + +void KHexEdit::removeRecentFile( const QString &fileName ) +{ + if( fileName.isEmpty() == true ) + { + return; + } + + if( fileName.contains( i18n( "Untitled" ), false ) ) + { + return; + } + + const KURL url( KURL::fromPathOrURL( fileName ) ); + mAction.openRecent->removeURL( url ); + +} + + +void KHexEdit::renameRecentFile(const QString &curName, const QString &newName) +{ + if( curName.contains( i18n( "Untitled" ), false ) ) + { + addRecentFile( newName ); + } + else + { + mAction.openRecent->removeURL( KURL::fromPathOrURL( curName ) ); + mAction.openRecent->addURL( KURL::fromPathOrURL( newName ) ); + } +} + + + +void KHexEdit::slotFileOpenRecent( const KURL& url ) +{ + if ( url.isLocalFile() ) + { + editor()->open( url.path(), false, 0 ); + } + else + { + // ### TODO: support network transparency + KMessageBox::error( this, i18n("Non local recent file: %1").arg( url.prettyURL() ) ); + } +} + + +KHexEdit *KHexEdit::newWindow( void ) +{ + KHexEdit *hexEdit = new KHexEdit; + if( hexEdit == 0 ) + { + QString msg = i18n( "Can not create new window.\n" ); + msg += hexError( Err_NoMemory ); + KMessageBox::error( topLevelWidget(), msg ); + return(0); + } + hexEdit->show(); + return(hexEdit); +} + + + +void KHexEdit::pasteNewWindow( void ) +{ + KHexEdit *app = newWindow(); + if( app != 0 ) + { + app->editor()->pasteNewFile(); + } +} + + + +void KHexEdit::closeWindow( void ) +{ + close(); +} + + +void KHexEdit::closeProgram( void ) +{ + if( mWindowList.count() > 1 ) + { + for( KHexEdit *w = mWindowList.first(); w != 0; w = mWindowList.next() ) + { + if( w->editor()->modified() == true ) + { + QString msg = i18n("" + "There are windows with unsaved modified documents. " + "If you quit now, these modifications will be lost."); + int reply = KMessageBox::warningContinueCancel( topLevelWidget(), msg, QString::null, KStdGuiItem::quit() ); + if( reply == KMessageBox::Continue ) + { + break; + } + else + { + return; + } + } + } + + + // + // Ths will write current configuration to disk. + // + queryExit(); + + // + // Make sure every widget is destroyed. The reason why I do this + // (besides it is the clean way to do it) is to make sure any + // configuration updates in the various destructors are triggered. + // + mWindowList.setAutoDelete(true); + while( mWindowList.first() ) + { + mWindowList.removeRef( mWindowList.first() ); + } + + kapp->quit(); + } + else + { + closeWindow(); + } + +} + + +bool KHexEdit::queryClose( void ) +{ + bool success = editor()->closeAll(); + if( success == true ) + { + mWindowList.removeRef( this ); + } + + return( success ); +} + + +// +// We will always return true here. +// +bool KHexEdit::queryExit( void ) +{ + writeConfiguration(); + return( true ); +} + +void KHexEdit::readConfiguration( void ) +{ + KConfig &config = *kapp->config(); + readConfiguration( config ); +} + + +void KHexEdit::writeConfiguration( void ) +{ + KConfig &config = *kapp->config(); + writeConfiguration( config ); +} + + +void KHexEdit::writeConfiguration( KConfig &config ) +{ + saveMainWindowSettings(& config, "General Options"); + config.setGroup("General Options" ); + config.writeEntry("ShowFullPath", mShowFullPath ); + config.writeEntry("ConversionPosition", (int)mManager->conversionPosition()); + config.writeEntry("TabBarPosition", (int)mManager->tabBarPosition()); + config.writeEntry("SearchBarPosition", (int)mManager->searchBarPosition()); + + if ( editor()->discardRecentFiles() ) + mAction.openRecent->clearURLList(); + mAction.openRecent->saveEntries( &config ); + + converter()->writeConfiguration( config ); + editor()->writeConfiguration( config ); + + config.sync(); +} + + +void KHexEdit::readConfiguration( KConfig &config ) +{ + applyMainWindowSettings(& config, "General Options"); + + config.setGroup("General Options"); + mShowFullPath = config.readBoolEntry( "ShowFullPath", true ); + int position = config.readNumEntry( "ConversionPosition", + CHexManagerWidget::Embed ); + + mAction.conversionHide->blockSignals(true); + mAction.conversionFloat->blockSignals(true); + mAction.conversionEmbed->blockSignals(true); + mAction.conversionHide->setChecked( + position == CHexManagerWidget::Hide ); + mAction.conversionFloat->setChecked( + position == CHexManagerWidget::Float ); + mAction.conversionEmbed->setChecked( + position == CHexManagerWidget::Embed ); + mAction.conversionHide->blockSignals(false); + mAction.conversionFloat->blockSignals(false); + mAction.conversionEmbed->blockSignals(false); + showConversionField(); + + position = config.readNumEntry( "TabBarPosition", CHexManagerWidget::Hide ); + mAction.tabHide->blockSignals(true); + mAction.tabShowAboveEditor->blockSignals(true); + mAction.tabShowBelowEditor->blockSignals(true); + mAction.tabHide->setChecked( + position==CHexManagerWidget::Hide ); + mAction.tabShowAboveEditor->setChecked( + position==CHexManagerWidget::AboveEditor ); + mAction.tabShowBelowEditor->setChecked( + position==CHexManagerWidget::BelowEditor ); + mAction.tabHide->blockSignals(false); + mAction.tabShowAboveEditor->blockSignals(false); + mAction.tabShowBelowEditor->blockSignals(false); + showDocumentTabs(); + + position = config.readNumEntry( "SearchBarPosition", + CHexManagerWidget::BelowEditor ); + mAction.searchHide->blockSignals(true); + mAction.searchShowAboveEditor->blockSignals(true); + mAction.searchShowBelowEditor->blockSignals(true); + mAction.searchHide->setChecked( + position==CHexManagerWidget::Hide ); + mAction.searchShowAboveEditor->setChecked( + position==CHexManagerWidget::AboveEditor ); + mAction.searchShowBelowEditor->setChecked( + position==CHexManagerWidget::BelowEditor ); + mAction.searchHide->blockSignals(false); + mAction.searchShowAboveEditor->blockSignals(false); + mAction.searchShowBelowEditor->blockSignals(false); + showSearchBar(); + + mAction.openRecent->loadEntries( &config ); + + converter()->readConfiguration( config ); + editor()->readConfiguration( config ); +} + + + +void KHexEdit::operationChanged( bool state ) +{ + mAction.cancel->setEnabled( state ); +} + + + +void KHexEdit::cursorChanged( SCursorState &state ) +{ + QString offset( i18n("Offset:") ); + + if( state.valid == false ) + { + statusBar()->changeItem( offset, status_Offset ); + } + else + { + SDisplayLayout &layout = editor()->layout(); + + if( layout.offsetMode == SDisplayLayout::hexadecimal ) + { + if( layout.offsetUpperCase == false ) + { + offset += QString().sprintf( " %04x:%04x-%u", state.offset>>16, + state.offset&0x0000FFFF, state.cell ); + } + else + { + offset += QString().sprintf( " %04X:%04X-%u", state.offset>>16, + state.offset&0x0000FFFF, state.cell ); + } + } + else + { + offset += QString().sprintf( " %010u-%u", state.offset, state.cell ); + } + statusBar()->changeItem( offset, status_Offset ); + } + + setUndoState( state.undoState ); + setSelectionState( state.selectionOffset, state.selectionSize ); +} + + + + +void KHexEdit::fileState( SFileState &state ) +{ + if( state.valid == true ) + { + statusBar()->changeItem( i18n("Size: %1").arg( state.size ), status_Size); + statusBar()->changeItem( state.modified ? "!" : "", status_Modified); + + if( mIsModified != state.modified ) + { + mIsModified = state.modified; + setupCaption( hexView()->url() ); + } + + } + else + { + statusBar()->changeItem( "", status_Size ); + statusBar()->changeItem( "", status_Modified ); + } +} + + + +void KHexEdit::layoutChanged( const SDisplayLayout &layout ) +{ + KRadioAction *radioAction; + + if( layout.primaryMode == SDisplayLayout::hexadecimal ) + { + radioAction = mAction.hexadecimal; + } + else if( layout.primaryMode == SDisplayLayout::decimal ) + { + radioAction = mAction.decimal; + } + else if( layout.primaryMode == SDisplayLayout::octal ) + { + radioAction = mAction.octal; + } + else if( layout.primaryMode == SDisplayLayout::binary ) + { + radioAction = mAction.binary; + } + else + { + radioAction = mAction.textOnly; + } + radioAction->blockSignals(true); + radioAction->setChecked( true ); + radioAction->blockSignals(false); + + mAction.showOffsetColumn->blockSignals(true); + mAction.showTextColumn->blockSignals(true); + mAction.offsetAsDecimal->blockSignals(true); + mAction.dataUppercase->blockSignals(true); + mAction.offsetUppercase->blockSignals(true); + + mAction.showOffsetColumn->setChecked( layout.offsetVisible ); + mAction.showTextColumn->setEnabled( + layout.primaryMode != SDisplayLayout::textOnly ); + mAction.showTextColumn->setChecked( + layout.secondaryMode != SDisplayLayout::hide ); + mAction.offsetAsDecimal->setChecked( + layout.offsetMode != SDisplayLayout::hexadecimal); + mAction.dataUppercase->setChecked( layout.primaryUpperCase ); + mAction.offsetUppercase->setChecked( layout.offsetUpperCase ); + + mAction.showOffsetColumn->blockSignals(false); + mAction.showTextColumn->blockSignals(false); + mAction.offsetAsDecimal->blockSignals(false); + mAction.dataUppercase->blockSignals(false); + mAction.offsetUppercase->blockSignals(false); + + if( layout.primaryMode == SDisplayLayout::hexadecimal ) + { + statusBar()->changeItem( i18n("Hex"), status_Layout ); + } + else if( layout.primaryMode == SDisplayLayout::decimal ) + { + statusBar()->changeItem( i18n("Dec"), status_Layout ); + } + else if( layout.primaryMode == SDisplayLayout::octal ) + { + statusBar()->changeItem( i18n("Oct"), status_Layout ); + } + else if( layout.primaryMode == SDisplayLayout::binary ) + { + statusBar()->changeItem( i18n("Bin"), status_Layout ); + } + else if( layout.primaryMode == SDisplayLayout::textOnly ) + { + statusBar()->changeItem( i18n("Txt"), status_Layout ); + } +} + + +void KHexEdit::inputModeChanged( const SDisplayInputMode &mode ) +{ + mAction.readOnly->blockSignals(true); + mAction.resizeLock->blockSignals(true); + mAction.readOnly->setChecked( mode.readOnly ); + mAction.resizeLock->setChecked( mode.allowResize ); + mAction.readOnly->blockSignals(false); + mAction.resizeLock->blockSignals(false); + + statusBar()->changeItem( mode.readOnly == true ? + i18n("R") : i18n("RW"), status_WriteProtect ); + + if( mode.readOnly == false ) + { + mWriteProtectButton->setIcon("edit"); + } + else + { + mWriteProtectButton->setIcon("lock"); + } +} + + +void KHexEdit::bookmarkChanged( QPtrList &list ) +{ + unplugActionList("bookmark_list"); + mAction.bookmarkList.setAutoDelete(true); + mAction.bookmarkList.clear(); + + if( list.count() == 0 ) + { + return; + } + + mAction.bookmarkList.append(new KActionSeparator()); + + QString text, offset; + int i=0; + + for( SCursorOffset *p=list.first(); p!=0; p=list.next(), i++ ) + { + offset.sprintf("%04X:%04X", p->offset>>16, p->offset&0x0000FFFF ); + text = i18n("Offset: %1").arg(offset); + KAction *action = new KAction(text, 0, mAction.bookmarkMapper, SLOT(map()), this, text.latin1()); + int key = acceleratorNumKey( i ); + if( key > 0 ) + { + action->setShortcut(KShortcut(ALT+key)); + } + mAction.bookmarkMapper->setMapping(action, i); + mAction.bookmarkList.append(action); + } + plugActionList("bookmark_list", mAction.bookmarkList); +} + + +void KHexEdit::setupCaption( const QString &url ) +{ + KURL u(url); + if( mShowFullPath == true ) + { + setCaption( u.prettyURL(), hexView()->modified() ); + } + else + { + setCaption( u.fileName(), hexView()->modified() ); + } +} + + +void KHexEdit::fileActive( const QString &url, bool onDisk ) +{ + setupCaption( url ); + mDragLabel->setUrl( url ); + mDragLabel->setEnabled( onDisk ); + + mAction.revert->setEnabled( onDisk ); + + if( url.isNull() == false ) + { + addDocument( url ); + addRecentFile( url ); + setTickedDocument( url ); + } +} + + +void KHexEdit::fileRename( const QString &curName, const QString &newName ) +{ + if( newName.isNull() == true ) + { + return; + } + + renameDocument( curName, newName ); + renameRecentFile( curName, newName ); + setupCaption( newName ); + //setCaption( newName ); +} + + +void KHexEdit::fileClosed( const QString &url ) +{ + removeDocument( url ); +} + + +void KHexEdit::editMode( CHexBuffer::EEditMode editMode ) +{ + statusBar()->changeItem( editMode == CHexBuffer::EditReplace ? + i18n("OVR") : i18n("INS"), status_Ovr ); +} + + +void KHexEdit::encodingChanged( const SEncodeState &encodeState ) +{ + KRadioAction *radioAction; + + if( encodeState.mode == CConversion::cnvDefault ) + { + radioAction = mAction.defaultEncoding; + } + else if( encodeState.mode == CConversion::cnvUsAscii ) + { + radioAction = mAction.usAsciiEncoding; + } + else if( encodeState.mode == CConversion::cnvEbcdic ) + { + radioAction = mAction.ebcdicEncoding; + } + else + { + return; + } + + radioAction->blockSignals(true); + radioAction->setChecked( true ); + radioAction->blockSignals(false); + + if( mSelectionSize == 0 ) + { + statusBar()->changeItem( i18n("Encoding: %1").arg(encodeState.name), + status_Selection ); + } +} + + +void KHexEdit::textWidth( uint ) +{ + resize( mManager->preferredWidth(), height() ); +} + + +void KHexEdit::setDisplayMode( void ) +{ + if( mAction.hexadecimal->isChecked() == true ) + { + editor()->setHexadecimalMode(); + } + else if( mAction.decimal->isChecked() == true ) + { + editor()->setDecimalMode(); + } + else if( mAction.octal->isChecked() == true ) + { + editor()->setOctalMode(); + } + else if( mAction.binary->isChecked() == true ) + { + editor()->setBinaryMode(); + } + else if( mAction.textOnly->isChecked() == true ) + { + editor()->setTextMode(); + } +} + + +void KHexEdit::showFullPath( void ) +{ + mShowFullPath = mAction.showFullPath->isChecked(); + setupCaption( hexView()->url() ); +} + + +void KHexEdit::showDocumentTabs( void ) +{ + if( mAction.tabHide->isChecked() == true ) + { + mManager->setTabBarPosition( CHexManagerWidget::HideItem ); + } + else if( mAction.tabShowAboveEditor->isChecked() == true ) + { + mManager->setTabBarPosition( CHexManagerWidget::AboveEditor ); + } + else if( mAction.tabShowBelowEditor->isChecked() == true ) + { + mManager->setTabBarPosition( CHexManagerWidget::BelowEditor ); + } +} + + +void KHexEdit::showConversionField( void ) +{ + if( mAction.conversionHide->isChecked() == true ) + { + mManager->setConversionVisibility( CHexManagerWidget::Hide ); + } + else if( mAction.conversionFloat->isChecked() == true ) + { + mManager->setConversionVisibility( CHexManagerWidget::Float ); + } + else if( mAction.conversionEmbed->isChecked() == true ) + { + mManager->setConversionVisibility( CHexManagerWidget::Embed ); + if( width() < mManager->preferredWidth() ) + { + resize( mManager->preferredWidth(), height() ); + } + } +} + + +void KHexEdit::showSearchBar( void ) +{ + if( mAction.searchHide->isChecked() == true ) + { + mManager->setSearchBarPosition( CHexManagerWidget::HideItem ); + } + else if( mAction.searchShowAboveEditor->isChecked() == true ) + { + mManager->setSearchBarPosition( CHexManagerWidget::AboveEditor ); + } + else if( mAction.searchShowBelowEditor->isChecked() == true ) + { + mManager->setSearchBarPosition( CHexManagerWidget::BelowEditor ); + } +} + + +void KHexEdit::setEncoding( void ) +{ + if( mAction.defaultEncoding->isChecked() == true ) + { + editor()->encode( CConversion::cnvDefault ); + } + else if( mAction.usAsciiEncoding->isChecked() == true ) + { + editor()->encode( CConversion::cnvUsAscii ); + } + else if( mAction.ebcdicEncoding->isChecked() == true ) + { + editor()->encode( CConversion::cnvEbcdic ); + } +} + + +void KHexEdit::setUndoState( uint undoState ) +{ + if( mUndoState != undoState ) + { + mUndoState = undoState; + mAction.undo->setEnabled( mUndoState & CHexBuffer::UndoOk ); + mAction.redo->setEnabled( mUndoState & CHexBuffer::RedoOk ); + } +} + + +void KHexEdit::setSelectionState( uint selectionOffset, uint selectionSize ) +{ + if( mSelectionSize != selectionSize ) + { + mSelectionOffset = selectionOffset; + mSelectionSize = selectionSize; + + bool valid = mSelectionSize > 0 ? true : false; + mAction.copy->setEnabled( valid ); + mAction.cut->setEnabled( valid ); + mAction.copyAsText->setEnabled( valid ); + + setSelectionText( selectionOffset, selectionSize ); + } +} + + +void KHexEdit::setSelectionText( uint selectionOffset, uint selectionSize ) +{ + if( selectionSize > 0 ) + { + QString selection = i18n("Selection:"); + if( mSelectionAsHexadecimal == true ) + { + selection += QString().sprintf( " %04x:%04x %04x:%04x", + selectionOffset>>16, selectionOffset&0x0000FFFF, + selectionSize>>16, selectionSize&0x0000FFFF ); + } + else + { + selection += QString().sprintf( " %08u %08u", + selectionOffset, selectionSize); + } + statusBar()->changeItem( selection, status_Selection ); + } + else + { + statusBar()->changeItem( + i18n("Encoding: %1").arg(hexView()->encoding().name), status_Selection); + } +} + + +void KHexEdit::documentMenuCB( int index ) +{ + if( (uint)index < mDocumentList.count() ) + { + editor()->open( mDocumentList[index], false, 0 ); + } +} + + +void KHexEdit::addDocument( const QString &fileName ) +{ + uint documentCount = mDocumentList.count(); + for( uint i=0; i < documentCount; i++ ) + { + if( fileName == mDocumentList[i] ) + { + return; + } + } + + mDocumentList.append( fileName ); + + QPopupMenu *documentMenu = (QPopupMenu *)factory()->container("documents", this); + documentMenu->insertItem( fileName, documentCount, documentCount ); + int key = acceleratorNumKey( documentCount ); + if( key > 0 ) + { + documentMenu->setAccel( CTRL+key, documentCount ); + } +} + + +void KHexEdit::removeDocument( const QString &fileName ) +{ + QStringList::Iterator it; + for( it = mDocumentList.begin(); it != mDocumentList.end(); it++ ) + { + if( *it == fileName ) + { + QPopupMenu *documentMenu = (QPopupMenu *)factory()->container("documents", this); + + documentMenu->removeItemAt( mDocumentList.findIndex(*it) ); + mDocumentList.remove( it ); + + for( uint i=0; i < mDocumentList.count(); i++ ) + { + documentMenu->setId( i, i ); + int key = acceleratorNumKey( i ); + if( key > 0 ) + { + documentMenu->setAccel( CTRL+key, i ); + } + } + return; + + } + } +} + + +void KHexEdit::renameDocument( const QString &curName, const QString &newName ) +{ + QStringList::Iterator it; + for( it = mDocumentList.begin(); it != mDocumentList.end(); it++ ) + { + if( *it == curName ) + { + QPopupMenu *documentMenu = (QPopupMenu *)factory()->container("documents", this); + documentMenu->changeItem( newName, mDocumentList.findIndex(*it) ); + mDocumentList.insert( it, newName ); + mDocumentList.remove( it ); + return; + } + } +} + + +void KHexEdit::setTickedDocument( const QString &fileName ) +{ + uint documentCount = mDocumentList.count(); + QPopupMenu *documentMenu = (QPopupMenu *)factory()->container("documents", this); + for( uint i=0; i < documentCount; i++ ) + { + documentMenu->setItemChecked( i, fileName == mDocumentList[i] ); + } +} + + +void KHexEdit::conversionClosed( void ) +{ + mAction.conversionHide->setChecked(true); +} + + +void KHexEdit::searchBarClosed( void ) +{ + mAction.searchHide->setChecked(true); +} + + +bool KHexEdit::eventFilter( QObject *o, QEvent *event ) +{ + if( event->type() == QEvent::DragEnter ) + { + QDragEnterEvent *e = (QDragEnterEvent*)event; + if( KURLDrag::canDecode(e) ) + { + e->accept(); + hexView()->setDropHighlight( true ); + } + return( true ); + } + else if( event->type() == QEvent::Drop ) + { + QMimeSource &m = *(QDropEvent*)event; + hexView()->setDropHighlight( false ); + + KURL::List list; + if( KURLDrag::decode( &m, list ) == true ) + { + QStringList offset; + QStringList urlList = list.toStringList(); + open( urlList, offset ); + return( true ); + } + return( true ); + } + else if( event->type() == QEvent::DragLeave ) + { + hexView()->setDropHighlight( false ); + return( true ); + } + + return KMainWindow::eventFilter( o, event ); +} + + +int KHexEdit::acceleratorNumKey( uint index ) +{ + static int keys[9] = + { + Key_1, Key_2, Key_3, Key_4, Key_5, Key_6, Key_7, Key_8, Key_9 + }; + return( index >= 9 ? -1 : keys[index] ); +} + + +#include +#include + +// +// This function is used to test kwin performance +// +void KHexEdit::resizeTest() +{ + struct timeval t1, t2; + gettimeofday( &t1, 0 ); + + int loop=400; + + for( int i=0; iprocessOneEvent(); + } + + gettimeofday( &t2, 0 ); + uint last = (t2.tv_sec-t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec); + + kdDebug(1501) << "Duration: " << (float)last/ 1000000.0 << endl; + kdDebug(1501) << "Duration/loop: " << (float)last/ (1000000.0*(float)loop) << endl; +} +#include "toplevel.moc" diff --git a/khexedit/toplevel.h b/khexedit/toplevel.h new file mode 100644 index 0000000..fbacca1 --- /dev/null +++ b/khexedit/toplevel.h @@ -0,0 +1,279 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999-2000 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _TOPLEVEL_H_ +#define _TOPLEVEL_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "hexbuffer.h" +#include "hexmanagerwidget.h" +#include "statusbarprogress.h" + +class QSignalMapper; +class KAction; +class KRecentFilesAction; +class KRadioAction; +class KSelectAction; +class KToggleAction; +class KToolBarButton; +class KURL; +class CDragLabel; + + +class KHexEdit : public KMainWindow +{ + Q_OBJECT + + enum StatusBarId + { + status_WriteProtect = 0, + status_Layout = 1, + status_Offset = 2, + status_Size = 3, + status_Ovr = 4, + status_Modified = 5, + status_Selection = 6, + status_Progress = 7 + }; + + struct SActionList + { + KAction *insert; + KRecentFilesAction *openRecent; + KAction *save; + KAction *saveAs; + KAction *revert; + KAction *close; + KAction *print; + KAction *exportData; + KAction *cancel; + KToggleAction *readOnly; + KToggleAction *resizeLock; + KAction *newWindow; + KAction *closeWindow; + KAction *quit; + KAction *undo; + KAction *redo; + KAction *cut; + KAction *copy; + KAction *paste; + KAction *selectAll; + KAction *unselect; + KAction *find; + KAction *findNext; + KAction *findPrev; + KAction *replace; + KAction *gotoOffset; + KAction *insertPattern; + KAction *copyAsText; + KAction *pasteToNewFile; + KAction *pasteToNewWindow; + KRadioAction *hexadecimal; + KRadioAction *decimal; + KRadioAction *octal; + KRadioAction *binary; + KRadioAction *textOnly; + KToggleAction *showOffsetColumn; + KToggleAction *showTextColumn; + KToggleAction *offsetAsDecimal; + KToggleAction *dataUppercase; + KToggleAction *offsetUppercase; + KRadioAction *defaultEncoding; + KRadioAction *usAsciiEncoding; + KRadioAction *ebcdicEncoding; +// KAction *customEncoding; + + KAction *strings; +// KAction *recordViewer; + KAction *filter; + KAction *characterTable; + KAction *converter; + KAction *statistics; + + KAction *addBookmark; + KAction *replaceBookmark; + KAction *removeBookmark; + KAction *removeAllBookmark; + KAction *nextBookmark; + KAction *prevBookmark; + + KToggleAction *showFullPath; + KRadioAction *tabHide; + KRadioAction *tabShowBelowEditor; + KRadioAction *tabShowAboveEditor; + KRadioAction *conversionHide; + KRadioAction *conversionFloat; + KRadioAction *conversionEmbed; + KRadioAction *searchHide; + KRadioAction *searchShowAboveEditor; + KRadioAction *searchShowBelowEditor; + +// KAction *favorites; + + QPtrList< KAction > bookmarkList; + QSignalMapper *bookmarkMapper; + }; + + public: + KHexEdit( void ); + ~KHexEdit( void ); + + inline void addStartupFile( const QString &fileName ); + inline void setStartupOffset( uint offset ); + + public slots: + KHexEdit *newWindow( void ); + void pasteNewWindow( void ); + void closeWindow( void ); + void closeProgram( void ); + void statusBarPressed( int id ); + + void operationChanged( bool state ); + void cursorChanged( SCursorState &state ); + void fileState( SFileState &state ); + void layoutChanged( const SDisplayLayout &layout ); + void inputModeChanged( const SDisplayInputMode &mode ); + void bookmarkChanged( QPtrList &list ); + void removeRecentFile( const QString &fileName ); + void renameRecentFile( const QString &curName, const QString &newName ); + + void setupCaption( const QString &url ); + void fileActive( const QString &url, bool onDisk ); + void fileRename( const QString &curName, const QString &newName ); + void fileClosed( const QString &url ); + void readConfiguration( void ); + void writeConfiguration( void ); + void editMode( CHexBuffer::EEditMode editMode ); + void encodingChanged( const SEncodeState &state ); + void textWidth( uint width ); + + void setDisplayMode( void ); + void showFullPath( void ); + void showDocumentTabs( void ); + void showConversionField( void ); + void showSearchBar( void ); + + void setEncoding( void ); + void documentMenuCB( int id ); + + /** + * Slot for opening a file among the recently opened files. + */ + void slotFileOpenRecent( const KURL & ); + +protected: + virtual bool queryExit( void ); + virtual bool queryClose( void ); + + private slots: + void delayedStartupOpen( void ); + void removeRecentFiles( void ); + void conversionClosed( void ); + void searchBarClosed( void ); + void resizeTest(); + + private: + void setupActions( void ); + void setupStatusBar( void ); + void open( QStringList &fileList, QStringList &offsetList ); + void initialize( bool openFiles ); + void addRecentFile( const QString &fileName ); + bool closeAllWindow( void ); + void setUndoState( uint undoState ); + void setSelectionState( uint selectionOffset, uint selectionSize ); + void setSelectionText( uint selectionOffset, uint selectionSize ); + void addDocument( const QString &fileName ); + void removeDocument( const QString &fileName ); + void renameDocument( const QString &curName, const QString &newName ); + void setTickedDocument( const QString &fileName ); + + void writeConfiguration( KConfig &config ); + void readConfiguration( KConfig &config ); + bool eventFilter( QObject *obj, QEvent *event ); + + int acceleratorNumKey( uint index ); + inline CHexEditorWidget *editor( void ); + inline CHexToolWidget *converter( void ); + inline CHexViewWidget *hexView( void ); + + private: + static QPtrList mWindowList; + CHexManagerWidget *mManager; + QStringList mDocumentList; + + QStringList mStartupFileList; ///< Files to automatically open on startup + QStringList mStartupOffsetList; ///< Start offset for those files. + uint mStartupOffset; ///< Value read from the command line + + SActionList mAction; + + CDragLabel *mDragLabel; + KToolBarButton *mWriteProtectButton; + + bool mIsModified; + bool mShowFullPath; + bool mSelectionAsHexadecimal; + uint mSelectionOffset; + uint mSelectionSize; + uint mUndoState; + int mRecentFileId; +}; + + +inline void KHexEdit::addStartupFile( const QString &fileName ) +{ + mStartupFileList.prepend( fileName ); + mStartupOffsetList.prepend( QString("%1").arg(mStartupOffset,0,16) ); + mStartupOffset = 0; +} + +inline void KHexEdit::setStartupOffset( uint offset ) +{ + mStartupOffset = offset; +} + +inline CHexEditorWidget *KHexEdit::editor( void ) +{ + return( mManager->editor() ); +} + +inline CHexViewWidget *KHexEdit::hexView( void ) +{ + return( mManager->editor()->view() ); +} + +inline CHexToolWidget *KHexEdit::converter( void ) +{ + return( mManager->converter() ); +} + + + +#endif + + diff --git a/khexedit/version.h b/khexedit/version.h new file mode 100644 index 0000000..536fa35 --- /dev/null +++ b/khexedit/version.h @@ -0,0 +1,32 @@ +/* + * khexedit - Versatile hex editor + * Copyright (C) 1999 Espen Sand, espensa@online.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _VERSION_H_ +#define _VERSION_H_ + +// +// Just a few replacements for defines in config.h I used when this +// program lived outside CVS +// +#define APP_PACKAGE_STRING "khexedit" +#define APP_VERSION_STRING "0.8.6" + + +#endif diff --git a/kjots/ANNOUNCE b/kjots/ANNOUNCE new file mode 100644 index 0000000..d9a696f --- /dev/null +++ b/kjots/ANNOUNCE @@ -0,0 +1,26 @@ +kjots (version 0.3.0) - a note taker +------------------------------------ + +Hi ! + +New versions of kjots go directly into the kdeutils distribution. +This is for version 0.3.0. + +What is kjots +------------- + +Name and idea for this program are taken from the jots program included +in the tkgoodstuff package by Mark Crimmins (markcrim@umich.edu). + +Kjots helps you to write down some notes and maybe reduces the stack of +paper lying on your desk. + +New in this version +------------------- + +- added lots of keyboard shortcuts + + +Regards. + + Chris. diff --git a/kjots/BUGS b/kjots/BUGS new file mode 100644 index 0000000..f8de6a4 --- /dev/null +++ b/kjots/BUGS @@ -0,0 +1,6 @@ +kjots - a note taker +------------------------------------ + +Please use the bug tracking system at http://bugs.kde.org to +report bugs. + diff --git a/kjots/CHANGES b/kjots/CHANGES new file mode 100644 index 0000000..9815d90 --- /dev/null +++ b/kjots/CHANGES @@ -0,0 +1,75 @@ + +new in version 0.5 (Aaron J. Seigo) +- redesign of UI +- use of XMLGUI +- simplification of internals +- insertion of date and time +- printing +- stability improvements +- made KUniqueApp + +(Carsten Pfeiffer ) +- use KEdit instead of QMultiLineEdit directly + -> gains Search & replace + undo +- allocate KTMainWindow on the heap to avoid double deletion on quit + +new in version 0.4 (Mario Weilguni ) +- works now with Qt 2.0 +- fixed broken layout of main window +- layout improvements in AskFileName() +- layout improvements in SubjList() +- compiles without warnings +- "Apply" button is only activated when changes were made +- improved layout of configuration dialog +- fixed a bug in the font selection + +- now compiles with EGCS ( Robert Williams ) + +new in version 0.3.0 +- added lots of keyboard shortcuts +- added klocale->translate() + +new in version 0.2.6 +- icons should be visible in the toolbar + +new in version 0.2.5 +- you may save books and pages to an ascii file +- more kde conforming due to the use of KTopLevelWidget + +new in version 0.2.4 +- uses kfontdialog to set the font of the editor widget +- you may select an URL in your text and press the right mouse button + to execute a program with this URL. The program to execute is + configurable for http and ftp URLs. +- some code cleanup + +new in version 0.2.3 +- compiles with libkde-970510 NOTE: this version is needed ! +- shouldn't segfault, if you delete pages +- double clicking on an entry in the subjectlist closes the subjectlist window +- fixed fonds -> fonts ;) + +new in version 0.2.2 +- compiles with libkde-0.7.2 +- several bug fixes + +new in version 0.2.1 + +- should compile cleanly with libqt1.2 and libkde-0.7.1 and later + +new in version 0.2.0 + +- changed the layout to be more KDE conforming (toolbar, statusbar,...) +- folders are now called books and entries are pages +- added subject to each page +- you may popup a window with a list of all subjects and use it to find + pages more easily +- further reduced the minimum size of the window + +new in version 0.1.1 + +- does not delete empty lines anymore +- you may insert TABs into your text +- the minimum size of the window is smaller now +- the size of the window is saved and read the next + time kjots is started diff --git a/kjots/KJotsMain.cpp b/kjots/KJotsMain.cpp new file mode 100644 index 0000000..a54cead --- /dev/null +++ b/kjots/KJotsMain.cpp @@ -0,0 +1,1199 @@ +// +// kjots +// +// Copyright (C) 1997 Christoph Neerfeld +// Copyright (C) 2002-2004 Aaron J. Seigo +// Copyright (C) 2003 Stanislav Kljuhhin +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "KJotsMain.h" +#include "KJotsSettings.h" +#include "kjotsbookmarks.h" +#include "kjotsedit.h" +#include "kjotsentry.h" +#include "confpagemisc.h" +#include "confpagefont.h" + +#define KJOTSVERSION "0.7" + +extern KIconLoader* global_pix_loader; + +//---------------------------------------------------------------------- +// KJOTSMAIN +//---------------------------------------------------------------------- +KJotsMain::KJotsMain(const char* name) + : KMainWindow(0,name), + currentEntry(0), + invalidMoveFlag(false) +{ + // + // Main widget + // + QWidget* f_main = new QFrame( this, "Frame_0" ); + setCentralWidget(f_main); + + splitter = new QSplitter(f_main); + splitter->setOpaqueResize( KGlobalSettings::opaqueResize() ); + + // the subject list + subjectList = new KListView(splitter, "subjectList"); + subjectList->setRootIsDecorated(true); + subjectList->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding)); + subjectList->setMinimumWidth(subjectList->fontMetrics().maxWidth() * 10 + 5); + subjectList->addColumn(i18n("Pages")); + subjectList->setFullWidth(true); + subjectList->setHScrollBarMode(QScrollView::AlwaysOff); + subjectList->setDefaultRenameAction(QListView::Accept); + subjectList->setSorting(-1); + subjectList->setAlternateBackground(QColor()); + subjectList->header()->hide(); + subjectList->setDragEnabled(true); + subjectList->setAcceptDrops(true); + subjectList->setItemsMovable(true); + subjectList->setItemsRenameable(true); + subjectList->setRenameable(0,true); + + textStack = new QWidgetStack(splitter); + + me_text = new KJotsEdit(textStack, "me_text"); + me_text->setFocusPolicy(QWidget::StrongFocus); + me_text->setEnabled(false); + textStack->addWidget(me_text); + connect(me_text, SIGNAL(findSuccessful()), this, SLOT(slotFindSuccessful())); + + roTextView = new KTextBrowser(textStack, "roTextView", true); + textStack->addWidget(roTextView); + + QVBoxLayout *bookGrid = new QVBoxLayout(f_main, KDialog::marginHint(), KDialog::spacingHint()); + bookGrid->addWidget(splitter, 0, 0); + bookGrid->setMargin(0); + splitter->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, 2, 1)); + + // create actions + actions[ACTION_NEXT_BOOK] = new KAction(i18n("Next Book"), QString::null, CTRL + Key_D, this, + SLOT(nextBook()), actionCollection(), "go_next_book"); + actions[ACTION_PREV_BOOK] = new KAction(i18n("Previous Book"), QString::null, CTRL + SHIFT + Key_D, this, + SLOT(prevBook()), actionCollection(), "go_prev_book"); + actions[ACTION_NEXT_PAGE] = new KAction(i18n("Next Page"), QString::null, CTRL + Key_PageDown, this, + SLOT(nextPage()), actionCollection(), "go_next_page"); + actions[ACTION_PREV_PAGE] = new KAction(i18n("Previous Page"), QString::null, CTRL + Key_PageUp, this, + SLOT(prevPage()), actionCollection(), "go_prev_page"); + + actions[ACTION_NEW_PAGE] = KStdAction::openNew(this, SLOT(newEntry()), actionCollection()); + actions[ACTION_NEW_PAGE]->setText(i18n("&New Page")); + actions[ACTION_NEW_BOOK] = new KAction(i18n("New &Book..."), "contents", CTRL + SHIFT + Key_N, this, + SLOT(createNewBook()), actionCollection(), "new_book"); + + exportPageMenu = new KActionMenu(i18n("Export Page"), actionCollection(), "save_page_to"); + actions[ACTION_PAGE2TEXT] = new KAction(i18n("To Text File..."), QString::null, 0, this, + SLOT(writePage()), actionCollection(), "save_page_to_ascii"); + actions[ACTION_PAGE2TEXT]->plug(exportPageMenu->popupMenu()); + actions[ACTION_PAGE2HTML] = new KAction(i18n("To HTML File..."), QString::null, 0, this, + SLOT(writePageToHTML()), actionCollection(), "save_page_to_html"); + actions[ACTION_PAGE2HTML]->plug(exportPageMenu->popupMenu()); + + exportBookMenu = new KActionMenu(i18n("Export Book"), actionCollection(), "save_book_to"); + actions[ACTION_BOOK2TEXT] = new KAction(i18n("To Text File..."), QString::null, 0, this, + SLOT(writeBook()), actionCollection(), "save_book_to_ascii"); + actions[ACTION_BOOK2TEXT]->plug(exportBookMenu->popupMenu()); + actions[ACTION_BOOK2HTML] = new KAction(i18n("To HTML File..."), QString::null, 0, this, + SLOT(writeBookToHTML()), actionCollection(), "save_book_to_html"); + actions[ACTION_BOOK2HTML]->plug(exportBookMenu->popupMenu()); + + actions[ACTION_DELETE_PAGE] = new KAction(i18n("&Delete Page"), "editdelete", CTRL + Key_Delete, this, + SLOT(deleteEntry()), actionCollection(), "del_page"); + actions[ACTION_DELETE_BOOK] = new KAction(i18n("Delete Boo&k"), "editdelete", CTRL + SHIFT + Key_Delete, this, + SLOT(deleteBook()), actionCollection(), "del_folder"); + + actions[ACTION_MANUAL_SAVE] = new KAction(i18n("Manual Save"), 0, KStdAccel::save(), + this, SLOT(autoSave()), actionCollection(), "manual_save"); + actions[ACTION_PRINT] = KStdAction::print(this, SLOT(slotPrint()), actionCollection()); + actions[ACTION_QUIT] = KStdAction::quit(this, SLOT(slotQuit()), actionCollection()); + + actions[ACTION_CUT] = KStdAction::cut(me_text, SLOT(cut()), actionCollection()); + connect(me_text, SIGNAL(copyAvailable(bool)), actions[ACTION_CUT], SLOT(setEnabled(bool))); + actions[ACTION_CUT]->setEnabled(false); + actions[ACTION_COPY] = KStdAction::copy(me_text, SLOT(copy()), actionCollection()); + connect(me_text, SIGNAL(copyAvailable(bool)), actions[ACTION_COPY], SLOT(setEnabled(bool))); + actions[ACTION_COPY]->setEnabled(false); + actions[ACTION_PASTE2TITLE] = new KAction(i18n("Copy &into Page Title"), "editcopy", CTRL+Key_T, this, + SLOT(copySelection()), actionCollection(), "copyIntoTitle"); + connect(me_text, SIGNAL(copyAvailable(bool)), actions[ACTION_PASTE2TITLE], SLOT(setEnabled(bool))); + actions[ACTION_PASTE2TITLE]->setEnabled(false); + actions[ACTION_PASTE] = KStdAction::pasteText(me_text, SLOT(paste()), actionCollection()); + + actions[ACTION_FIND] = KStdAction::find( this, SLOT( slotSearch() ), actionCollection() ); + actions[ACTION_FIND_NEXT] = KStdAction::findNext( this, SLOT( slotRepeatSearch() ), actionCollection() ); + actions[ACTION_FIND_NEXT]->setEnabled(false); + actions[ACTION_REPLACE] = KStdAction::replace( this, SLOT( slotReplace() ), actionCollection() ); + + actions[ACTION_RENAME] = new KAction(i18n("Rename..."), QString::null, CTRL + Key_M, this, + SLOT(slotRenameEntry()), actionCollection(), "rename_entry"); + actions[ACTION_INSERT_DATE] = new KAction(i18n("Insert Date"), "date", CTRL + Key_I, this, + SLOT(insertDate()), actionCollection(), "insert_date"); + + KStdAction::preferences(this, SLOT(configure()), actionCollection()); + + bookmarkMenu = new KActionMenu(i18n("&Bookmarks"), "bookmarks", actionCollection(), "bookmarks"); + KJotsBookmarks* bookmarks = new KJotsBookmarks(this); + connect(bookmarks, SIGNAL(openPage(const QString&)), SLOT(jumpToBookmark(const QString&))); + new KBookmarkMenu(KBookmarkManager::managerForFile(locateLocal("appdata","bookmarks.xml")), + bookmarks, bookmarkMenu->popupMenu(), + actionCollection(), true); + setupGUI(); + /* + * TODO: add a bookmark bar, something like this + KToolBar* bar = dynamic_cast(child("bookmarkToolBar", "KToolBar")); + new KBookmarkBar(KBookmarkManager::managerForFile(locateLocal("appdata","bookmarks.xml")), + bookmarks, bar, actionCollection(), this, "BookmarkBar"); + if (bar->count() == 0) + { + bar->hide(); + } + */ + + m_autosaveTimer = new QTimer(this, "autosave_timer"); + + // + // Set startup size. + // + if (!KJotsSettings::splitterSizes().isEmpty()) + { + splitter->setSizes(KJotsSettings::splitterSizes()); + } + + // + // Now load the books + // + loadBooks(); + + updateConfiguration(); + updateMenu(); + + QTimer::singleShot(0, this, SLOT(slotSetupInterface())); + + //connect new slots + connect(subjectList, SIGNAL(selectionChanged(QListViewItem*)), + this, SLOT(jumpToEntry(QListViewItem*))); + connect(subjectList, SIGNAL(moved(QListViewItem*, QListViewItem*, QListViewItem*)), + this, SLOT(slotItemMoved(QListViewItem*, QListViewItem*, QListViewItem*))); + connect(subjectList, SIGNAL(expanded(QListViewItem*)), + this, SLOT(slotExpandBook(QListViewItem*))); + connect(subjectList, SIGNAL(collapsed(QListViewItem*)), + this, SLOT(slotCollapseBook(QListViewItem*))); + connect(subjectList, SIGNAL(contextMenu(KListView*,QListViewItem*,const QPoint&)), + this, SLOT(showListviewContextMenu(KListView*,QListViewItem*,const QPoint&))); + connect(subjectList, SIGNAL(itemRenamed(QListViewItem*,const QString&,int)), + this, SLOT(slotItemRenamed(QListViewItem*,const QString&,int))); + connect(roTextView, SIGNAL(urlClick(const QString&)), + this, SLOT(linkClicked(const QString&))); + connect(m_autosaveTimer, SIGNAL(timeout()), + this, SLOT(autoSave())); +} + +void KJotsMain::slotSetupInterface() +{ + if (subjectList->childCount() == 0) + { + if ( !createNewBook() ) + { + roTextView->clear(); + textStack->raiseWidget(roTextView); + } + } +} + +/*! + \brief Loads all the books it can find in the appdata directory. + Needless to say: this should only ever be called once. +*/ +void KJotsMain::loadBooks() +{ + QDir dir(locateLocal("appdata","")); + QStringList files = dir.entryList(QDir::Files|QDir::Readable); + Q_UINT64 currentSelection = KJotsSettings::currentSelection(); + + //TODO: Eventually we can make use of the ".book" extension here, but for + //right now (2005/06/04) there's just too much legacy data out there. + + for (QStringList::Iterator it = files.begin(); it != files.end(); it++) + { + QString filepath = dir.absFilePath(*it); + + if (!KJotsBook::isBookFile(filepath) ) + { + continue; + } + + KJotsBook* book = new KJotsBook(subjectList, 0); + book->openBook(filepath); + } + + QListViewItemIterator it( subjectList ); + while ( it.current() ) { + KJotsEntryBase *entry = dynamic_cast(it.current()); + if ( entry && entry->id() == currentSelection ) + { + subjectList->ensureItemVisible(entry); + subjectList->setSelected(entry, true); + jumpToEntry(entry); + break; + } + ++it; + } + + return; +} + +bool KJotsMain::createNewBook() +{ + bool ok; + + QString name = KInputDialog::getText( i18n( "New Book" ), + i18n( "Book name:" ), QString::null, &ok, this ); + + if (!ok) + return false; + + KJotsBook* book = new KJotsBook(subjectList, 0); + book->setSubject(name); + book->openBook(""); + book->setOpen(true); + subjectList->setSelected(book->firstChild(), true); + return true; +} + +void KJotsMain::slotRenameEntry() +{ + KJotsEntryBase* entry = dynamic_cast(subjectList->currentItem()); + + if (entry) + { + entry->rename(); + jumpToEntry(entry, true); //reflect the changes on screen + } +} + +void KJotsMain::deleteBook() +{ + KJotsBook* b = currentBook(); + + if (!b) + return; + + QString msg = i18n("Are you sure you want to delete the %1 book?"); + int result = KMessageBox::warningContinueCancel(topLevelWidget(), msg.arg(b->subject()), i18n("Delete Book"),KStdGuiItem::del()); + + if (result!=KMessageBox::Continue) + return; + + KJotsBook* nxt=dynamic_cast(b->nextSibling()); + + b->deleteBook(); + currentEntry = 0L; + delete b; + + if (!nxt) + nxt=dynamic_cast(subjectList->firstChild()); + + if (nxt) + { + subjectList->setSelected(nxt, true); + } + else + { + roTextView->clear(); + textStack->raiseWidget(roTextView); + updateMenu(); + } +} + +void KJotsMain::newEntry() +{ + KJotsBook* b = currentBook(); + + if (b) + { + KJotsPage* s = b->addPage(); + subjectList->setSelected(s, true); + } +} + +void KJotsMain::deleteEntry() +{ + KJotsPage* cur = currentPage(); + + if (!cur || + KMessageBox::warningContinueCancel(topLevelWidget(), + i18n("Are you sure you want to delete the %1 page?") + .arg(cur->subject()), + i18n("Delete Page"),KStdGuiItem::del()) != KMessageBox::Continue) + { + return; + } + + KJotsBook* bk = cur->parentBook(); + KJotsPage* nxt = dynamic_cast(cur->nextSibling()); + + me_text->setEntry(0); + delete cur; + currentEntry = 0; + + if (!nxt) + nxt = dynamic_cast(bk->firstChild()); + + if (nxt) + { + subjectList->setSelected(nxt, true); + } else { + subjectList->setSelected(bk, true); + } + + updateMenu(); +} + +void KJotsMain::configure() +{ + if(KConfigDialog::showDialog("settings")) + return; + + KConfigDialog* dialog = new KConfigDialog(this, "settings", KJotsSettings::self()); + + confPageFont* cpFont = new confPageFont(0, "Font"); + dialog->addPage(cpFont, i18n("Font"), "fonts"); + + confPageMisc* cpMisc = new confPageMisc(0, "Autosave"); + dialog->addPage(cpMisc, i18n("Autosave"), "misc"); + + connect(dialog, SIGNAL(settingsChanged()), this, SLOT(updateConfiguration())); + + dialog->show(); +} + +void KJotsMain::slotSearch() +{ + me_text->search(); +} + +void KJotsMain::slotRepeatSearch() +{ + me_text->repeatSearch(); +} + +void KJotsMain::slotReplace() +{ + me_text->replace(); +} + +void KJotsMain::updateConfiguration() +{ + static int encoding = -1; + + //Keep track of the encoding setting. If the user changes it, we + //need to mark all books dirty so they are saved correctly. + if ( encoding == -1 ) { + encoding = KJotsSettings::unicode(); + } else { + if ( (int)encoding != KJotsSettings::unicode() ) { + KJotsBook *book = dynamic_cast(subjectList->firstChild()); + while (book) { + book->setDirty(true); + book = dynamic_cast(book->nextSibling()); + } + + encoding = (int)KJotsSettings::unicode(); + } + } + + me_text->setFont(KJotsSettings::font()); + if (KJotsSettings::autoSave()) + m_autosaveTimer->changeInterval(KJotsSettings::autoSaveInterval()*1000*60); + else + m_autosaveTimer->stop(); +} + +/*! + \brief Saves any books that need saving. +*/ +void KJotsMain::autoSave() +{ + KJotsBook *book = dynamic_cast(subjectList->firstChild()); + while (book) + { + if ( book->isDirty() ) + { + book->saveBook(); + } + + book = dynamic_cast(book->nextSibling()); + } +} + +void KJotsMain::writeBook() +{ + saveBookToFile(true); +} + +void KJotsMain::writeBookToHTML() +{ + saveBookToFile(false); +} + +void KJotsMain::saveBookToFile(bool plainText) +{ + KJotsBook* b = currentBook(); + + if (!b) + return; + + bool tryAgain = true; + KEncodingFileDialog::Result res; + while (tryAgain) + { + + res = KEncodingFileDialog::getSaveURLAndEncoding(); + + if (res.URLs[0].isEmpty()) + { + tryAgain = false; + } + + if (!KIO::NetAccess::exists(res.URLs[0], true, this) || + KMessageBox::warningYesNo(this, "" + i18n("The file %1 already exists. Do you wish to overwrite it?").arg(res.URLs[0].prettyURL()) + "", i18n("File Exists"), i18n("Overwrite"), KStdGuiItem::cancel()) == KMessageBox::Yes) + { + tryAgain = false; + } + } + + if (!res.URLs[0].isEmpty()) + { + b->saveToFile(res.URLs[0], plainText, res.encoding); + } +} + +void KJotsMain::writePage() +{ + savePageToFile(true); +} + +void KJotsMain::writePageToHTML() +{ + savePageToFile(false); +} + +void KJotsMain::savePageToFile(bool plainText) +{ + KJotsPage* e = currentPage(); + + if (!e) + return; + + bool tryAgain = true; + KEncodingFileDialog::Result res; + while (tryAgain) + { + res = KEncodingFileDialog::getSaveURLAndEncoding(); + + if (res.URLs[0].isEmpty()) + { + tryAgain = false; + } + + if (!KIO::NetAccess::exists(res.URLs[0], true, this) || + KMessageBox::warningYesNo(this, "" + i18n("The file %1 already exists. Do you wish to overwrite it?").arg(res.URLs[0].prettyURL()) + "", i18n("File Exists"), i18n("Overwrite"), KStdGuiItem::cancel()) == KMessageBox::Yes) + { + tryAgain = false; + } + } + + if (!res.URLs[0].isEmpty()) + { + e->saveToFile(res.URLs[0], plainText, res.encoding); + } +} + +void KJotsMain::copySelection() +{ + //TODO: Strip HTML tags + KJotsPage* cur = currentPage(); + + if (cur && me_text->hasSelectedText()) + cur->setSubject(me_text->selectedText()); +} + +void KJotsMain::slotPrint() +{ + autoSave(); + KJotsEntryBase* entry = dynamic_cast(subjectList->currentItem()); + + if (entry) + { + entry->print(m_font); + } +} + +void KJotsMain::slotQuit() +{ + close(); +} + +void KJotsMain::insertDate() +{ + me_text->insert(KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(), true) + " "); +} + +void KJotsMain::updateMenu() +{ + KJotsEntryBase* cur = dynamic_cast(subjectList->currentItem()); + + if (!cur) + { + // no (meaningful?) selection + actions[ACTION_DELETE_BOOK]->setEnabled(false); + actions[ACTION_DELETE_PAGE]->setEnabled(false); + actions[ACTION_NEW_PAGE]->setEnabled(false); + actions[ACTION_PRINT]->setEnabled(false); + actions[ACTION_CUT]->setEnabled(false); + actions[ACTION_PASTE]->setEnabled(false); + actions[ACTION_FIND]->setEnabled(false); + actions[ACTION_REPLACE]->setEnabled(false); + actions[ACTION_BOOK2TEXT]->setEnabled(false); + actions[ACTION_BOOK2HTML]->setEnabled(false); + actions[ACTION_PAGE2TEXT]->setEnabled(false); + actions[ACTION_PAGE2HTML]->setEnabled(false); + actions[ACTION_RENAME]->setEnabled(false); + actions[ACTION_INSERT_DATE]->setEnabled(false); + actions[ACTION_NEXT_BOOK]->setEnabled(false); + actions[ACTION_PREV_BOOK]->setEnabled(false); + actions[ACTION_NEXT_PAGE]->setEnabled(false); + actions[ACTION_PREV_PAGE]->setEnabled(false); + actions[ACTION_MANUAL_SAVE]->setEnabled(false); + bookmarkMenu->setEnabled(false); + exportPageMenu->setEnabled(false); + exportBookMenu->setEnabled(false); + } + else + { + actions[ACTION_DELETE_BOOK]->setEnabled(true); + actions[ACTION_NEW_PAGE]->setEnabled(true); + actions[ACTION_PRINT]->setEnabled(true); + actions[ACTION_FIND]->setEnabled(true); + actions[ACTION_BOOK2TEXT]->setEnabled(true); + actions[ACTION_BOOK2HTML]->setEnabled(true); + actions[ACTION_RENAME]->setEnabled(true); + actions[ACTION_MANUAL_SAVE]->setEnabled(true); + bookmarkMenu->setEnabled(true); + exportBookMenu->setEnabled(true); + + //TODO: Only activate if there is a next/prev book/page. + actions[ACTION_NEXT_BOOK]->setEnabled(true); + actions[ACTION_PREV_BOOK]->setEnabled(true); + actions[ACTION_NEXT_PAGE]->setEnabled(true); + actions[ACTION_PREV_PAGE]->setEnabled(true); + + if ( cur->isBook() ) + { + actions[ACTION_CUT]->setEnabled(false); + actions[ACTION_PASTE]->setEnabled(false); + actions[ACTION_REPLACE]->setEnabled(false); + actions[ACTION_DELETE_PAGE]->setEnabled(false); + actions[ACTION_PAGE2TEXT]->setEnabled(false); + actions[ACTION_PAGE2HTML]->setEnabled(false); + actions[ACTION_INSERT_DATE]->setEnabled(false); + exportPageMenu->setEnabled(false); + } + else + { + actions[ACTION_PASTE]->setEnabled(true); + actions[ACTION_REPLACE]->setEnabled(true); + actions[ACTION_DELETE_PAGE]->setEnabled(true); + actions[ACTION_PAGE2TEXT]->setEnabled(true); + actions[ACTION_PAGE2HTML]->setEnabled(true); + actions[ACTION_INSERT_DATE]->setEnabled(true); + exportPageMenu->setEnabled(true); + } + } +} + +void KJotsMain::slotFindSuccessful() +{ + actions[ACTION_FIND_NEXT]->setEnabled(true); +} + +void KJotsMain::showListviewContextMenu(KListView*, QListViewItem* i, const QPoint& p) +{ + if ( invalidMoveFlag ) return; //Prevent race condition + KActionMenu* am = new KActionMenu(this); + + if (!i) + { + // clicked on empty space + am->insert(actions[ACTION_NEW_BOOK]); + } + else if (dynamic_cast(i)) + { + // clicked on book + am->insert(actions[ACTION_NEW_PAGE]); + am->insert(actions[ACTION_RENAME]); + am->insert(exportBookMenu); + am->insert(new KActionSeparator(am)); + am->insert(actions[ACTION_DELETE_BOOK]); + } + else + { + //clicked on page + am->insert(actions[ACTION_NEW_PAGE]); + am->insert(actions[ACTION_RENAME]); + am->insert(exportPageMenu); + am->insert(new KActionSeparator(am)); + am->insert(actions[ACTION_DELETE_PAGE]); + } + + am->popup(p); +} + +/*! + \brief Handle link clicks in read-only HTML view + All URL clicks in the read-only window come here. For some reason + KTextBrowser doesn't handle anchor links itself, so we have to take + care of those, too. +*/ +void KJotsMain::linkClicked(const QString& link) +{ + if (link[0] == '#') + { + // internal link from TOC + roTextView->scrollToAnchor(link.mid(1)); + return; + } + + Q_UINT64 target = link.toULongLong(); + QListViewItemIterator it( subjectList ); + while ( it.current() ) { + KJotsEntryBase *entry = dynamic_cast(it.current()); + if ( entry && entry->id() == target ) + { + subjectList->ensureItemVisible(entry); + subjectList->setSelected(entry, true); + jumpToEntry(entry); + break; + } + ++it; + } + + return; +} + +bool KJotsMain::queryClose() +{ + autoSave(); + saveProperties(); + return true; +} + +/*! + \brief Saves settings to the ini-like config file. + This function only needs to be called before program termination. +*/ +void KJotsMain::saveProperties() +{ + KJotsSettings::setSplitterSizes(splitter->sizes()); + + KJotsEntryBase* entry = dynamic_cast(subjectList->currentItem()); + KJotsSettings::setCurrentSelection( entry ? entry->id() : 0); + + KJotsSettings::writeConfig(); + return; +} + +/*! + \brief Called when a book is opened/expanded/whatever. +*/ +void KJotsMain::slotExpandBook(QListViewItem *item) +{ + KJotsEntryBase *entry = dynamic_cast(item); + if ( entry ) entry->setDirty(true); +} + +/*! + \brief Called when a book is closed/collapsed/whatever. +*/ +void KJotsMain::slotCollapseBook(QListViewItem *item) +{ + KJotsEntryBase *entry = dynamic_cast(item); + if ( entry ) entry->setDirty(true); +} + +/*! + Returns the name of the active book or page. +*/ +QString KJotsMain::currentBookmarkTitle() +{ + QString title; + QListViewItem *item = subjectList->currentItem(); + + while ( item ) + { + KJotsEntryBase *entry = dynamic_cast(item); + item = item->parent(); + + if ( item ) + { + title = ": " + entry->subject() + title; + } else { + title = entry->subject() + title; + } + } + + return title; +} + +/*! + Returns a bookmark that identifies the active book or page. +*/ +QString KJotsMain::currentBookmarkURL() +{ + QString url; + KJotsEntryBase *entry = dynamic_cast(subjectList->currentItem()); + + if ( entry ) + { + url.setNum( entry->id() ); + } + + return url; +} + +/*! + Accepts a bookmark from the bookmark manager and jumps to the given entry. + \param bookmark The bookmark. +*/ +void KJotsMain::jumpToBookmark(const QString& bookmark) +{ + Q_UINT64 id = bookmark.toULongLong(); + + if ( id ) + { + QListViewItemIterator it( subjectList ); + while ( it.current() ) { + KJotsEntryBase *entry = dynamic_cast(it.current()); + if ( entry && entry->id() == id ) + { + subjectList->ensureItemVisible(entry); + subjectList->setSelected(entry, true); + jumpToEntry(entry); + break; + } + ++it; + } + } else { + //This is an old bookmark. Warn, and then continue. This can all be removed at some point + //in the future. CREATION DATE: 2005/06/10 + + KMessageBox::information(this, + i18n("This bookmark is from an older version of KJots and is not fully supported. It may or may not work. You should delete and recreate this bookmark."), QString::null, "oldBookmarkWarning"); + + int slash = bookmark.findRev('/'); + + if (slash != -1) + { + QString bookName = bookmark.left(slash); + int pageNo = bookmark.mid(slash+1).toInt(); + int pageCount = 0; + + //First, find the book. It'll only be root-level. + KJotsEntryBase *entry = dynamic_cast(subjectList->firstChild()); + + while (entry) + { + if ( entry->subject() == bookName ) + { + break; + } + entry = dynamic_cast(entry->nextSibling()); + } + + if ( !entry ) return; + + if ( !pageNo ) + { + subjectList->setSelected(entry, true); + jumpToEntry(entry); + } else { + //Now, find the right page + entry = dynamic_cast(entry->firstChild()); + + while (entry) + { + KJotsPage *page = dynamic_cast(entry); + + if ( page ) + { + if ( ++pageCount == pageNo ) + { + static_cast(entry)->parent()->setOpen(true); + subjectList->ensureItemVisible(entry); + subjectList->setSelected(entry, true); + jumpToEntry(entry); + break; + } + } + + entry = dynamic_cast(entry->nextSibling()); + } + } + } + } +} + +/*! + \brief Moves to the next book after the current selection. +*/ +void KJotsMain::nextBook() +{ + QListViewItem *item = subjectList->currentItem(); + if ( !item ) return; //sanity check + + QListViewItemIterator it ( item ); + QListViewItemIterator start ( it ); + + do { + it++; + + //if we iterate off the list, start over again. + if ( !it.current() ) + { + it = QListViewItemIterator ( subjectList ); + } + + if ( it.current() == start.current() ) return; //Bail out if we loop. + } while ( !dynamic_cast(it.current())); + + subjectList->ensureItemVisible(it.current()); + subjectList->setSelected(it.current(), true); + + return; +} + +/*! + \brief Moves to the previous book before the current selection. +*/ +void KJotsMain::prevBook() +{ + //Don't get caught by parent book. + QListViewItem *startingPoint = subjectList->currentItem(); + if ( !startingPoint ) return; //sanity check + + if ( dynamic_cast(startingPoint) ) + startingPoint = startingPoint->parent(); + + QListViewItemIterator it ( startingPoint ); + do { + it--; + + //if we iterate off the list, start over again. + if ( !it.current() ) + { + it = QListViewItemIterator ( subjectList->lastItem() ); + } + + if ( it.current() == startingPoint ) return; //Bail out if we loop. + } while ( !dynamic_cast(it.current())); + + subjectList->ensureItemVisible(it.current()); + subjectList->setSelected(it.current(), true); + + return; +} + +/*! + \brief Moves to the next page after the current selection. +*/ +void KJotsMain::nextPage() +{ + QListViewItem *item = subjectList->currentItem(); + if ( !item ) return; //sanity check + + QListViewItemIterator it ( item ); + QListViewItemIterator start ( it ); + + do { + it++; + + //if we iterate off the list, start over again. + if ( !it.current() ) + { + it = QListViewItemIterator ( subjectList ); + } + + if ( it.current() == start.current() ) return; //Bail out if we loop. + } while ( !dynamic_cast(it.current())); + + subjectList->ensureItemVisible(it.current()); + subjectList->setSelected(it.current(), true); + + return; +} + +/*! + \brief Moves to the previous page before the current selection. +*/ +void KJotsMain::prevPage() +{ + QListViewItem *item = subjectList->currentItem(); + if ( !item ) return; //sanity check + + QListViewItemIterator it ( item ); + QListViewItemIterator start ( it ); + + do { + it--; + + //if we iterate off the list, start over again. + if ( !it.current() ) + { + it = QListViewItemIterator ( subjectList->lastItem() ); + } + + if ( it.current() == start.current() ) return; //Bail out if we loop. + } while ( !dynamic_cast(it.current())); + + subjectList->ensureItemVisible(it.current()); + subjectList->setSelected(it.current(), true); + + return; +} + +void KJotsMain::jumpToEntry(QListViewItem* entry, bool force) +{ + //This won't lose data or anything; but it does reset the cursor postion and waste cycles. + if (currentEntry == entry && !force) + return; + + if (entry == 0) + { + me_text->setEntry(0); + currentEntry = 0; + } + else if (dynamic_cast(entry)) + { + me_text->setEntry(0); //clear any old data + + KJotsBook* book = static_cast(entry); + QString html = book->generateHtml(book, false); + + roTextView->setText(html); + roTextView->setCursorPosition(0, 0); + textStack->raiseWidget(roTextView); + currentEntry = 0; + } + else + { + textStack->raiseWidget(me_text); + me_text->setEntry(dynamic_cast(entry)); + currentEntry = static_cast(entry); + } + + updateCaption(); + updateMenu(); +} + +/*! + Sets the window caption. +*/ +void KJotsMain::updateCaption() +{ + QString caption; + QListViewItem *item = subjectList->currentItem(); + + while ( item ) + { + KJotsEntryBase *entry = dynamic_cast(item); + item = item->parent(); + + if ( item ) + { + caption = " / " + entry->subject() + caption; + } else { + caption = entry->subject() + caption; + } + } + + setCaption(kapp->makeStdCaption(caption)); + return; +} + +void KJotsMain::slotItemRenamed(QListViewItem* item, const QString& str, int /*col*/) +{ + KJotsEntryBase* entry = dynamic_cast(item); + + if (entry) + { + entry->setSubject(str); + entry->setDirty(true); + updateCaption(); + jumpToEntry(entry, true); //reflect the changes on screen + } +} + +/*! + \brief Called when an item is moved via drag-and-drop. + \warning The whole drag-n-drop reordering system is completely booched. + Tread lightly and test well when modifying things here. +*/ +void KJotsMain::slotItemMoved(QListViewItem *item, QListViewItem* afterFirst, QListViewItem */*afterNow*/ ) +{ + KJotsEntryBase *entry = dynamic_cast(item); + + //afterFirst doesn't work like we need it to. We want it to point to the + //previous sibling, not just the entry directly above it. + if ( afterFirst && afterFirst->parent() != entry->parentBook() ) + { + QListViewItemIterator it ( afterFirst ); + afterFirst = 0; + + //Rewind backwards up the tree... + while ( it.current() ) + { + //No other items were above this one. + if ( it.current() == entry->parentBook() ) + { + break; + } + + //Found a previous sibling! + if ( it.current()->parent() == entry->parentBook() ) + { + afterFirst = it.current(); + break; + } + + --it; + } + } + + KJotsEntryBase *entryAfter = dynamic_cast(afterFirst); + + if ( entry->isPage() && !item->parent() ) + { + invalidMoveFlag=true; //Don't do anything while we're stuck here. + subjectList->setItemsMovable(false); + subjectList->setItemsRenameable(false); + + // We don't accept pages in the root. Create a new book? + if (KMessageBox::questionYesNo(this, + i18n("All pages must be inside a book. " + "Would you like to create a new book to put the page in, " + "or would you prefer to not move the page at all?"), + QString::null, + i18n("Create New Book"), i18n("Do Not Move Page")) == + KMessageBox::No || + !createNewBook()) + { + //We have to move item back. + subjectList->takeItem(item); + entry->parentBook()->insertItem(item); + entry->moveItem(afterFirst); + } else { + subjectList->takeItem(item); + delete currentBook()->firstChild(); + currentBook()->insertItem(item); + subjectList->ensureItemVisible(item); + subjectList->setSelected(item, true); + } + + invalidMoveFlag=false; + subjectList->setItemsMovable(true); + subjectList->setItemsRenameable(true); + } + + if ( entry ) + { + entry->resetParent(); + entry->setDirty(true); + } + + if ( entryAfter ) + { + //Set the old parent book to dirty, since it just lost a page. + if ( entryAfter->isBook() ) + entryAfter->setDirty(true); + else + entryAfter->parentBook()->setDirty(true); + } + + return; +} + +/*! + Returns a pointer to the currently selected book, or the book that owns + the currently selected page. +*/ +KJotsBook* KJotsMain::currentBook() +{ + KJotsEntryBase* e = dynamic_cast(subjectList->currentItem()); + + while (e) + { + if (dynamic_cast(e)) + { + return dynamic_cast(e); + } + e = dynamic_cast(e->KListViewItem::parent()); + } + + return 0; +} + +/*! + Returns the currently selected page or 0 if no page is selected. +*/ +KJotsPage* KJotsMain::currentPage() +{ + return dynamic_cast(subjectList->currentItem()); +} + +void addBookmark() +{ +} + +void editBookmarks() +{ +} + +#include "KJotsMain.moc" +/* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/kjots/KJotsMain.h b/kjots/KJotsMain.h new file mode 100644 index 0000000..28ec089 --- /dev/null +++ b/kjots/KJotsMain.h @@ -0,0 +1,165 @@ +// +// kjots +// +// Copyright (C) 1997 Christoph Neerfeld +// Copyright (C) 2002-2004 Aaron J. Seigo +// Copyright (C) 2003 Stanislav Kljuhhin +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef KJotsMain_included +#define KJotsMain_included + +#include +#include + +#include +#include + +class QGroupBox; +class QWidgetStack; +class KTextBrowser; +class KAccel; +class KJotsMain; +class KToolBar; +class KListBox; +class KListView; +class KPopupMenu; +class ConfigureDialog; +class KEdFind; +class KEdReplace; +class QTimer; +class KAction; +class KActionMenu; + +class KJotsPage; +class KJotsBook; +class KJotsEntryBase; +class KJotsEdit; + +// +// KJotsMain +// +#define ACTION_NEXT_BOOK 0 +#define ACTION_PREV_BOOK 1 +#define ACTION_NEXT_PAGE 2 +#define ACTION_PREV_PAGE 3 +#define ACTION_NEW_PAGE 4 +#define ACTION_NEW_BOOK 5 +#define ACTION_PAGE2TEXT 6 +#define ACTION_PAGE2HTML 7 +#define ACTION_BOOK2TEXT 8 +#define ACTION_BOOK2HTML 9 +#define ACTION_DELETE_PAGE 10 +#define ACTION_DELETE_BOOK 11 +#define ACTION_MANUAL_SAVE 12 +#define ACTION_PRINT 13 +#define ACTION_QUIT 14 +#define ACTION_CUT 15 +#define ACTION_COPY 16 +#define ACTION_PASTE2TITLE 17 +#define ACTION_PASTE 18 +#define ACTION_FIND 19 +#define ACTION_FIND_NEXT 20 +#define ACTION_REPLACE 21 +#define ACTION_RENAME 22 +#define ACTION_INSERT_DATE 23 +#define ACTION_MAX 24 + +class KJotsMain : public KMainWindow +{ + Q_OBJECT + + public: + KJotsMain( const char* name = 0 ); + + QString currentBookmarkTitle(); + QString currentBookmarkURL(); + + public: + void updateCaption(); + + protected slots: + void slotSetupInterface(); + bool createNewBook(); + void deleteBook(); + void newEntry(); + void deleteEntry(); + void slotRenameEntry(); + void configure(); + void updateConfiguration(); + + void copySelection(); + void insertDate(); + void slotPrint(); + void slotSearch(); + void slotRepeatSearch(); + void slotReplace(); + void slotQuit(); + void slotFindSuccessful(); + + void jumpToEntry(QListViewItem* entry, bool=false); + + void slotExpandBook(QListViewItem* item); + void slotCollapseBook(QListViewItem* item); + void slotItemRenamed(QListViewItem*,const QString&,int); + void slotItemMoved(QListViewItem*,QListViewItem*,QListViewItem*); + void writeBook(); + void writeBookToHTML(); + void saveBookToFile(bool plainText); + void writePage(); + void writePageToHTML(); + void savePageToFile(bool plainText); + + void nextBook(); + void prevBook(); + void nextPage(); + void prevPage(); + + // handling page changes in the listview + void showListviewContextMenu(KListView* l, QListViewItem* i, const QPoint& p); + void linkClicked(const QString&); + void autoSave(void); + + // bookmarks + void jumpToBookmark(const QString& page); + + protected: + void saveProperties(); + bool queryClose(); + void updateMenu(); + void loadBooks(); + KJotsBook* currentBook(); + KJotsPage* currentPage(); + + QHBoxLayout *bg_top_layout; + QButtonGroup *bg_top; + KJotsEdit *me_text; + KTextBrowser *roTextView; + KListView *subjectList; + KJotsEntryBase *currentEntry; + QSplitter *splitter; + QWidgetStack *textStack; + QFont m_font; + QTimer* m_autosaveTimer; + bool invalidMoveFlag; //!< Used to fix a race condition. See Bug #109299 + + KAction* actions[ACTION_MAX]; + KActionMenu *exportPageMenu, *exportBookMenu, *bookmarkMenu; +}; + +#endif // KJotsMain_included +/* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/kjots/KJotsSettings.kcfgc b/kjots/KJotsSettings.kcfgc new file mode 100644 index 0000000..44b75cc --- /dev/null +++ b/kjots/KJotsSettings.kcfgc @@ -0,0 +1,8 @@ +# Code generation options for kconfig_compiler +File=kjots.kcfg +ClassName=KJotsSettings +Singleton=true +Mutators=Width,Height,SplitterSizes,CurrentSelection,OpenBooks,LastId +# Inherits=KConfigSkeleton +# IncludeFiles=libkdepim/kpimprefs.h +# MemberVariables=public diff --git a/kjots/Kjots.desktop b/kjots/Kjots.desktop new file mode 100644 index 0000000..b0550e0 --- /dev/null +++ b/kjots/Kjots.desktop @@ -0,0 +1,80 @@ +[Desktop Entry] +DocPath=kjots/index.html +Name=KJots +Name[af]=Kjots +Name[eo]=Notlibro +Name[hi]=के-जॉट्स +Name[hr]=Bilješke +Name[pt_BR]=Tomador de notas +Name[sv]=Kjots +Name[ta]= KJots +Name[th]=บันทึกช่วยจำ +Name[xh]=Amaxabiso amancinane e K +GenericName=Note Taker +GenericName[af]=Nota Afnemer +GenericName[ar]=برنامج لأخذ الملاحظات +GenericName[bg]=Бележки +GenericName[bs]=Uzimanje bilješki +GenericName[ca]=Anotador +GenericName[cs]=Poznámkový blok +GenericName[cy]=Cofnodydd +GenericName[da]=Notetager +GenericName[de]=Notizen machen +GenericName[el]=Καταγραφέας σημειώσεων +GenericName[eo]=Notolibro +GenericName[es]=Para tomar notas +GenericName[et]=Märkmete tegemine +GenericName[eu]=Ohar Hartzailea +GenericName[fa]=یادداشت بردار +GenericName[fi]=Muistilappuohjelma +GenericName[fr]=Prise de notes +GenericName[ga]=Eagarthóir Nótaí +GenericName[he]=כותב הערות +GenericName[hi]=नोट टेकर +GenericName[hr]=Program za pisanje bilježaka +GenericName[hu]=Jegyzetlapok +GenericName[is]=Minnispunktar +GenericName[it]=Blocco per appunti +GenericName[ja]=メモを取る +GenericName[kk]=Шағын дәптер +GenericName[km]=កម្មវិធី​កត់ចំណាំNote Taker +GenericName[lt]=Pastabų gavėjas +GenericName[lv]=Piezīmju Ņēmējs +GenericName[mk]=Прибележувач +GenericName[ms]=Pengambil Nota +GenericName[mt]=Ħu noti +GenericName[nb]=Beskjedverktøy +GenericName[nds]=Notizen maken +GenericName[ne]=टिपोट टेकर +GenericName[nl]=Notitieboekje +GenericName[nn]=Notatprogram +GenericName[pa]=ਨੋਟ ਲਵੋ +GenericName[pl]=Notatnik +GenericName[pt]=Bloco de Notas +GenericName[pt_BR]=Anotar pequenos apontamentos +GenericName[ro]=Notiţe +GenericName[ru]=Записная книжка +GenericName[sk]=Ukladanie poznámok +GenericName[sl]=Majhna beležnica +GenericName[sr]=Прибележивач +GenericName[sr@Latn]=Pribeleživač +GenericName[sv]=Elektroniska anteckningar +GenericName[ta]= குறிப்பு எடுப்பான் +GenericName[tg]=Китобчаи Навиштаҷот +GenericName[th]=บันทึกช่วยจำ +GenericName[tr]=Not alıcı +GenericName[uk]=Записна книжка +GenericName[ven]=Mudzhii wa dzinotsi +GenericName[wa]=Usteye po prinde des notes +GenericName[xh]=Umthathi Womakuqwalaselwe +GenericName[zh_CN]=笔记记录 +GenericName[zh_TW]=筆記簡記 +GenericName[zu]=Umthathi Wepheshana +Icon=kjots +Exec=kjots -caption "%c" %i %m +Type=Application +Path= +Terminal=false +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Utility;X-KDE-Utilities-PIM; diff --git a/kjots/Makefile.am b/kjots/Makefile.am new file mode 100644 index 0000000..32af728 --- /dev/null +++ b/kjots/Makefile.am @@ -0,0 +1,28 @@ +INCLUDES = $(all_includes) +AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) +LDADD = $(LIB_KFILE) $(LIB_KDEPRINT) + +bin_PROGRAMS = kjots + +kjots_SOURCES = main.cpp\ + KJotsMain.cpp\ + kjotsentry.cpp\ + kjotsedit.cpp\ + kjotsbookmarks.cpp\ + confpagefont.ui\ + confpagemisc.ui \ + KJotsSettings.kcfgc + +kjots_METASOURCES = AUTO + +SUBDIRS = icons + +xdg_apps_DATA = Kjots.desktop +kde_kcfg_DATA = kjots.kcfg + +rcdir = $(kde_datadir)/kjots +rc_DATA = kjotsui.rc + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kjots.pot + diff --git a/kjots/README b/kjots/README new file mode 100644 index 0000000..2ac51eb --- /dev/null +++ b/kjots/README @@ -0,0 +1,33 @@ +kjots - a note taker +------------------------------------ + +(C) 2002, 2003 Aaron J. Seigo + +(C) 1997 Christoph Neerfeld (Christoph.Neerfeld@home.ivm.de) +You may distribute kjots under the terms of the GNU General Public License. + +kjots is a small note taker program. Name and idea are taken from the jots +program included in the tkgoodstuff package. The tkgoodstuff package is +copyright (C) 1995-96 by Mark Crimmins (markcrim@umich.edu). + +Features: + - you may create several folders to store small text notes + +Bugs: + - see the BUGS doc or http://bugs.kde.org + +TODO for 3.2: + - preserve ordering of books between reloads + +TODO for post 3.2: + - statusbar with e.g. timestamp of last mod + - allow formatting of text in notes + - allow trees of pages + - page templates (TODO, diary, etc) + - encryption of pages + - syncing w/handhelds + +Install: + see INSTALL for details + +If you find bugs or have suggestions, send me an email diff --git a/kjots/confpagefont.ui b/kjots/confpagefont.ui new file mode 100644 index 0000000..e89e5b5 --- /dev/null +++ b/kjots/confpagefont.ui @@ -0,0 +1,38 @@ + +confPageFont + + + confPageFont + + + + 0 + 0 + 520 + 406 + + + + Font + + + + unnamed + + + 0 + + + + kcfg_Font + + + + + + + + + kfontdialog.h + + diff --git a/kjots/confpagemisc.ui b/kjots/confpagemisc.ui new file mode 100644 index 0000000..ef66e21 --- /dev/null +++ b/kjots/confpagemisc.ui @@ -0,0 +1,152 @@ + +confPageMisc + + + confPageMisc + + + + 0 + 0 + 289 + 123 + + + + Miscellaneous + + + + unnamed + + + 0 + + + + kcfg_AutoSaveInterval + + + minutes + + + 1 minute + + + 1440 + + + 1 + + + This is the number of minutes KJots will wait before automatically saving changes. + + + + + textLabel1 + + + S&ave every: + + + kcfg_AutoSaveInterval + + + This is the number of minutes KJots will wait before automatically saving changes. + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + spacer4 + + + Vertical + + + Expanding + + + + 20 + 30 + + + + + + spacer3 + + + Horizontal + + + Fixed + + + + 20 + 20 + + + + + + kcfg_AutoSave + + + &Save changes periodically + + + true + + + When "Enable autosave" is checked, KJots will automatically save changes made to books at the interval defined below. + + + + + kcfg_Unicode + + + Use Unico&de encoding + + + + + + + kcfg_AutoSave + toggled(bool) + kcfg_AutoSaveInterval + setEnabled(bool) + + + kcfg_AutoSave + toggled(bool) + textLabel1 + setEnabled(bool) + + + + + knuminput.h + + diff --git a/kjots/icons/Makefile.am b/kjots/icons/Makefile.am new file mode 100644 index 0000000..7345ca5 --- /dev/null +++ b/kjots/icons/Makefile.am @@ -0,0 +1,6 @@ + +pics_DATA = filedel.png +picsdir = $(kde_datadir)/kjots/pics + +KDE_ICON = kjots + diff --git a/kjots/icons/README b/kjots/icons/README new file mode 100644 index 0000000..3926e1e --- /dev/null +++ b/kjots/icons/README @@ -0,0 +1,24 @@ +The file jots.xpm is part of the tkgoodstuff package +copyright (C) 1995-96 by Mark Crimmins (markcrim@umich.edu) + +Here is the copyright notice of tkgoodstuff: +# tkgoodstuff by Mark Crimmins (markcrim@umich.edu) +# copyright (C) 1995-96, all rights reserved. +# Void where prohibited. Your mileage may vary. + +# Seriously, enjoy my handiwork, but don't sue me if it causes troubles. +# Also, the University of Michigan has NOTHING WHATEVER to do with this +# software. + +# This program (the tkgoodstuff 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 (version 2 of the License). This program is +# distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. For a copy of the GNU General Public +# License, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + diff --git a/kjots/icons/filedel.png b/kjots/icons/filedel.png new file mode 100644 index 0000000..6d0d29d Binary files /dev/null and b/kjots/icons/filedel.png differ diff --git a/kjots/icons/hi16-app-kjots.png b/kjots/icons/hi16-app-kjots.png new file mode 100644 index 0000000..5466e25 Binary files /dev/null and b/kjots/icons/hi16-app-kjots.png differ diff --git a/kjots/icons/hi22-app-kjots.png b/kjots/icons/hi22-app-kjots.png new file mode 100644 index 0000000..36ce904 Binary files /dev/null and b/kjots/icons/hi22-app-kjots.png differ diff --git a/kjots/icons/hi32-app-kjots.png b/kjots/icons/hi32-app-kjots.png new file mode 100644 index 0000000..b2b128d Binary files /dev/null and b/kjots/icons/hi32-app-kjots.png differ diff --git a/kjots/icons/hi48-app-kjots.png b/kjots/icons/hi48-app-kjots.png new file mode 100644 index 0000000..142af59 Binary files /dev/null and b/kjots/icons/hi48-app-kjots.png differ diff --git a/kjots/icons/hi64-app-kjots.png b/kjots/icons/hi64-app-kjots.png new file mode 100644 index 0000000..ec0f270 Binary files /dev/null and b/kjots/icons/hi64-app-kjots.png differ diff --git a/kjots/kjots.kcfg b/kjots/kjots.kcfg new file mode 100644 index 0000000..4350210 --- /dev/null +++ b/kjots/kjots.kcfg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + KGlobalSettings::generalFont() + + + + true + + + + false + + + + 5 + + + + 0 + + + diff --git a/kjots/kjotsbookmarks.cpp b/kjots/kjotsbookmarks.cpp new file mode 100644 index 0000000..b339a46 --- /dev/null +++ b/kjots/kjotsbookmarks.cpp @@ -0,0 +1,51 @@ +// +// kjotsbookmarks +// +// Copyright (C) 1997 Christoph Neerfeld +// Copyright (C) 2002, 2003 Aaron J. Seigo +// Copyright (C) 2003 Stanislav Kljuhhin +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "KJotsMain.h" +#include "kjotsbookmarks.h" + +KJotsBookmarks::KJotsBookmarks(KJotsMain* parent, const char* name) + : QObject(parent, name), + m_kjots(parent) +{ +} + +KJotsBookmarks::~KJotsBookmarks() +{ +} + +void KJotsBookmarks::openBookmarkURL(const QString& page) +{ + emit openPage(page); +} + +QString KJotsBookmarks::currentURL() const +{ + return m_kjots->currentBookmarkURL(); +} + +QString KJotsBookmarks::currentTitle() const +{ + return m_kjots->currentBookmarkTitle(); +} + +#include "kjotsbookmarks.moc" diff --git a/kjots/kjotsbookmarks.h b/kjots/kjotsbookmarks.h new file mode 100644 index 0000000..7cb3144 --- /dev/null +++ b/kjots/kjotsbookmarks.h @@ -0,0 +1,51 @@ +// +// kjotsbookmarks +// +// Copyright (C) 1997 Christoph Neerfeld +// Copyright (C) 2002, 2003 Aaron J. Seigo +// Copyright (C) 2003 Stanislav Kljuhhin +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef KJOTSBOOKMARKS +#define KJOTSBOOKMARKS + +#include + +class KJotsMain; + +class KJotsBookmarks : public QObject, public KBookmarkOwner +{ + Q_OBJECT + + public: + KJotsBookmarks(KJotsMain* parent = 0, const char* name = 0); + ~KJotsBookmarks(); + + virtual void openBookmarkURL(const QString& url); + virtual QString currentURL() const; + QString currentTitle() const; + + signals: + void openPage(const QString& page); + + private: + KJotsMain* m_kjots; +}; + + +#endif +/* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/kjots/kjotsedit.cpp b/kjots/kjotsedit.cpp new file mode 100644 index 0000000..0a61c62 --- /dev/null +++ b/kjots/kjotsedit.cpp @@ -0,0 +1,150 @@ +// +// kjots +// +// Copyright (C) 1997 Christoph Neerfeld +// Copyright (C) 2002, 2003 Aaron J. Seigo +// Copyright (C) 2003 Stanislav Kljuhhin +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "kjotsedit.h" +#include "kjotsentry.h" + +//---------------------------------------------------------------------- +// MYMULTIEDIT +//---------------------------------------------------------------------- +KJotsEdit::KJotsEdit (QWidget* parent, const char* name) + : KEdit(parent, name), + m_entry(0) +{ + // no rich text until printing and other such issues are worked out + setTextFormat(Qt::PlainText); + setWordWrap(QTextEdit::WidgetWidth); + setLinkUnderline(true); + web_menu = new KPopupMenu(this);; + web_menu->insertItem(i18n("Open URL"), this, SLOT(openUrl()) ); +} + +KJotsEdit::~KJotsEdit() +{ + +} + +void KJotsEdit::mousePressEvent( QMouseEvent *e ) +{ + if(e->button() == RightButton && + hasSelectedText()) + { + KURL url(selectedText()); + + if(url.isValid()) + { + web_menu->popup(QCursor::pos()); + return; + } + } + + KEdit::mousePressEvent(e); +} + +void KJotsEdit::openUrl() +{ + if (hasSelectedText()) + { + KURL url(selectedText()); + if(url.isValid()) + { + new KRun(url); + } + } +} + +void KJotsEdit::print(QString title) +{ + KPrinter printer; + printer.setDocName(title); + printer.setFullPage(false); + printer.setCreator("KJots"); + + if (printer.setup(this)) + { + QFont printFont = font(); + QPainter painter( &printer ); + QPaintDeviceMetrics metrics( &printer ); + int y = 0; + int maxWidth = metrics.width(); + int maxHeight = metrics.height(); + QString currentParagraph; + + for (int paragraphCount = 0; paragraphCount < paragraphs(); ++paragraphCount ) + { + currentParagraph = text(paragraphCount); + QRect r = painter.boundingRect(0, y, maxWidth, maxHeight, + QPainter::ExpandTabs | QPainter::WordBreak, + currentParagraph); + + if ((y + r.height()) > maxHeight) + { + printer.newPage(); + y = 0; + } + + painter.drawText(0, y, maxWidth, maxHeight - y, + QPainter::ExpandTabs | QPainter::WordBreak, + currentParagraph); + y += r.height(); + } + painter.end(); + } +} + +void KJotsEdit::setEntry (KJotsPage *entry) +{ + //tell the old entry to take a hike + if ( m_entry ) + { + m_entry->setEditor(0); + } + + //load up the new entry (assuming there is one) + if ( entry ) + { + m_entry = entry; + setText(entry->body()); + removeSelection(); + repaint(); + setEnabled(true); + setFocus(); + entry->setEditor(this); + } else { + clear(); + } + + m_entry = entry; +} + +#include "kjotsedit.moc" +/* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/kjots/kjotsedit.h b/kjots/kjotsedit.h new file mode 100644 index 0000000..cae025c --- /dev/null +++ b/kjots/kjotsedit.h @@ -0,0 +1,54 @@ +// +// kjots +// +// Copyright (C) 1997 Christoph Neerfeld +// Copyright (C) 2002, 2003 Aaron J. Seigo +// Copyright (C) 2003 Stanislav Kljuhhin +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef __KJOTSEDIT_H +#define __KJOTSEDIT_H + +#include +class KPopupMenu; +class KJotsPage; + +class KJotsEdit : public KEdit +{ + Q_OBJECT + public: + KJotsEdit (QWidget* parent=0, const char* name=0); + ~KJotsEdit (); + + void print(QString title = QString::null); + void setEntry(KJotsPage*); + + signals: + void findSuccessful(); + + protected slots: + void openUrl(); + + protected: + virtual void mousePressEvent (QMouseEvent *e); + + KPopupMenu *web_menu; + KJotsPage *m_entry; //!< The entry we are editing. It needs to be kept informed. +}; + +#endif // __KJOTSEDIT_H +/* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/kjots/kjotsentry.cpp b/kjots/kjotsentry.cpp new file mode 100644 index 0000000..a27b00e --- /dev/null +++ b/kjots/kjotsentry.cpp @@ -0,0 +1,1234 @@ +// +// kjots +// +// Copyright (C) 1997 Christoph Neerfeld +// Copyright (C) 2002, 2003 Aaron J. Seigo +// Copyright (C) 2003 Stanislav Kljuhhin +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "kjotsedit.h" +#include "KJotsMain.h" +#include "KJotsSettings.h" +#include "kjotsentry.h" + +// helper functions for HTML output +QString prepForHTML(QString text) +{ + text.replace("<", "<"); + text.replace(">", ">"); + text.replace("\n", "
"); + return text; +} + +QString htmlHeader(const QString& title, QTextCodec* codec) +{ + QString head = "" + prepForHTML(title) + ""; + return head; +} + +QString htmlFooter() +{ + return ""; +} + +// +// KJotsEntryBase +// + +KJotsEntryBase::KJotsEntryBase(KListView* parent, QListViewItem* after=0) + :KListViewItem(parent,after) +{ + m_id = 0; + m_saveInProgress = m_dirty = false; + m_parent = 0; +} + +KJotsEntryBase::KJotsEntryBase(KListViewItem* parent, QListViewItem* after=0) + :KListViewItem(parent,after) +{ + m_id = 0; + m_saveInProgress = m_dirty = false; + m_parent = dynamic_cast(parent); +} + +void KJotsEntryBase::setSubject(const QString& subj) +{ + setText(0, subj); +} + +void KJotsEntryBase::setText(int column, const QString& text) +{ + if (column == 0 && text.isEmpty()) + KListViewItem::setText(0, defaultSubject()); + else + KListViewItem::setText(column, text); +} + +/*! + \brief Sets a new parent. + This is mostly just used during drag-and-drop reordering in the list view. + We need to keep track of the previous parent in case the move is invalid. +*/ +void KJotsEntryBase::resetParent() +{ + m_parent = dynamic_cast(QListViewItem::parent()); +} + +/*! +* \brief Set the ID number. +* \param id The ID to set, or 0 to pick a fresh one. +* +* Set ourselves to a particular ID number, or pick a new one. The lastId used is +* stored in the settings. Now in theory it will eventually wrap, and may collide +* with preexisting IDs. Seeing as how we are using an unsigned long long, I am +* comfortable with the amount of time we have to worry about this. +*/ +void KJotsEntryBase::setId(Q_UINT64 id) +{ + //Find an unused id... + if ( id == 0 ) + { + Q_UINT64 lastId = KJotsSettings::lastId(); + + //TODO: In theory, we could wrap. The universe may end beforehand tho. + id = ++lastId; + if ( id == 0 ) id = ++lastId; //*IF* by some chance we do wrap, this will prevent bad things. + KJotsSettings::setLastId(id); + } + + m_id = id; + return; +} + +/*! + \brief Performs functions necessary to save the entry to a KJots file. + This function should ONLY be called when saving the file, as it performs + other functions than generating XML. +*/ +void KJotsEntryBase::generateXml( QDomDocument &doc, QDomElement &parent ) +{ + QDomElement title = doc.createElement( "Title" ); + title.appendChild( doc.createTextNode( subject() )); + parent.appendChild( title ); + + QDomElement id = doc.createElement( "ID" ); + QString id_string; + id_string.setNum(m_id); + id.appendChild( doc.createTextNode(id_string) ); + parent.appendChild( id ); + + setDirty( false ); + return; +} + +/*! + Parses through XML data for settings inherent to the base class. +*/ +void KJotsEntryBase::parseXml( QDomElement &e ) +{ + if ( !e.isNull() ) + { + if ( e.tagName() == "Title" ) + { + setSubject(e.text()); + } + else + if ( e.tagName() == "ID" ) + { + setId(e.text().toULongLong()); + } + } + + return; +} + +/*! + \brief Draws the Title box when printing. + This is a helper function for the derived classes. Code consolidation==the good. +*/ +int KJotsEntryBase::printTitleBox(QString title, KPrinter& printer, QPainter& painter, int y) +{ + QPaintDeviceMetrics metrics( &printer ); + int maxWidth = metrics.width(); + int maxHeight = metrics.height(); + + QRect r = painter.boundingRect(0, y, + maxWidth, maxHeight, + QPainter::ExpandTabs | QPainter::WordBreak | QPainter::AlignHCenter, + title); + y += 10; + + if ((y + r.height()) > maxHeight) + { + printer.newPage(); + y = 0; + } + else + { + r.moveBy(0, 10); + } + + r.setLeft(0); + r.setRight(maxWidth); + painter.drawRect(r); + painter.drawText(0, y, maxWidth, maxHeight - y, + QPainter::ExpandTabs | QPainter::WordBreak | QPainter::AlignHCenter, + title); + y += r.height() + 15; + + return y; +} + +// +// KJotsBook +// + +KJotsBook::KJotsBook(KListView* parent, QListViewItem* after) + : KJotsEntryBase(parent, after) +{ + init(); +} + +KJotsBook::KJotsBook(KListViewItem* parent, QListViewItem* after) + : KJotsEntryBase(parent, after) +{ + init(); +} + +KJotsBook::~KJotsBook() +{ +} + +/*! + \brief Initialize a KJotsBook object. + + This function is used for code consolidation. Otherwise, you'de have to change these + things in both constructors. +*/ +void KJotsBook::init() +{ + m_isBook = true; + m_open = false; + m_saveProgressDialog = 0; + setExpandable(true); + setPixmap(0, kapp->iconLoader()->loadIcon(QString("contents"),KIcon::Small)); +} + +/*! + \brief Is this a KJots file? + \param filename Filename to check. + + This function does a cursory check to see if this looks like it is a KJots file. + It's a little too quick and dirty for my taste, but seems to work OK. +*/ +bool KJotsBook::isBookFile(const QString& filename) +{ + QFile folder(filename); + bool test = false; + + if ( folder.exists() ) + { + if ( folder.open(IO_ReadWrite) ) + { + QTextStream st(static_cast(&folder)); + st.setEncoding( KJotsSettings::unicode() ? QTextStream::UnicodeUTF8 : QTextStream::Locale ); + QString buf = st.readLine().stripWhiteSpace(); + + //Check for new-style book. Not very pretty, but it is faster than loading the DOM. + if (buf == "") + { + test=true; + } + else + //Check for old-style book. See KJotsBook::loadOldBook() + if (buf.left(9) == "\\NewEntry") + { + test=true; + } + + } + } + + return test; +} + +/*! + \brief Reads a book in from a disk file. + This function is only called for root-level books. +*/ +bool KJotsBook::openBook(const QString& filename) +{ + if ( !m_open ) //sanity check + { + listView()->setUpdatesEnabled(false); + m_fileName = filename; + + if ( m_fileName.isEmpty() ) //new books names are empty. + { + addPage(); + m_open = true; + } else { + QFile file(m_fileName); + + if ( file.exists() && file.open(IO_ReadWrite) ) //TODO: Implement read-only mode? + { + QTextStream st(static_cast(&file)); + st.setEncoding( KJotsSettings::unicode() ? QTextStream::UnicodeUTF8 : QTextStream::Locale ); + QString data = st.read(); + + QDomDocument doc( "KJots" ); + if ( doc.setContent( data ) ) + { + QDomElement docElem = doc.documentElement(); + + if ( docElem.tagName() == "KJots" ) + { + QDomNode n = docElem.firstChild(); + while( !n.isNull() ) + { + QDomElement e = n.toElement(); // try to convert the node to an element. + if( !e.isNull() && e.tagName() == "KJotsBook" ) + { + parseXml(e); + } + n = n.nextSibling(); + } + } + + } else { + //Woah. Something didn't work right. Maybe this is an old file? + file.reset(); + if ( loadOldBook(file) ) + { + QFileInfo fi( file ); + setSubject(fi.fileName()); + } + } + } + + if ( !childCount() ) //sanity check + { + //We should NOT be here. That must not have been a book file, or it is damaged. + //To make things happy-happy, we just create a blank page and continue. + //TODO: Add an information message? Make a translater work for something so unlikely? + addPage(); + } + + m_open = true; + + // Support legacy files. Can be removed at some point. CREATION DATE: 2005/06/04 + if ( !m_fileName.isEmpty() && !m_fileName.endsWith(".book") ) + { + //some old books have incorrect names. So we save a new copy, then kill the old file + m_fileName = QString::null; //trick ourselves into thinking we're a new book + saveBook(); + file.remove(); + } + } + + listView()->setUpdatesEnabled(true); + + // Support legacy files. Can be removed at some point. CREATION DATE: 2005/06/07 + if ( m_open && !id() ) + { + //This book (and its pages) need new IDs! + setId(0); + + KJotsPage *page = dynamic_cast(firstChild()); + while ( page ) + { + page->setId(0); //TODO: Make setId() a protected function if this legacy code is removed. + page = dynamic_cast(page->nextSibling()); + } + } + } + + return m_open; +} + +/*! + \brief Load an old-style book file. + + This is a function for files made from older KJots versions. It could probably be removed + at some point in the future. CREATION DATE: 2005/05/30 +*/ +bool KJotsBook::loadOldBook(QFile &file) +{ + QTextStream st(static_cast(&file)); + st.setEncoding( KJotsSettings::unicode() ? QTextStream::UnicodeUTF8 : QTextStream::Locale ); + QString buf = st.readLine(); + + if (buf.left(9) != "\\NewEntry") + { + addPage(); + return false; + } + + KJotsPage *entry = 0; + QString body; + + bool quit=false; + + while (1) + { + if (buf.left(9) == "\\NewEntry") + { + if (entry) + { + entry->setBody(body); + } + + body = QString::null; + QString title = buf.mid(10, buf.length()); + + // now catch the page id + buf = st.readLine(); + if (buf.left(3) == "\\ID") + { + buf = st.readLine(); + } + + entry = new KJotsPage(this, entry); + entry->setSubject(title); + } + + int pos = 0; + + while ((pos = buf.find('\\',pos)) != -1) + if (buf[++pos] == '\\') + buf.remove(pos, 1 ); + + body.append( buf + "\n"); + + if (quit) + break; + + buf = st.readLine(); + + quit = st.eof(); + } + + entry->setBody(body); + return true; +} + +/*! + \brief Saves this book and everything in it to the data directory. +*/ +void KJotsBook::saveBook(void) +{ + if (!m_open) //sanity check + return; + + // Are we a new book? + if ( m_fileName.isEmpty() ) + { + KTempFile temp(locateLocal("appdata",""), ".book", 0644); + m_fileName = temp.name(); + } + + QFile file(m_fileName); + if (file.open(IO_WriteOnly | IO_Truncate)) + { + QDomDocument doc("KJots"); + QDomElement root = doc.createElement( "KJots" ); + doc.appendChild( root ); + + this->generateXml( doc, root ); //recursive + + QTextStream st((QIODevice *) &file); + st.setEncoding( KJotsSettings::unicode() ? QTextStream::UnicodeUTF8 : QTextStream::Locale ); + st << doc.toString(); + + file.close(); + } + +} + +/*! + \brief Deletes a book by removing the data file. + This does not affect the list display, and can be called for reasons other than + choosing to delete an entry from the list. If you want the object to dissappear + from the list, then you have to delete it. +*/ +void KJotsBook::deleteBook() +{ + QFile::remove(m_fileName); + m_fileName = QString::null; +} + +void KJotsBook::rename() +{ + bool ok; + QString name = KInputDialog::getText(i18n( "Rename Book" ), + i18n( "Book name:" ), + subject(), &ok, listView()); + if (ok) + { + setSubject(name); + + KJotsMain* m = dynamic_cast(kapp->mainWidget()); + + if (m) + m->updateCaption(); + + setDirty(true); + } +} + +/*! + \brief Initiated when the user chooses to save this to a file. + This function gets everything ready to go to save to the disk. +*/ +void KJotsBook::saveToFile(KURL url, bool plainText, const QString& encoding) +{ + if (url.isEmpty() || m_saveInProgress) + return; + + m_saveToPlainText = plainText; + m_saveEncoding = QTextCodec::codecForName(encoding.ascii()); + KIO::TransferJob* job = KIO::put(url, -1, true, false, false); + + if (!job) + { + return; + } + + //NOTE: The current implementation does not need the progress dialog, but further + //revisions will likely use it. I don't want to make the translators add, remove, + //and re-add translations, so I'm just keeping this here for now. + m_saveProgressDialog = new KProgressDialog(listView(), "bookSaveInProgress", + i18n("Saving %1").arg(subject()), + i18n("Saving the contents of %1 to %2") + .arg(subject(), url.prettyURL()), + true); + + m_saveProgressDialog->progressBar()->setTotalSteps(1); + m_saveProgressDialog->showCancelButton(false); + m_saveProgressDialog->setAutoClose(true); + + connect(job, SIGNAL(dataReq(KIO::Job*, QByteArray&)), SLOT(saveDataReq(KIO::Job*, QByteArray&))); + connect(job, SIGNAL(result( KIO::Job *)), SLOT(slotSaveResult( KIO::Job *))); + + m_saveInProgress = true; +} + +/*! + \brief Pumps out data when saving to a file. + This function pumps out page data during a disk save. +*/ +void KJotsBook::saveDataReq(KIO::Job* /* job */, QByteArray& data) +{ + if (!m_saveInProgress) return; //sanity check + + QTextStream stream(data, IO_WriteOnly); + stream.setCodec(m_saveEncoding); + + if (!m_saveToPlainText) + { + stream << htmlHeader(subject(), m_saveEncoding); + stream << generateHtml(this, true); + stream << htmlFooter(); + } else { + stream << generateText(); + } + + m_saveInProgress = false; +} + +/*! + \brief Completes a disk save. + This function is called after a disk save. The disk save may or may + not have completed normally. +*/ +void KJotsBook::slotSaveResult(KIO::Job *) +{ + m_saveInProgress = false; + delete m_saveProgressDialog; + m_saveProgressDialog = 0; + /* if (job->error() != 0) {} */ +} + +/*! + \brief Add a new page to the end of this book. +*/ +KJotsPage* KJotsBook::addPage() +{ + QListViewItem *after = 0; + + // append new pages + QListViewItem* tmp = firstChild(); + while (tmp) + { + after = tmp; + tmp = tmp->nextSibling(); + } + + KJotsPage *page = new KJotsPage(this, after); + page->initNewPage(); + return page; +} + +/*! + \brief Called when the user wants to print the book. +*/ +void KJotsBook::print(QFont& defaultFont) +{ + KPrinter printer; + printer.setDocName(subject()); + printer.setFullPage(false); + printer.setCreator("KJots"); + + if (!printer.setup(listView(), i18n("Print: %1").arg(subject()))) + { + return; + } + + QPainter painter(&printer); + painter.setFont(defaultFont); + print(printer, painter, 0); + + painter.end(); +} + +/*! + \brief Prints this book. +*/ +int KJotsBook::print(KPrinter& printer, QPainter& painter, int y) +{ + y = printTitleBox(subject(), printer, painter, y); + + KJotsEntryBase* entry = dynamic_cast(firstChild()); + while (entry) + { + y = entry->print(printer, painter, y); + entry = dynamic_cast(entry->nextSibling()); + } + + return y; +} + +QString KJotsBook::defaultSubject() +{ + return i18n("Untitled Book"); +} + +/*! + \brief Does this book need to be saved? + This function recursively checks itself, and all books and pages it owns to + see if any changes have been made. +*/ +bool KJotsBook::isDirty() +{ + //Am I dirty? + if ( KJotsEntryBase::isDirty() ) return true; + + //Check all children to see if any of them are dirty + KJotsEntryBase *entry = dynamic_cast(firstChild()); + while ( entry ) + { + if ( entry->isDirty() ) return true; + entry = dynamic_cast(entry->nextSibling()); + } + + return false; +} + +/*! + \brief Creates XML code and performs necessary tasks to save file. + This function should ONLY be called when saving the file. +*/ +void KJotsBook::generateXml( QDomDocument &doc, QDomElement &parent ) +{ + QDomElement book = doc.createElement( "KJotsBook" ); + parent.appendChild( book ); + + KJotsEntryBase::generateXml(doc, book); //let the base class save important stuff + + QDomElement open = doc.createElement( "Open" ); + open.appendChild( this->isOpen() ? doc.createTextNode("1") : doc.createTextNode("0") ); + book.appendChild( open ); + + KJotsEntryBase* entry = dynamic_cast(firstChild()); + while ( entry ) + { + entry->generateXml( doc, book ); + entry = dynamic_cast(entry->nextSibling()); + } + + if ( !m_fileName.isEmpty() && QListViewItem::parent() ) + { + //Hmmmm... We were originally loaded from a file, but now we have a parent, so + //we must have been moved into another tree. Remove the old file now that we + //have saved ourselves into the new tree. + deleteBook(); + } + + return; +} + +/*! + Parses through XML code from a file. +*/ +void KJotsBook::parseXml( QDomElement &me ) +{ + KJotsEntryBase *lastEntry = 0; //keep track of the last entry inserted for speed + + if ( me.tagName() == "KJotsBook" ) + { + QDomNode n = me.firstChild(); + while( !n.isNull() ) + { + QDomElement e = n.toElement(); // try to convert the node to an element. + if ( !e.isNull() ) + { + if ( e.tagName() == "KJotsPage" ) + { + KJotsPage *page = new KJotsPage(this, lastEntry); + page->parseXml(e); + lastEntry=page; + } + else + if ( e.tagName() == "KJotsBook" ) + { + KJotsBook *book = new KJotsBook(this, lastEntry); + book->parseXml(e); + lastEntry=book; + } + else + if ( e.tagName() == "Open" ) + { + if ( e.text() == "1" ) + { + this->setOpen(true); + } + } + else + { + //What was this? Send it to the base class and see if it can figure it out. + KJotsEntryBase::parseXml(e); + } + } + n = n.nextSibling(); + } + } + + return; +} + +/*! + \brief Returns an HTML Table of contents for this book. + This is a helper function for generateHtml(). +*/ +QString KJotsBook::getToc() +{ + QString toc; + + toc += "
    "; + + KJotsEntryBase *entry = dynamic_cast(firstChild()); + while ( entry ) { + QString htmlSubject = prepForHTML(entry->subject()); + toc += QString("
  • ").arg(entry->id()) + htmlSubject + "
  • "; + + KJotsBook *book = dynamic_cast(entry); + if ( book ) toc += book->getToc(); + + entry = dynamic_cast(entry->nextSibling()); + } + + toc += "
"; + return toc; +} + +/*! + \brief Returns HTML for the read-only "book" view. + \param top Pointer to the "starting point" of this tree. + \param diskMode Files saved to disk have a slightly different format. +*/ +QString KJotsBook::generateHtml( KJotsEntryBase* top, bool diskMode ) +{ + QString toc, body; + QString htmlTitle = prepForHTML(subject()); + + if ( top == this ) + { + toc = QString("

%2

").arg(id()).arg(htmlTitle); + } else { + if ( diskMode ) + { + toc = QString("

%2

").arg(id()).arg(htmlTitle); + } else { + toc = QString("

%3

").arg(id()).arg(id()).arg(htmlTitle); + } + } + + toc += "

" + i18n("Table of Contents") + "

"; + toc += getToc(); + toc += "
"; + + // Do the body text of the entries. + KJotsEntryBase* entry = dynamic_cast(firstChild()); + while ( entry ) + { + body += entry->generateHtml(top, diskMode); + entry = dynamic_cast(entry->nextSibling()); + } + + return toc + body; +} + +/*! + \brief Returns Text when saving to a file. + + This functions output moderately formatted text when the user chooses to save as + a text file. +*/ +QString KJotsBook::generateText( void ) +{ + QString out; + + //Print Fancy Text header + QString line, buf; + line.fill('#', subject().length() + 2); + line += "\n"; + out = line + QString("# ") + subject() + QString("\n") + line; + + KJotsEntryBase* entry = dynamic_cast(firstChild()); + while ( entry ) + { + out += entry->generateText(); + entry = dynamic_cast(entry->nextSibling()); + } + + out += "\n"; + return out; +} + +// +// KJotsPage +// + +KJotsPage::KJotsPage(KJotsBook* parent, QListViewItem *after) + : KJotsEntryBase(parent,after), + m_editor(0) +{ + m_isBook = false; + m_paraPos = m_indexPos = 0; + setPixmap(0, kapp->iconLoader()->loadIcon(QString("edit"), KIcon::Small)); +} + +KJotsPage::~KJotsPage() +{ + if ( m_editor ) + { + //Well now, this isn't good. We're going bye-bye but the editor + //still thinks we're here. Set ourselves to 0 (IMPORTANT!!) and + //then clear the editor. + KJotsEdit *temp = m_editor; + m_editor=0; + temp->setEntry(0); + } +} + +/*! + \brief Sets up info for a new page. + + This should be called on brand new pages. +*/ +void KJotsPage::initNewPage(void) +{ + setId(0); + setSubject(defaultSubject()); +} + +/*! + \brief Return the text of this page. +*/ +QString KJotsPage::body() +{ + //if we're being edited we want the current text, not whatever we saved before. + if ( m_editor && m_editor->edited() ) + { + m_text = m_editor->text(); + m_editor->setEdited(false); + setDirty(true); + } + + return m_text; +} + +/*! + \brief Sets the text of this page. +*/ +void KJotsPage::setBody(const QString& text) +{ + assert ( !m_editor ); //m_editor should *never* be set. + m_text = text; +} + +void KJotsPage::rename() +{ + bool ok; + + QString name = KInputDialog::getText(i18n( "Rename Page" ), + i18n( "Page title:" ), + subject(), &ok, listView() ); + + if (ok) + { + setSubject(name); + + KJotsMain* m = dynamic_cast(kapp->mainWidget()); + + if (m) + m->updateCaption(); + + setDirty(true); + } +} + +/*! + \brief Initiated when the user chooses to save this to a file. + This function gets everything ready to go to save to the disk. +*/ +void KJotsPage::saveToFile(KURL url, bool plainText, const QString& encoding) +{ + if (url.isEmpty() || m_saveInProgress) + return; + + m_saveToPlainText = plainText; + m_saveEncoding = QTextCodec::codecForName(encoding.ascii()); + KIO::TransferJob* job = KIO::put(url, -1, true, false, false); + if (!job) + { + return; + } + + connect(job, SIGNAL(dataReq(KIO::Job*, QByteArray&)), SLOT(saveDataReq(KIO::Job*, QByteArray&))); + connect(job, SIGNAL(result( KIO::Job *)), SLOT(slotSaveResult( KIO::Job *))); + m_saveInProgress = true; +} + +/*! + \brief Pumps out data when saving to a file. + This function pumps out page data during a disk save. + + \todo This should be augmented to cycle in case of REALLY long pages. +*/ +void KJotsPage::saveDataReq(KIO::Job* /* job */, QByteArray& data) +{ + if (!m_saveInProgress) return; //sanity check + + QTextStream stream(data, IO_WriteOnly); + stream.setCodec(m_saveEncoding); + + if ( !m_saveToPlainText ) + { + stream << htmlHeader(subject(), m_saveEncoding); + stream << generateHtml(this, true); + stream << htmlFooter(); + } else { + stream << generateText(); + } + + m_saveInProgress = false; +} + +/*! + \brief Completes a disk save. + This function is called after a disk save. The disk save may or may + not have completed normally. +*/ +void KJotsPage::slotSaveResult(KIO::Job *) +{ + m_saveInProgress = false; + /* if (job->error() != 0) {} */ +} + +void KJotsPage::print(QFont& defaultFont) +{ + KJotsEntryBase* book = dynamic_cast(KListViewItem::parent()); + + QString docName = book->subject(); + if (!subject().isNull()) + { + docName += ": " + subject(); + } + + KPrinter printer; + printer.setDocName(docName); + printer.setFullPage(false); + printer.setCreator("KJots"); + + if (printer.setup(listView(), i18n("Print: %1").arg(docName))) + { + QPainter painter( &printer ); + painter.setFont(defaultFont); + print(printer, painter, 0); + painter.end(); + } +} + +/*! + \brief Prints this page. +*/ +int KJotsPage::print(KPrinter& printer, QPainter& painter, int y) +{ + QPaintDeviceMetrics metrics( &printer ); + int maxWidth = metrics.width(); + int maxHeight = metrics.height(); + //TODO: Is it really necessary to copy the entire body when printing? + QStringList paragraphs = QStringList::split(QChar('\n'), body(), true); + + y = printTitleBox(subject(), printer, painter, y); + + for (QStringList::iterator para = paragraphs.begin(); + para != paragraphs.end(); + ++para) + { + //Watch for blank lines inserted as spacers. + if ( (*para).isNull() ) *para = " "; + + QRect r = painter.boundingRect(0, y, + maxWidth, maxHeight, + QPainter::ExpandTabs | QPainter::WordBreak, + *para); + + if ((y + r.height()) > maxHeight) + { + printer.newPage(); + y = 0; + } + + painter.drawText(0, y, maxWidth, maxHeight - y, + QPainter::ExpandTabs | QPainter::WordBreak, + *para); + y += r.height(); + } + + return y; +} + +/*! + \brief Get the default title of this page. + \note This is only used by initNewPage(); it could probably be removed. +*/ +QString KJotsPage::defaultSubject() +{ + int page = 0; + + if ( parentBook() ) + { + //We can't use childCount() here because it will count books, too. + KJotsEntryBase *entry = dynamic_cast(parentBook()->firstChild()); + while ( entry ) + { + if ( entry->isPage() ) ++page; + entry = dynamic_cast(entry->nextSibling()); + } + } else { + //We should never be here. + page = 1; + } + + return i18n("Page %1").arg(page); +} + +/*! + \brief Tells this page that it has been loaded into the edit window. +*/ +void KJotsPage::setEditor( KJotsEdit *editor ) +{ + //out with the old... + if ( m_editor ) + { + m_editor->getCursorPosition(&m_paraPos, &m_indexPos); + + if ( m_editor->edited() ) + { + m_text = m_editor->text(); + setDirty(true); + } + } + + m_editor = editor; + + //and in with the new + if ( m_editor ) + { + m_editor->setEdited(false); + m_editor->setCursorPosition(m_paraPos, m_indexPos); + } + + return; +} + +/*! + \brief Has the data in this page been changed? + We first check the editor status, if we are being edited. Then we let + the base class handle things for us. +*/ +bool KJotsPage::isDirty() +{ + if ( m_editor && m_editor->edited() ) + { + setDirty(true); + } + + return KJotsEntryBase::isDirty(); +} + +/*! + \brief Creates XML code and performs necessary tasks to save file. + This function should ONLY be called when saving the file. +*/void KJotsPage::generateXml( QDomDocument &doc, QDomElement &parent ) +{ + QDomElement page = doc.createElement( "KJotsPage" ); + parent.appendChild( page ); + + KJotsEntryBase::generateXml(doc, page); //let the base class save important stuff + + QDomElement text = doc.createElement( "Text" ); + QString saveText = body(); + if ( saveText.contains("]]>") ) { + saveText.replace("]]>","]]>"); + text.setAttribute("fixed", "1"); + } + text.appendChild( doc.createCDATASection( saveText )); + page.appendChild( text ); + + return; +} + +/*! + Parses through XML code from a file. +*/ +void KJotsPage::parseXml( QDomElement &me ) +{ + if ( me.tagName() == "KJotsPage" ) + { + QDomNode n = me.firstChild(); + while( !n.isNull() ) + { + QDomElement e = n.toElement(); // try to convert the node to an element. + if ( !e.isNull() ) + { + if ( e.tagName() == "Text" ) + { + QString bodyText = e.text(); + if ( e.hasAttribute("fixed") ) + { + bodyText.replace("]]>", "]]>"); + } + setBody(bodyText); + } + else + { + //What was this? Send it to the base class and see if it can figure it out. + KJotsEntryBase::parseXml(e); + } + } + n = n.nextSibling(); + } + } + + return; +} + +/*! + \brief Returns HTML for the read-only "book" overview. + \param top This tells us that we are the toplevel. + \param diskMode Files saved to disk have a slightly different format. +*/ +QString KJotsPage::generateHtml( KJotsEntryBase *top, bool diskMode ) +{ + QString html; + QString htmlSubject = prepForHTML(subject()); + + if ( top == this || diskMode ) { + html += QString("

%2

").arg(id()).arg(htmlSubject); + } else { + html += QString("

%3

").arg(id()).arg(id()).arg(htmlSubject); + } + html += prepForHTML(body()); + + html += "
" << endl; + os << "" << endl; + for( i=0; i" << endl << "" << endl; + } + + os << "" << endl << "
" << endl; + return( Err_Success ); +} + + +int CHexBuffer::printHtmlLine( QTextStream &os, uint line, bool isPrimary, + bool bw ) +{ + uint offset = line * mLayout.lineSize; + QColor prevColor; + + QColor color; + if( bw == true ) + { + color = Qt::white; + } + else + { + color = (line+1) % 2 ? mColor.textBg : mColor.secondTextBg; + } + + os << "
" + << endl; + if( offset >= documentSize() ) + { + os << "
"; + html += QString("").arg(id()).arg(subject()); + + if ( top != this ) + { + KJotsBook *parent = parentBook(); + while ( parent ) + { + html += QString("").arg(parent->id()).arg(parent->subject()); + if ( parent == top ) break; + parent = parent->parentBook(); + } + } + html += QString("
%2%2
"); + + if ( top != this ) html += "
"; + return html; +} + +/*! + \brief Returns Text when saving to a file. + \param top This is a hint to specify if this book is the "starting point" or not. + + This functions output moderately formatted text when the user chooses to save as + a text file. +*/ +QString KJotsPage::generateText( void ) +{ + QString out; + + //Print Fancy Text header + QString line, buf; + line.fill('#', subject().length() + 2); + line += "\n"; + out = line + QString("# ") + subject() + QString("\n") + line; + + out += body(); + + out += "\n"; + return out; +} + +/* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ + +#include "kjotsentry.moc" diff --git a/kjots/kjotsentry.h b/kjots/kjotsentry.h new file mode 100644 index 0000000..a16d176 --- /dev/null +++ b/kjots/kjotsentry.h @@ -0,0 +1,179 @@ +// +// kjots +// +// Copyright (C) 1997 Christoph Neerfeld +// Copyright (C) 2002, 2003 Aaron J. Seigo +// Copyright (C) 2003 Stanislav Kljuhhin +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef __KJOTSENTRY_H +#define __KJOTSENTRY_H + +#include +#include + +// +// class KJotsEntryBase +// + +class KURL; +class KJotsPage; +class KProgressDialog; +class KJotsEdit; +class QTextCodec; +class QDomDocument; +class QDomElement; +class QFile; + +class KJotsBook; + +namespace KIO +{ + class Job; +} + +class KJotsEntryBase : public QObject, public KListViewItem +{ + Q_OBJECT + public: + KJotsEntryBase(KListView*, QListViewItem*); + KJotsEntryBase(KListViewItem*, QListViewItem*); + + public: + virtual void setSubject(const QString&); + QString subject() { return text(0); } + void setText(int,const QString&); + virtual void saveToFile(KURL, bool plainText, const QString& encoding) = 0; + virtual void print(QFont& defaultFont) = 0; + virtual int print(KPrinter&, QPainter&, int) = 0; + virtual QString defaultSubject() = 0; //!< "subject" is the caption name + virtual void rename() = 0; + virtual void generateXml( QDomDocument&, QDomElement& ); + virtual void parseXml( QDomElement& ); + virtual QString generateHtml( KJotsEntryBase*, bool ) = 0; + virtual QString generateText( void ) = 0; + + void setDirty(bool d) { m_dirty = d; } //!< Toggles the dirty flag. + virtual bool isDirty() { return m_dirty; }; //!< Accessor for dirty flag. + + Q_UINT64 id() { return m_id; } + void setId(Q_UINT64); + + KJotsBook *parentBook() { return m_parent; } + void resetParent(); + + bool isBook() const { return m_isBook; } + bool isPage() const { return !m_isBook; } + + protected: + int printTitleBox(QString, KPrinter&, QPainter&, int); + + bool m_saveInProgress; //!< Toggled during a manual disk save. + bool m_isBook; //!< used for speed and code clarity. + + private: + Q_UINT64 m_id; //!< unique ID for this entry + bool m_dirty; //!< Set when this entry has been changed. + KJotsBook *m_parent; //!< used during drag-n-drop moving +}; + +// +// class KjotsBook +// + +class KJotsBook : public KJotsEntryBase +{ + Q_OBJECT + public: + KJotsBook(KListView*, QListViewItem* after = 0); + KJotsBook(KListViewItem*, QListViewItem* after = 0); + ~KJotsBook(); + + static bool isBookFile(const QString& book); + bool openBook(const QString&); + void saveBook(); + void deleteBook(); + void rename(); + void saveToFile(KURL, bool plainText, const QString& encoding); + KJotsPage* addPage(); //!< Add a new page to this book. + void print(QFont& defaultFont); + int print(KPrinter&, QPainter&, int); + bool isDirty(); + QString defaultSubject(); + void generateXml( QDomDocument&, QDomElement& ); + void parseXml( QDomElement& ); + QString generateHtml( KJotsEntryBase*, bool ); + QString generateText( void ); + + protected slots: + void saveDataReq(KIO::Job* job, QByteArray& data); + void slotSaveResult(KIO::Job*); + + private: + QString getToc(); + bool loadOldBook(QFile &); + void init(); + + bool m_open; + QString m_fileName; + bool m_saveToPlainText; + QTextCodec* m_saveEncoding; + KProgressDialog* m_saveProgressDialog; +}; + +// +// class KJotsPage +// +class KJotsPage : public KJotsEntryBase +{ + Q_OBJECT + public: + KJotsPage(KJotsBook* parent, QListViewItem* after = 0); + ~KJotsPage(); + + public: + QString body(); + void setBody(const QString&); + void saveToFile(KURL, bool plainText, const QString& encoding); + void print(QFont& defaultFont); + int print(KPrinter&, QPainter&, int); + QString defaultSubject(); + void rename(); + + void setEditor(KJotsEdit*); + bool isDirty(); + void generateXml( QDomDocument&, QDomElement& ); + void parseXml( QDomElement& ); + void initNewPage(void); + QString generateHtml( KJotsEntryBase*, bool ); + QString generateText( void ); + + protected slots: + void saveDataReq(KIO::Job* job, QByteArray& data); + void slotSaveResult(KIO::Job*); + + private: + QString m_text; + QTextCodec* m_saveEncoding; + bool m_saveToPlainText; + KJotsEdit *m_editor; //!< ptr to editor if this is the active subject + int m_paraPos; //< used to remrmber the cursor position + int m_indexPos; //< used to remrmber the cursor position +}; + +#endif // __KJOTSENTRY_H +/* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/kjots/kjotsui.rc b/kjots/kjotsui.rc new file mode 100644 index 0000000..6c63a07 --- /dev/null +++ b/kjots/kjotsui.rc @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kjots/main.cpp b/kjots/main.cpp new file mode 100644 index 0000000..4b0c10d --- /dev/null +++ b/kjots/main.cpp @@ -0,0 +1,98 @@ +// -*- C++ -*- + +// +// kjots +// +// Copyright (C) 1997 Christoph Neerfeld +// email: Christoph.Neerfeld@home.ivm.de or chris@kde.org +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include +#include +#include +#include +#include + +#include "KJotsMain.h" + + +static const char description[] = I18N_NOOP("KDE note taking utility"); + +static const char version[] = "v0.7"; + + +int main( int argc, char **argv ) +{ + KAboutData aboutData( "kjots", I18N_NOOP("KJots"), + version, description, KAboutData::License_GPL, + "(c) 1997-2002, Christoph Neerfeld"); + aboutData.addAuthor("Pradeepto K. Bhattacharya", I18N_NOOP("Current maintainer"), "pradeepto@kde.org"); + aboutData.addAuthor("Jaison Lee", 0, "lee.jaison@gmail.com"); + aboutData.addAuthor("Aaron J. Seigo", 0, "aseigo@kde.org"); + aboutData.addAuthor("Stanislav Kljuhhin", 0, "crz@starman.ee"); + aboutData.addAuthor("Christoph Neerfeld", I18N_NOOP("Original author"), "chris@kde.org"); + KCmdLineArgs::init(argc, argv, &aboutData); + KUniqueApplication::addCmdLineOptions(); + + if (!KUniqueApplication::start()) + { + fprintf(stderr, "kjots is already running!\n"); + exit(0); + } + + KUniqueApplication a; + + // backwards compatibility code to convert "old" user font settings + // to the new config settings + KConfig *config = a.config(); + config->setGroup("kjots"); + if (config->hasKey("EFontFamily")) { + // read old font and create it + QFont font( config->readEntry("EFontFamily"), + config->readNumEntry("EFontSize", 12), + config->readNumEntry("EFontWeight", 0), + config->readNumEntry("EFontItalic", 0)); + // delete old entries + config->deleteEntry("EFontFamily"); + config->deleteEntry("EFontSize"); + config->deleteEntry("EFontWeight"); + config->deleteEntry("EFontItalic"); + config->deleteEntry("EFontCharset"); + // write new "converted" entry + config->writeEntry("Font", font); + } + + KJotsMain *jots = new KJotsMain; + if( a.isRestored() ) + { + if( KJotsMain::canBeRestored(1) ) + { + jots->restore(1); + } + } + + a.setMainWidget( (QWidget *) jots ); + jots->show(); + jots->resize(jots->size()); + return a.exec(); +} + +/* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/klaptopdaemon/Makefile.am b/klaptopdaemon/Makefile.am new file mode 100644 index 0000000..8a2e737 --- /dev/null +++ b/klaptopdaemon/Makefile.am @@ -0,0 +1,49 @@ +kde_module_LTLIBRARIES = kcm_laptop.la kded_klaptopdaemon.la +bin_PROGRAMS = klaptop_acpi_helper klaptop_check +lib_LTLIBRARIES = libkcmlaptop.la +SUBDIRS = pics applnk + +libkcmlaptop_la_SOURCES = portable.cpp smapidev.c daemon_state.cpp wake_laptop.cpp krichtextlabel.cpp +libkcmlaptop_la_LDFLAGS = $(all_libraries) +libkcmlaptop_la_LIBADD = $(LIB_KDEUI) + +MESSAGE_SOURCES = laptop_daemon.cpp kpcmcia.cpp xautolock.cc kpcmciainfo.cpp daemondock.cpp xautolock_diy.c xautolock_engine.c +kded_klaptopdaemon_la_SOURCES = $(MESSAGE_SOURCES) laptop_daemon.skel +kded_klaptopdaemon_la_LDFLAGS = $(all_libraries) -module -avoid-version -lXtst +kded_klaptopdaemon_la_LIBADD = $(LIB_KDEUI) $(LIB_XSS) libkcmlaptop.la + +klaptop_acpi_helper_SOURCES = acpi_helper.cpp + +klaptop_check_SOURCES = laptop_check.cpp +klaptop_check_LDFLAGS = $(all_libraries) +klaptop_check_LDADD = $(LIB_KFILE) $(LIB_KDEUI) libkcmlaptop.la + +kcm_laptop_la_SOURCES = battery.cpp main.cpp pcmcia.cpp power.cpp warning.cpp \ + acpi.cpp sony.cpp profile.cpp buttons.cpp apm.cpp +kcm_laptop_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +kcm_laptop_la_LIBADD = $(LIB_KFILE) $(LIB_KDEUI) libkcmlaptop.la +kcm_laptop_la_COMPILE_FIRST = crcresult.h + +AM_CPPFLAGS = $(all_includes) + +AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) + +KDE_OPTIONS = nofinal + +kcm_laptop_la_METASOURCES = AUTO + +messages: + $(XGETTEXT) $(libkcmlaptop_la_SOURCES) $(klaptop_acpi_helper_SOURCES) $(klaptop_check_SOURCES) $(MESSAGE_SOURCES) -o $(podir)/klaptopdaemon.pot + $(XGETTEXT) $(kcm_laptop_la_SOURCES) -o $(podir)/kcmlaptop.pot + +dummy.cpp: + echo >dummy.cpp + +noinst_PROGRAMS = makecrc +makecrc_SOURCES = makecrc.cpp +makecrc_LDADD = $(LIBZ) + +crcresult.h: makecrc klaptop_acpi_helper + ./makecrc >crcresult.h + +CLEANFILES = crcresult.h makecrc diff --git a/klaptopdaemon/README b/klaptopdaemon/README new file mode 100644 index 0000000..858e0ff --- /dev/null +++ b/klaptopdaemon/README @@ -0,0 +1,8 @@ +This is klaptop daemon it provides battery monitoring and management +for laptops - this is a KDE 2 rewrite of kcmlaptop which is not +supported for KDE >2.0. Please pass any bug reports to Paul Campbell +paul@taniwha.com. + +The power management stuff is all abstracted out into portable.* +if you feel the urge to port it to your OS/CPU please contact me for +help - Paul diff --git a/klaptopdaemon/acpi.cpp b/klaptopdaemon/acpi.cpp new file mode 100644 index 0000000..cb13f40 --- /dev/null +++ b/klaptopdaemon/acpi.cpp @@ -0,0 +1,281 @@ +/* + * acpi.cpp + * + * Copyright (c) 1999, 2003 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// my headers: +#include "acpi.h" +#include "version.h" +#include "portable.h" +#include +#include + +// other KDE headers: +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// other Qt headers: +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern void wake_laptop_daemon(); + +AcpiConfig::AcpiConfig (QWidget * parent, const char *name) + : KCModule(parent, name) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + config = new KConfig("kcmlaptoprc"); + + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *tmp_label = new QLabel( i18n("This panel provides information about your system's ACPI implementation " + "and lets you have access to some of the extra features provided by ACPI"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + tmp_label = new QLabel( i18n("NOTE: the Linux ACPI implementation is still a 'work in progress'. " + "Some features, in particular suspend and hibernate are not yet available " + "under 2.4 - and under 2.5 some particular ACPI implementations are still " + "unstable, these check boxes let you only enable the things that work reliably. " + "You should test these features very gingerly - save all your work, check them " + "on and try a suspend/standby/hibernate from the popup menu on the battery icon " + "in the panel if it fails to come back successfully uncheck the box again."), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + tmp_label = new QLabel( i18n("Some changes made on this page may require you to quit the laptop panel " + "and start it again to take effect"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + bool can_enable = laptop_portable::has_acpi(1); // is helper ready + enableStandby = new QCheckBox( i18n("Enable standby"), this ); + top_layout->addWidget( enableStandby ); + QToolTip::add( enableStandby, i18n( "If checked this box enables transitions to the 'standby' state - a temporary powered down state" ) ); + enableStandby->setEnabled(can_enable); + connect( enableStandby, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + enableSuspend = new QCheckBox( i18n("Enable &suspend"), this ); + top_layout->addWidget( enableSuspend ); + QToolTip::add( enableSuspend, i18n( "If checked this box enables transitions to the 'suspend' state - a semi-powered down state, sometimes called 'suspend-to-ram'" ) ); + enableSuspend->setEnabled(can_enable); + connect( enableSuspend, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + QHBoxLayout *ll = new QHBoxLayout(); + enableHibernate = new QCheckBox( i18n("Enable &hibernate"), this ); + ll->addWidget( enableHibernate ); + QToolTip::add( enableHibernate, i18n( "If checked this box enables transitions to the 'hibernate' state - a powered down state, sometimes called 'suspend-to-disk'" ) ); + enableHibernate->setEnabled(can_enable); + connect( enableHibernate, SIGNAL(clicked()), this, SLOT(configChanged()) ); + if (laptop_portable::has_software_suspend()) { + ll->addStretch(1); + enableSoftwareSuspendHibernate = new QCheckBox( i18n("Use software suspend for hibernate"), this ); + ll->addWidget( enableSoftwareSuspendHibernate ); + QToolTip::add( enableSoftwareSuspendHibernate, i18n( "If checked this box enables transitions to the 'hibernate' state - a powered down state, sometimes called 'suspend-to-disk' - the kernel 'Software Suspend' mechanism will be used instead of using ACPI directly" ) ); + enableSoftwareSuspendHibernate->setEnabled(laptop_portable::has_software_suspend(2)); + connect( enableSoftwareSuspendHibernate, SIGNAL(clicked()), this, SLOT(configChanged()) ); + } else { + enableSoftwareSuspendHibernate = 0; + } + ll->addStretch(10); + + top_layout->addLayout(ll); + + enablePerformance = new QCheckBox( i18n("Enable &performance profiles"), this ); + top_layout->addWidget( enablePerformance ); + QToolTip::add( enablePerformance, i18n( "If checked this box enables access to ACPI performance profiles - usually OK in 2.4 and later" ) ); + enablePerformance->setEnabled(can_enable); + connect( enablePerformance, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + enableThrottle = new QCheckBox( i18n("Enable &CPU throttling"), this ); + top_layout->addWidget( enableThrottle ); + QToolTip::add( enableThrottle, i18n( "If checked this box enables access to ACPI throttle speed changes - usually OK in 2.4 and later" ) ); + enableThrottle->setEnabled(can_enable); + connect( enableThrottle, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + tmp_label = new QLabel(i18n("If the above boxes are disabled then there is no 'helper' " + "application set up to help change ACPI states, there are two " + "ways you can enable this application, either make the file " + "/proc/acpi/sleep writeable by anyone every time your system boots " + "or use the button below to make the KDE ACPI helper application " + "set-uid root"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + ll = new QHBoxLayout(); + QPushButton *setupButton = new QPushButton(i18n("Setup Helper Application"), this); + connect( setupButton, SIGNAL(clicked()), this, SLOT(setupHelper()) ); + QToolTip::add( setupButton, i18n( "This button can be used to enable the ACPI helper application" ) ); + ll->addStretch(2); + ll->addWidget(setupButton); + ll->addStretch(8); + top_layout->addLayout(ll); + + + top_layout->addStretch(1); + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this), 0, Qt::AlignRight ); + + + load(); +} + +AcpiConfig::~AcpiConfig() +{ + delete config; +} + +#include "checkcrc.h" +#include "crcresult.h" +#include + +void AcpiConfig::setupHelper() +{ + unsigned long len, crc; + QString helper = KStandardDirs::findExe("klaptop_acpi_helper"); + checkcrc(QFile::encodeName(helper), len, crc); + if (len != file_len || crc != file_crc) { + QString str(i18n("The %1 application does not seem to have " + "the same size or checksum as when it was compiled we do NOT recommend " + "you proceed with making it setuid-root without further investigation").arg(helper)); + int rc = KMessageBox::warningContinueCancel(0, str, i18n("KLaptopDaemon"), i18n("Run Nevertheless")); + if (rc != KMessageBox::Continue) + return; + } + + QString kdesu = KStandardDirs::findExe("kdesu"); + if (!kdesu.isEmpty()) { + int rc = KMessageBox::warningContinueCancel(0, + i18n("You will need to supply a root password " + "to allow the privileges of the klaptop_acpi_helper to change."), + i18n("KLaptopDaemon"), KStdGuiItem::cont(), + ""); + if (rc == KMessageBox::Continue) { + KProcess proc; + proc << kdesu; + proc << "-u"; + proc << "root"; + proc << "chown root "+helper+"; chmod +s "+helper; + proc.start(KProcess::Block); // run it sync so has_acpi below sees the results + } + } else { + KMessageBox::sorry(0, i18n("The ACPI helper cannot be enabled because kdesu cannot be found. Please make sure that it is installed correctly."), + i18n("KLaptopDaemon")); + } + laptop_portable::acpi_set_mask(enablestandby, enablesuspend, enablehibernate, enableperformance, enablethrottle); + bool can_enable = laptop_portable::has_acpi(1); // is helper ready + enableStandby->setEnabled(can_enable); + enableSuspend->setEnabled(can_enable); + enableHibernate->setEnabled(can_enable); + enablePerformance->setEnabled(can_enable); + enableThrottle->setEnabled(can_enable); + if (enableSoftwareSuspendHibernate) + enableSoftwareSuspendHibernate->setEnabled(laptop_portable::has_software_suspend(2)); + wake_laptop_daemon(); +} + + +void AcpiConfig::save() +{ + enablestandby = enableStandby->isChecked(); + enablesuspend = enableSuspend->isChecked(); + enablehibernate = enableHibernate->isChecked(); + enablesoftwaresuspend = (enableSoftwareSuspendHibernate?enableSoftwareSuspendHibernate->isChecked():0); + enableperformance = enablePerformance->isChecked(); + enablethrottle = enableThrottle->isChecked(); + laptop_portable::acpi_set_mask(enablestandby, enablesuspend, enablehibernate, enableperformance, enablethrottle); + + config->setGroup("AcpiDefault"); + + config->writeEntry("EnableStandby", enablestandby); + config->writeEntry("EnableSuspend", enablesuspend); + config->writeEntry("EnableHibernate", enablehibernate); + config->writeEntry("EnableThrottle", enablethrottle); + config->writeEntry("EnablePerformance", enableperformance); + config->setGroup("SoftwareSuspendDefault"); + config->writeEntry("EnableHibernate", enablesoftwaresuspend); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void AcpiConfig::load() +{ + load( false ); +} + +void AcpiConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + + config->setGroup("AcpiDefault"); + + enablestandby = config->readBoolEntry("EnableStandby", false); + enableStandby->setChecked(enablestandby); + enablesuspend = config->readBoolEntry("EnableSuspend", false); + enableSuspend->setChecked(enablesuspend); + enablehibernate = config->readBoolEntry("EnableHibernate", false); + enableHibernate->setChecked(enablehibernate); + enableperformance = config->readBoolEntry("EnablePerformance", false); + enablePerformance->setChecked(enableperformance); + enablethrottle = config->readBoolEntry("EnableThrottle", false); + enableThrottle->setChecked(enablethrottle); + config->setGroup("SoftwareSuspendDefault"); + enablesoftwaresuspend = config->readBoolEntry("EnableHibernate", false); + if (enableSoftwareSuspendHibernate) + enableSoftwareSuspendHibernate->setChecked(enablesoftwaresuspend); + + emit changed(useDefaults); +} + +void AcpiConfig::defaults() +{ + load( true ); +} + + +void AcpiConfig::configChanged() +{ + emit changed(true); +} + + +QString AcpiConfig::quickHelp() const +{ + return i18n("

ACPI Setup

This module allows you to configure ACPI for your system"); +} + +#include "acpi.moc" + + diff --git a/klaptopdaemon/acpi.h b/klaptopdaemon/acpi.h new file mode 100644 index 0000000..a6a77cb --- /dev/null +++ b/klaptopdaemon/acpi.h @@ -0,0 +1,72 @@ +/* + * acpi.h + * + * Copyright (c) 2002 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __ACPICONFIG_H__ +#define __ACPICONFIG_H__ + +#include +#include + +class QWidget; +class QSpinBox; +class KConfig; +class QCheckBox; +class KIconLoader; +class KIconButton; +class QPushButton; + + +class AcpiConfig : public KCModule +{ + Q_OBJECT +public: + AcpiConfig( QWidget *parent=0, const char* name=0); + ~AcpiConfig( ); + + void save( void ); + void load(); + void load( bool useDefaults ); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + void setupHelper(); + +private: + KConfig *config; + + QCheckBox *enableHibernate; + QCheckBox *enableSuspend; + QCheckBox *enableStandby; + QCheckBox *enablePerformance; + QCheckBox *enableThrottle; + QCheckBox *enableSoftwareSuspendHibernate; + bool enablestandby, enablesuspend, enablehibernate, enableperformance, enablethrottle, enablesoftwaresuspend; +}; + +#endif + diff --git a/klaptopdaemon/acpi_helper.cpp b/klaptopdaemon/acpi_helper.cpp new file mode 100644 index 0000000..660d2cb --- /dev/null +++ b/klaptopdaemon/acpi_helper.cpp @@ -0,0 +1,325 @@ +/* + * acpi_helper.cpp - acpi helper + * + * Copyright (c) 2002 Paul Campbell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// +// README!! +// +// This file contains code that is intended to be run setuid root +// (only if the end user enables it themselves, it's not set that +// way as part of a standard KDE build). +// +// Because of this this code should be simple and easily visually +// inspected for security holes and/or bugs - if you feel the need +// to change this file please get someone else to review your work +// (I'll happily do it for you - mail me at paul@taniwha.com, please +// review mine!) +// +// I recommend the following practices here - both for safety and +// transparency: +// +// - check all array references (snprintf/strncpy etc) +// +// - avoid malloc/new calls and pointers too if possible +// + +#include +#include +#include +#include +#include +#include + +#define MAX_TOSHIBA_STRING 64 + +/* Write a value to /proc/acpi/sleep, where value may be between + 1 and 4 (whatever they mean). Does not return; calls exit(). */ + +void write_to_proc_sleep(int value) +{ + char tmp[256]; + int fd; + + /* Sanity check value */ + if ((value<1) || (value>4)) + exit(1); + + /* Convert value to string */ + snprintf(tmp,sizeof(tmp),"%d",value); + tmp[sizeof(tmp)-1]=0; + + /* Broken imitation of typing sync sync + on the command line before shutting down the machine; + part of the lore of UNIX machines. */ + sync(); + sync(); + fd = open("/proc/acpi/sleep", O_RDWR); + if (fd < 0) + exit(1); + write(fd, tmp, 1); + close(fd); + setuid(getuid()); // drop all priority asap + exit(0); +} + +/* Write string to new acpi power interface */ +void write_to_power(const char * str) +{ + int fd; + /* Broken imitation of typing sync sync + on the command line before shutting down the machine; + part of the lore of UNIX machines. */ + sync(); + sync(); + fd = open("/sys/power/state", O_RDWR); + if (fd < 0) + exit(1); + write(fd, str, strlen(str)); + close(fd); + setuid(getuid()); // drop all priority asap + exit(0); +} + +/* Run the program @param path, if it exists and seems safe to do so. + Returns only if the program does not exist; if the program exists + and is unsafe, exit; if the program exists and is safe, run it + and never return. */ +void run_program(const char *path) +{ + struct stat sb; + int err; + + if (!path) exit(1); /* Bad pointer */ + if (path[0] != '/') exit(1); /* Not an absolute path */ + + if ((err = stat(path, &sb)) != 0 || sb.st_mode&S_IWOTH) { + if (err != 0) { + fprintf(stderr, "Can't find %s\n", path); + return; + } else { + fprintf(stderr, "%s is writeable by anyone - we don't trust it\n", path); + } + exit(1); + } + ::setuid(::geteuid()); // otherwise bash will throw it away + ::execl(path, NULL); // this is not KDE environment code + exit(0); +} + +int +main(int argc, char **argv) +{ + int fd; + int i; + int toshibalcd_val = 0; + bool useSysPower=false; + + fd = open("/sys/power/state", O_RDWR); + if (fd >= 0) + useSysPower=true; + close(fd); + + ::close(0); // we're setuid - this is just in case + for (i = 1; i < argc; i++) + if (strcmp(argv[i], "--suspend") == 0 || strcmp(argv[i], "-suspend") == 0) { + /* Returns only if suspend does not exist. */ + run_program("/usr/sbin/suspend"); + if (useSysPower) + write_to_power("mem"); + else + write_to_proc_sleep(3); + exit(0); + } else + if (strcmp(argv[i], "--standby") == 0 || strcmp(argv[i], "-standby") == 0) { + if (useSysPower) + write_to_power("standby"); + else + write_to_proc_sleep(1); + exit(0); + } else + if (strcmp(argv[i], "--standby2") == 0 || strcmp(argv[i], "-standby2") == 0) { + write_to_proc_sleep(2); + exit(0); + } else + if (strcmp(argv[i], "--hibernate") == 0 || strcmp(argv[i], "-hibernate") == 0) { + run_program("/usr/sbin/hibernate"); + if (useSysPower) + write_to_power("disk"); + else + write_to_proc_sleep(4); + exit(0); + } else + if (strcmp(argv[i], "--software-suspend") == 0 || strcmp(argv[i], "-software-suspend") == 0) { + run_program("/usr/sbin/hibernate"); + exit(0); + } else + if (strcmp(argv[i], "--throttling") == 0 || strcmp(argv[i], "-throttling") == 0) { + int val; + char tmp[256]; + + i++; + if (i >= argc) + break; + if (strlen(argv[i]) > 50 || strchr(argv[i], '.')) + break; + snprintf(tmp, sizeof(tmp), "/proc/acpi/processor/%s/throttling", argv[i]); + tmp[sizeof(tmp)-1] = 0; + i++; + if (i >= argc) + break; + val= atoi(argv[i]); + if (val < 0) + break; + sync(); + sync(); + fd = open(tmp, O_RDWR); + if (fd < 0) + exit(1); + snprintf(tmp, sizeof(tmp), "%d", val); + write(fd, tmp, strlen(tmp)); + close(fd); + setuid(getuid()); // drop all priority asap + exit(0); + } else + if (strcmp(argv[i], "--performance") == 0 || strcmp(argv[i], "-performance") == 0) { + int val; + char tmp[256]; + + i++; + if (i >= argc) + break; + if (strlen(argv[i]) > 50 || strchr(argv[i], '.')) + break; + snprintf(tmp, sizeof(tmp), "/proc/acpi/processor/%s/performance", argv[i]); + tmp[sizeof(tmp)-1] = 0; + i++; + if (i >= argc) + break; + val= atoi(argv[i]); + if (val < 0) + break; + sync(); + sync(); + fd = open(tmp, O_RDWR); + if (fd < 0) + exit(1); + snprintf(tmp, sizeof(tmp), "%d", val); + write(fd, tmp, strlen(tmp)); + close(fd); + setuid(getuid()); // drop all priority asap + exit(0); + } else + if (strcmp(argv[i], "--toshibalcd") == 0 || strcmp(argv[i], "-toshibalcd") == 0) { + + i++; + if (i >= argc) + break; + toshibalcd_val= atoi(argv[i]); + if (toshibalcd_val < 0) + toshibalcd_val = 0; + if (toshibalcd_val > 7) + toshibalcd_val = 7; + fd = open("/proc/acpi/TOSHIBA1/lcd", O_RDWR); + if (fd >= 0 ) { + char c; + + c = '0'+toshibalcd_val; + write(fd, &c, 1); + close(fd); + } else { + fd = open("/proc/acpi/toshiba/lcd", O_RDWR); + if (fd >= 0) { + char str[MAX_TOSHIBA_STRING]; + + snprintf(str,sizeof(str),"brightness : %d",toshibalcd_val); + str[sizeof(str)-1]=0; + write(fd,str,strlen(str)); + close(fd); + } + } + setuid(getuid()); // drop all priority asap + exit(0); + } else + // CPUFreq support + if (strncmp(argv[i], "--cpufreq", 9) == 0 || strncmp(argv[i], "-cpufreq", 8) == 0) { + if ((i+1) >= argc) + break; + if (strlen(argv[i+1]) > 50 || strchr(argv[i+1], '.')) + break; + int val; + char tmp[256]; + // CPUFreq support for the interface of the 2.4 kernell (/proc/sys/cpu/N/) + if (strcmp(argv[i], "--cpufreq-24") == 0 || strcmp(argv[i], "-cpufreq-24") == 0) { + ++i; + snprintf(tmp, sizeof(tmp), "/proc/sys/cpu/%s/speed", argv[i]); + tmp[sizeof(tmp)-1] = 0; + ++i; + if (i >= argc) + break; + val = atoi(argv[i]); + if (val < 0) + break; + fd = open(tmp, O_WRONLY); + if (fd < 0) + exit(1); + snprintf(tmp, sizeof(tmp), "%d", val); + write(fd, tmp, strlen(tmp)); + } else + // CPUFreq support for the interface of the 2.5 kernel (/proc/cpufreq) + if (strcmp(argv[i], "--cpufreq-25") == 0 || strcmp(argv[i], "-cpufreq-25") == 0) { + ++i; + snprintf(tmp, sizeof(tmp), "%s", argv[i]); + tmp[sizeof(tmp)-1] = 0; + fd = open("/proc/cpufreq", O_WRONLY); + if (fd < 0) + exit(1); + write(fd, tmp, strlen(tmp)); + } else + // CPUFreq support fot the sysfs interface of the 2.5 kernel (/sys/devices/sys/cpuN/cpufreq/) + if (strcmp(argv[i], "--cpufreq-sysfs") == 0 || strcmp(argv[i], "-cpufreq-sysfs") == 0) { + ++i; + snprintf(tmp, sizeof(tmp), "/sys/devices/system/cpu/%s/cpufreq/scaling_governor", argv[i]); + tmp[sizeof(tmp)-1] = 0; + ++i; + if (i >= argc) + break; + fd = open(tmp, O_WRONLY); + if (fd < 0) + exit(1); + if (strlen(argv[i]) > 50) + break; + snprintf(tmp, sizeof(tmp), "%s", argv[i]); + tmp[sizeof(tmp)-1] = 0; + write(fd, tmp, strlen(tmp)); + } else { + break; + } + close(fd); + setuid(getuid()); // drop all priority asap + exit(0); + } else { +usage: + setuid(getuid()); // drop all priority asap + fprintf(stderr, "Usage: %s [--suspend] [--standby] [--hibernate][--software-suspend][--toshibalcd N][--performance CPU N][--throttling CPU N][--cpufreq-[24|25|sysfs]]\n", argv[0]); + exit(1); + } + goto usage; + +} + diff --git a/klaptopdaemon/apm.cpp b/klaptopdaemon/apm.cpp new file mode 100644 index 0000000..a13a907 --- /dev/null +++ b/klaptopdaemon/apm.cpp @@ -0,0 +1,285 @@ +/* + * battery.cpp + * + * Copyright (c) 1999 Paul Campbell + * Copyright (c) 2002 Marc Mutz + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// my headers: +#include "apm.h" +#include "version.h" +#include "portable.h" +#include +#include + +// other KDE headers: +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// other Qt headers: +#include +#include +#include +#include +#include +#include +#include +#include +extern void wake_laptop_daemon(); + +ApmConfig::ApmConfig (QWidget * parent, const char *name) + : KCModule(parent, name) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + config = new KConfig("kcmlaptoprc"); + + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + QLabel *tmp_label = new QLabel( i18n("This panel lets you configure your APM system and lets " + "you have access to some of the extra features provided by it"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + tmp_label = new QLabel( i18n("NOTE: some APM implementations have buggy suspend/standby " + "implementations. You should test these features very gingerly - save " + "all your work, check them on and try a suspend/standby from " + "the popup menu on the battery icon in the panel if it fails to come " + "back successfully uncheck the box again."), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + tmp_label = new QLabel( i18n("Some changes made on this page may require you to quit the laptop panel " + "and start it again to take effect"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + bool can_enable = laptop_portable::has_apm(1); // is helper ready + enableStandby = new QCheckBox( i18n("Enable standby"), this ); + top_layout->addWidget( enableStandby ); + QToolTip::add( enableStandby, i18n( "If checked this box enables transitions to the 'standby' state - a temporary powered down state" ) ); + enableStandby->setEnabled(can_enable); + connect( enableStandby, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + enableSuspend = new QCheckBox( i18n("Enable &suspend"), this ); + top_layout->addWidget( enableSuspend ); + QToolTip::add( enableSuspend, i18n( "If checked this box enables transitions to the 'suspend' state - a semi-powered down state, sometimes called 'suspend-to-ram'" ) ); + enableSuspend->setEnabled(can_enable); + connect( enableSuspend, SIGNAL(clicked()), this, SLOT(configChanged()) ); + apm_name = "/usr/bin/apm"; + if (::access(apm_name, F_OK) != 0 && ::access("/usr/sbin/apm", F_OK) == 0) + apm_name = "/usr/sbin/apm"; + + tmp_label = new QLabel(i18n("If the above boxes are disabled then there is no 'helper' " + "application set up to help change APM states, there are two " + "ways you can enable this application, either make the file " + "/proc/apm writeable by anyone every time your system boots " + "or use the button below to make the %1 application " + "set-uid root").arg(apm_name), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + QHBoxLayout *ll = new QHBoxLayout(top_layout); + QPushButton *setupButton = new QPushButton(i18n("Setup Helper Application"), this); + connect( setupButton, SIGNAL(clicked()), this, SLOT(setupHelper()) ); + QToolTip::add( setupButton, i18n( "This button can be used to enable the APM helper application" ) ); + ll->addStretch(2); + ll->addWidget(setupButton); + ll->addStretch(8); + if (laptop_portable::has_software_suspend()) { + tmp_label = new QLabel( i18n("Your system seems to have 'Software Suspend' installed, this can " + "be used to hibernate or 'suspend to disk' your system if you want " + "to use this for hibernation check the box below"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + enableSoftwareSuspendHibernate = new QCheckBox( i18n("Enable software suspend for hibernate"), this ); + top_layout->addWidget( enableSoftwareSuspendHibernate ); + QToolTip::add( enableSoftwareSuspendHibernate, i18n( "If checked this box enables transitions to the 'hibernate' state using the 'Software Suspend' mechanism" ) ); + enableSoftwareSuspendHibernate->setEnabled(laptop_portable::has_software_suspend(2)); + connect( enableSoftwareSuspendHibernate, SIGNAL(clicked()), this, SLOT(configChanged()) ); + tmp_label = new QLabel( i18n("If the above box is disabled then you need to be logged in " + "as root or need a helper application to invoke the Software " + "Suspend utility - KDE provides a utility to do this, if you " + "wish to use it you must make it set-uid root, the button " + "below will do this for you"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + ll = new QHBoxLayout(this); + QPushButton *setupSSButton = new QPushButton(i18n("Setup SS Helper Application"), this); + connect( setupSSButton, SIGNAL(clicked()), this, SLOT(setupHelper2()) ); + QToolTip::add( setupSSButton, i18n( "This button can be used to enable the Software Suspend helper application" ) ); + ll->addStretch(2); + ll->addWidget(setupSSButton); + ll->addStretch(8); + } else { + enableSoftwareSuspendHibernate = 0; + } + + + top_layout->addStretch(1); + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this), 0, Qt::AlignRight ); + + + load(); +} + +ApmConfig::~ApmConfig() +{ + delete config; +} + +void ApmConfig::setupHelper() +{ + QString kdesu = KStandardDirs::findExe("kdesu"); + if (!kdesu.isEmpty()) { + int rc = KMessageBox::warningContinueCancel(0, + i18n("You will need to supply a root password " + "to allow the privileges of the %1 application to change.").arg(apm_name), + "KLaptopDaemon", KStdGuiItem::cont(), + ""); + if (rc == KMessageBox::Continue) { + KProcess proc; + proc << kdesu; + proc << "-u"; + proc << "root"; + proc << QString("chown root ")+apm_name+"; chmod +s "+apm_name; + proc.start(KProcess::Block); // run it sync so has_apm below sees the results + } + } else { + KMessageBox::sorry(0, i18n("%1 cannot be enabled because kdesu cannot be found. Please make sure that it is installed correctly.").arg(QString(apm_name)), + i18n("KLaptopDaemon")); + } + laptop_portable::apm_set_mask(enablestandby, enablesuspend); + bool can_enable = laptop_portable::has_apm(1); // is helper ready + enableStandby->setEnabled(can_enable); + enableSuspend->setEnabled(can_enable); + wake_laptop_daemon(); +} + +#include "checkcrc.h" +#include "crcresult.h" +void ApmConfig::setupHelper2() // we use the acpi helper to do software suspend +{ + unsigned long len, crc; + QString helper = KStandardDirs::findExe("klaptop_acpi_helper"); + checkcrc(helper.latin1(), len, crc); + if (len != file_len || crc != file_crc) { + QString str(i18n("The %1 application does not seem to have " + "the same size or checksum as when it was compiled we do NOT recommend " + "you proceed with making it setuid-root without further investigation").arg(helper)); + int rc = KMessageBox::warningContinueCancel(0, str, i18n("KLaptopDaemon"), i18n("Run Nevertheless")); + if (rc != KMessageBox::Continue) + return; + } + + QString kdesu = KStandardDirs::findExe("kdesu"); + if (!kdesu.isEmpty()) { + int rc = KMessageBox::warningContinueCancel(0, + i18n("You will need to supply a root password " + "to allow the privileges of the klaptop_acpi_helper to change."), + i18n("KLaptopDaemon"), KStdGuiItem::cont(), + ""); + if (rc == KMessageBox::Continue) { + KProcess proc; + proc << kdesu; + proc << "-u"; + proc << "root"; + proc << "chown root "+helper+"; chmod +s "+helper; + proc.start(KProcess::Block); // run it sync so has_acpi below sees the results + } + } else { + KMessageBox::sorry(0, i18n("The Software Suspend helper cannot be enabled because kdesu cannot be found. Please make sure that it is installed correctly."), + i18n("KLaptopDaemon")); + } + laptop_portable::software_suspend_set_mask(enablesoftwaresuspend); + bool can_enable = laptop_portable::has_software_suspend(2); // is helper ready + enableSoftwareSuspendHibernate->setEnabled(can_enable); + wake_laptop_daemon(); +} + + +void ApmConfig::save() +{ + enablestandby = enableStandby->isChecked(); + enablesuspend = enableSuspend->isChecked(); + laptop_portable::apm_set_mask(enablestandby, enablesuspend); + enablesoftwaresuspend = (enableSoftwareSuspendHibernate ? enableSoftwareSuspendHibernate->isChecked():0); + laptop_portable::software_suspend_set_mask(enablesoftwaresuspend); + + config->setGroup("ApmDefault"); + + config->writeEntry("EnableStandby", enablestandby); + config->writeEntry("EnableSuspend", enablesuspend); + + config->setGroup("SoftwareSuspendDefault"); + config->writeEntry("EnableHibernate", enablesoftwaresuspend); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void ApmConfig::load() +{ + load( false ); +} + +void ApmConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + config->setGroup("ApmDefault"); + enablestandby = config->readBoolEntry("EnableStandby", true); + enableStandby->setChecked(enablestandby); + enablesuspend = config->readBoolEntry("EnableSuspend", true); + enableSuspend->setChecked(enablesuspend); + config->setGroup("SoftwareSuspendDefault"); + enablesoftwaresuspend = config->readBoolEntry("EnableHibernate", false); + if (enableSoftwareSuspendHibernate) + enableSoftwareSuspendHibernate->setChecked(enablesoftwaresuspend); + emit changed(useDefaults); +} + +void ApmConfig::defaults() +{ + load( true ); +} + + +void ApmConfig::configChanged() +{ + emit changed(true); +} + + +QString ApmConfig::quickHelp() const +{ + return i18n("

APM Setup

This module allows you to configure APM for your system"); +} + + +#include "apm.moc" + + diff --git a/klaptopdaemon/apm.h b/klaptopdaemon/apm.h new file mode 100644 index 0000000..a2213e9 --- /dev/null +++ b/klaptopdaemon/apm.h @@ -0,0 +1,71 @@ +/* + * apm.h + * + * Copyright (c) 2003 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __APMCONFIG_H__ +#define __APMCONFIG_H__ + +#include +#include + +class QWidget; +class QSpinBox; +class KConfig; +class QCheckBox; +class KIconLoader; +class KIconButton; +class QPushButton; + + +class ApmConfig : public KCModule +{ + Q_OBJECT +public: + ApmConfig( QWidget *parent=0, const char* name=0); + ~ApmConfig( ); + + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + void setupHelper(); + void setupHelper2(); + +private: + KConfig *config; + + QCheckBox *enableSuspend; + QCheckBox *enableStandby; + QCheckBox *enableSoftwareSuspendHibernate; + bool enablestandby, enablesuspend, enablesoftwaresuspend; + const char *apm_name; +}; + +#endif + diff --git a/klaptopdaemon/applnk/.directory b/klaptopdaemon/applnk/.directory new file mode 100644 index 0000000..5099b09 --- /dev/null +++ b/klaptopdaemon/applnk/.directory @@ -0,0 +1,48 @@ +# KDE Config File +[KDE Desktop Entry] +Name=Laptop +Name[af]=Draagbare rekenaar +Name[az]=Dizüstü +Name[bg]=Лаптоп +Name[br]=Hezoug +Name[ca]=Portàtil +Name[cs]=Notebook +Name[cy]=Gliniadur +Name[da]=Bærbar +Name[de]=Notebook +Name[el]=Φορητό +Name[eo]=Portkomputilo +Name[es]=Portátil +Name[et]=Sülearvuti +Name[ga]=Ríomhaire Glúine +Name[gl]=Portátil +Name[hi]=लैपटॉप +Name[hu]=Noteszgép +Name[is]=Ferðavél +Name[it]=Computer portatile +Name[ja]=ラップトップ +Name[km]=កុំព្យួទ័រ​យួរដៃ +Name[ko]=랩탑 +Name[lv]=Laptops +Name[mk]=Лаптоп +Name[ms]=Komputer riba +Name[nds]=Klappreekner +Name[pt]=Portátil +Name[ru]=Батарея ноутбука +Name[sl]=Prenosnik +Name[sr]=Лаптоп +Name[sv]=Bärbar dator +Name[ta]= மடிக் கணினி +Name[tg]=Компютери Дастӣ +Name[th]=แลปทอป +Name[tr]=Dizüstü Bilgisayar +Name[uz@cyrillic]=Лаптоп +Name[ven]=Khomupwutha pfarwa +Name[wa]=Poirtåve +Name[xh]=Umphezulu osongiweyo +Name[zh_TW]=筆記型電腦 +Name[zu]=Ikhomputha eyisicaba ephathwayo +SortOrder=battery.desktop,bwarning.desktop,cwarning.desktop,power.desktop,pcmcia.desktop +Icon=laptop_settings +MiniIcon=laptop_settings + diff --git a/klaptopdaemon/applnk/Makefile.am b/klaptopdaemon/applnk/Makefile.am new file mode 100644 index 0000000..77274c7 --- /dev/null +++ b/klaptopdaemon/applnk/Makefile.am @@ -0,0 +1,4 @@ +xdg_apps_DATA = laptop.desktop pcmcia.desktop + +data3_DATA = klaptopdaemon.desktop +data3dir = $(kde_servicesdir)/kded diff --git a/klaptopdaemon/applnk/klaptopdaemon.desktop b/klaptopdaemon/applnk/klaptopdaemon.desktop new file mode 100644 index 0000000..0ba43cb --- /dev/null +++ b/klaptopdaemon/applnk/klaptopdaemon.desktop @@ -0,0 +1,116 @@ +[Desktop Entry] +Type=Service + +ServiceTypes=KDEDModule +X-KDE-ModuleType=Library +X-KDE-Library=klaptopdaemon +X-KDE-FactoryName=klaptopdaemon +X-KDE-Kded-autoload=false +X-KDE-Kded-load-on-demand=true + +Icon=laptop_battery +DocPath=kcontrol/battery-monitor.html +Comment=Laptop battery monitor +Comment[ar]=مراقب بطّاريّة الحاسوب المحمول +Comment[bg]=Мониторинг на батериите на лаптоп +Comment[bs]=Nadzor baterije laptopa +Comment[ca]=Monitor de bateria de portàtils +Comment[cs]=Monitor baterií laptopu +Comment[da]=Batteriovervågning for bærbar +Comment[de]=Benachrichtigung über den Akku-Ladezustand +Comment[el]=Επόπτης μπαταρίας φορητού +Comment[eo]=Portkomputila baterimonitoro +Comment[es]=Monitor de batería del portátil +Comment[et]=Sülearvuti aku monitooring +Comment[eu]=Magalekoaren bateria begiralea +Comment[fa]=نمایشگر باتری رایانۀ کیفی +Comment[fi]=Kannettavan koneen akkutarkkailja +Comment[fr]=Indicateur de batterie de portable +Comment[ga]=Monatóir chadhnra ríomhaire glúine +Comment[he]=מד סוללה למחשב ברכיים +Comment[hu]=A telepek szintjelzője +Comment[is]=Rafhlöðueftirlit fyrir ferðavélar +Comment[it]=Controllo batteria computer portatile +Comment[ja]=ラップトップバッテリモニタ +Comment[ka]=ლეპტოპის კვების ელემენტის მონიტორი +Comment[kk]=Ноутбук аккумуляторын бақылау +Comment[km]=កម្មវិធី​ត្រួតពិនិត្យ​ថ្ម​របស់​កុំព្យូទ័រ​យួរដៃ +Comment[lt]=Akumuliatoriaus stebėjimo priemonė +Comment[nb]=Batteriovervåker for bærbar maskin +Comment[nds]=Klappreekner-Batteriekieker +Comment[ne]=ल्यापटप ब्याट्री मोनिटर +Comment[nl]=Programma voor laptop-batterijbewaking +Comment[nn]=Batteriovervaking for bærbar maskin +Comment[pa]=ਲੈਪਟਾਪ ਬੈਟਰੀ ਨਿਗਰਾਨ +Comment[pl]=Kontrola stanu baterii laptopa +Comment[pt]=Monitor de bateria +Comment[pt_BR]=Monitor de bateria de laptop +Comment[ro]=Monitorează bateria laptop-ului +Comment[ru]=Монитор состояния батареи +Comment[sk]=Monitor nabitia bateriek +Comment[sl]=Nadzornik baterije za prenosnik +Comment[sr]=Надгледа батерију лаптопа +Comment[sr@Latn]=Nadgleda bateriju laptopa +Comment[sv]=Batterimonitor för bärbar dator +Comment[ta]= மடிக் கணினி மின்கலம் கண்காணிப்பாளன் +Comment[tr]=Dizüstü bilgisayarlar için pil izleyici +Comment[uk]=Монітор батарей лептопа +Comment[uz]=Laptopning batareyasini nazorat qilish +Comment[uz@cyrillic]=Лаптопнинг батареясини назорат қилиш +Comment[zh_CN]=便携电脑电池监视器 +Comment[zh_TW]=筆記型電腦電池監視器 +Name=Laptop Battery Monitor +Name[ar]=مراقب بطّاريّة الحاسوب المحمول +Name[bg]=Мониторинг на батериите +Name[bs]=Nadzor baterije laptopa +Name[ca]=Monitor de bateria de portàtils +Name[cs]=Monitor baterií laptopu +Name[cy]=Monitr Batri Gliniadur +Name[da]=Batteriovervågning for bærbar +Name[de]=Akku-Überwachung +Name[el]=Επόπτης μπαταρίας φορητού +Name[eo]=Portkomputila baterimonitoro +Name[es]=Monitor de batería del portátil +Name[et]=Sülearvuti aku monitooring +Name[eu]=Magalekoaren Bateria Begiralea +Name[fa]=نمایشگر باتری رایانۀ کیفی +Name[fi]=Akkutarkkailija +Name[fr]=Indicateur de batterie de portable +Name[ga]=Monatóir Chadhnra Ríomhaire Glúine +Name[he]=מד סוללה למחשב ברכיים +Name[hi]=लैपटॉप बैटरी मॉनीटर +Name[hu]=Feltöltöttségi szintjelző +Name[is]=Rafhlöðueftirlit fyrir ferðavélar +Name[it]=Controllo batteria portatile +Name[ja]=ラップトップバッテリモニタ +Name[ka]=ლეპტოპის კვების ელემენტის მონიტორი +Name[kk]=Ноутбук аккумуляторын бақылау +Name[km]=កម្មវិធី​ត្រួតពិនិត្យ​ថ្ម​កុំព្យូទ័រ​យួរដៃ +Name[lt]=Akumuliatoriaus stebėjimo priemonė +Name[mk]=Монитор на батеријата на лаптопот +Name[ms]=Memerhatikan Bateri Komputer Riba +Name[nb]=Batteriovervåker for bærbar maskin +Name[nds]=Klappreekner-Batteriekieker +Name[ne]=ल्यापटप ब्याट्री मोनिटर +Name[nl]=Laptop-batterijbewaking +Name[nn]=Batteriovervakar for bærbar maskin +Name[pa]=ਲੈਪਟਾਪ ਬੈਟਰੀ ਨਿਗਰਾਨ +Name[pl]=Monitor baterii +Name[pt]=Monitor de Bateria +Name[pt_BR]=Monitor de Bateria de Laptop +Name[ro]=Monitor baterie de laptop +Name[ru]=Состояние батареи +Name[sk]=Monitor nabitia bateriek +Name[sl]=Nadzornik baterije za prenosnik +Name[sr]=Надгледање батерије лаптопа +Name[sr@Latn]=Nadgledanje baterije laptopa +Name[sv]=Batterimonitor för bärbar dator +Name[ta]= மடிக் கணினி மின்கலம் கண்காணி +Name[tg]=Дидабони Батареяи Компютери Дастӣ +Name[tr]=Dizüstü Pil Monitörü +Name[uk]=Монітор батарей +Name[uz]=Laptopning batareyasini nazorat qilish +Name[uz@cyrillic]=Лаптопнинг батареясини назорат қилиш +Name[wa]=Corwaitoe del batreye do poirtåve +Name[zh_CN]=便携电脑电池监视器 +Name[zh_TW]=筆記型電腦電池監視器 diff --git a/klaptopdaemon/applnk/laptop.desktop b/klaptopdaemon/applnk/laptop.desktop new file mode 100644 index 0000000..5c4101c --- /dev/null +++ b/klaptopdaemon/applnk/laptop.desktop @@ -0,0 +1,135 @@ +[Desktop Entry] +X-KDE-Library=laptop +X-KDE-FactoryName=laptop +X-KDE-Init=laptop +Exec=kcmshell laptop +Icon=laptop_battery +Type=Application +DocPath=kcontrol/laptop/index.html +Categories=Qt;KDE;X-KDE-settings-power; +Comment=Laptop Battery +Comment[af]=Draagbare rekenaar Batery +Comment[ar]=بطّاريّة الحاسوب المحمول +Comment[bg]=Мониторинг на батериите на лаптоп +Comment[br]=Pod-tredan an hezoug +Comment[bs]=Upozorenje istrošene baterije +Comment[ca]=Bateria de portàtil +Comment[cs]=Baterie notebooku +Comment[cy]=Batri Gliniadur +Comment[da]=Batteri for bærbar +Comment[de]=Notebook-Akku +Comment[el]=Μπαταρία φορητού +Comment[eo]=Avertilo por maplenigo de la baterio +Comment[es]=Batería del portátil +Comment[et]=Sülearvuti aku +Comment[eu]=Magalekoen Bateria +Comment[fa]=باتری رایانۀ کیفی +Comment[fi]=Kannettavan akku +Comment[fr]=Batterie d'ordinateur portable +Comment[ga]=Cadhnra Ríomhaire Glúine +Comment[he]=סוללת מחשב נייד +Comment[hi]=लैपटॉप बैटरी +Comment[hr]=Baterija laptopa +Comment[hu]=Energiakezelési beállítások noteszgép esetén +Comment[is]=Rafhlaða ferðavélar +Comment[it]=Batteria computer portatile +Comment[ja]=ラップトップバッテリ +Comment[ka]=ლეპტოპის კვების ელემენტი +Comment[kk]=Ноутбуктің аккумуляторы +Comment[km]=ថ្ម​កុំព្យូទ័រ​យួរដៃ +Comment[lt]=Nešiojamo kompiuterio akumuliatorius +Comment[mk]=Предупредува кога батеријата е слаба +Comment[ms]=Bateri Komputer Riba +Comment[mt]=Batterija tal-laptop +Comment[nb]=Batteri til bærbar maskin +Comment[nds]=Klappreekner-Batterie +Comment[ne]=ल्यापटप ब्याट्री +Comment[nl]=Laptopbatterij +Comment[nn]=Batteri til bærbar +Comment[pa]=ਲੈਪਟਾਪ ਬੈਟਰੀ +Comment[pl]=Ostrzeżenie o słabych bateriach +Comment[pt]=Bateria do portátil +Comment[pt_BR]=Bateria do Laptop +Comment[ro]=Baterie de laptop +Comment[ru]=Батарея ноутбука +Comment[sk]=Batérie laptopu +Comment[sl]=Baterija prenosnika +Comment[sr]=Батерија лаптопа +Comment[sr@Latn]=Baterija laptopa +Comment[sv]=Batteri för bärbar dator +Comment[ta]= மடிக் கணினி மின்கலம் +Comment[tg]=Батареяи Компютери Дастӣ +Comment[th]=แบตเตอรีของเครื่องแลปทอบ +Comment[tr]=Dizüstü Pili +Comment[uk]=Батареї лептопа +Comment[uz]=Laptopning batareyasi +Comment[uz@cyrillic]=Лаптопнинг батареяси +Comment[wa]=Batreye do poirtåve +Comment[xh]=Ibhetri ye Laptop +Comment[zh_CN]=便携电脑电池 +Comment[zh_TW]=筆記型電腦的電池 +Comment[zu]=Ibhetri Yekhomputha eyisicaba ephathwayo +Name=Laptop Battery +Name[af]=Draagbare rekenaar Batery +Name[ar]=بطّاريّة الحاسوب المحمول +Name[bg]=Батерии на лаптоп +Name[br]=Pod-tredan an hezoug +Name[bs]=Laptop baterija +Name[ca]=Bateria de portàtil +Name[cs]=Baterie notebooku +Name[cy]=Batri Gliniadur +Name[da]=Batteri for bærbar +Name[de]=Notebook-Akku +Name[el]=Μπαταρία φορητού +Name[eo]=Portkomputila baterio +Name[es]=Batería del portátil +Name[et]=Sülearvuti aku +Name[eu]=Magalekoen Bateria +Name[fa]=باتری رایانۀ کیفی +Name[fi]=Kannettavan akku +Name[fr]=Batterie d'ordinateur portable +Name[ga]=Cadhnra Ríomhaire Glúine +Name[he]=סוללת מחשב נייד +Name[hi]=लैपटॉप बैटरी +Name[hr]=Laptop baterija +Name[hu]=Noteszgép-telepek +Name[is]=Ferðavélarafhlaða +Name[it]=Batteria computer portatile +Name[ja]=ラップトップバッテリ +Name[ka]=ლეპტოპის კვების ელემენტი +Name[kk]=Ноутбуктің аккумуляторы +Name[km]=ថ្ម​កុំព្យូទ័រ​យួរដៃ +Name[lt]=Laptop baterija +Name[mk]=Батерија на лаптопот +Name[ms]=Bateri Komputer Riba +Name[mt]=Batterija tal-laptop +Name[nb]=Batteri til bærbar maskin +Name[nds]=Klappreekner-Batterie +Name[ne]=ल्यापटप ब्याट्री +Name[nl]=Laptopbatterij +Name[nn]=Batteri til bærbar +Name[pa]=ਲੈਪਟਾਪ ਬੈਟਰੀ +Name[pl]=Bateria laptopa +Name[pt]=Bateria do Portátil +Name[pt_BR]=Bateria do Laptop +Name[ro]=Baterie laptop +Name[ru]=Батарея ноутбука +Name[sk]=Batérie laptopu +Name[sl]=Baterija prenosnika +Name[sr]=Батерија лаптопа +Name[sr@Latn]=Baterija laptopa +Name[sv]=Batteri för bärbar dator +Name[ta]= மடிக் கணினி மின்கலம் +Name[tg]=Батареяи Компютери Дастӣ +Name[th]=แบตเตอรีแลปทอบ +Name[tr]=Dizüstü Pili +Name[uk]=Батареї лептопа +Name[uz]=Laptopning batareyasi +Name[uz@cyrillic]=Лаптопнинг батареяси +Name[wa]=Batreye do poirtåve +Name[xh]=Ibhetri ye Laptop +Name[zh_CN]=便携电脑电池 +Name[zh_TW]=筆記型電腦的電池 +Name[zu]=Ibhetri Yekhomputha eyisicaba ephathwayo +Init=klaptop_check + diff --git a/klaptopdaemon/applnk/pcmcia.desktop b/klaptopdaemon/applnk/pcmcia.desktop new file mode 100644 index 0000000..0b1249a --- /dev/null +++ b/klaptopdaemon/applnk/pcmcia.desktop @@ -0,0 +1,84 @@ +[Desktop Entry] +X-KDE-ModuleType=Library +X-KDE-Library=laptop +X-KDE-FactoryName=pcmcia +Exec=kcmshell pcmcia +Icon=laptop_pcmcia +Type=Application +DocPath=kinfocenter/pcmcia/index.html +Comment=PCMCIA status +Comment[af]=Pcmcia status +Comment[ar]=حالة بطاقة PCMCIA +Comment[az]=PCMCIA vəziyyəti +Comment[bg]=Информация за PCMCIA +Comment[br]=Saviad PCMCIA +Comment[ca]=Estat de PCMCIA +Comment[cs]=Stav PCMCIA +Comment[cy]=Statws PCMCIA +Comment[da]=PCMCIA-status +Comment[de]=PCMCIA-Status +Comment[el]=Κατάσταση PCMCIA +Comment[eo]=PCMCIA-stato +Comment[es]=Estado PCMCIA +Comment[et]=PCMCIA olek +Comment[eu]=PCMCIAren egoera +Comment[fa]=PCMCIA وضعیت +Comment[fi]=PCMCIA-tila +Comment[fr]=État PCMCIA +Comment[ga]=Stádas PCMCIA +Comment[gl]=Estado de PCMCIA +Comment[he]=מידע על מצב PCMCIA +Comment[hi]=पीसीएमसीआईए स्थिति +Comment[hr]=Stanje PCMCIA +Comment[hu]=PCMCIA-állapot +Comment[id]=Status PCMCIA +Comment[is]=PCMCIA staða +Comment[it]=Stato PCMCIA +Comment[ja]=PCMCIA の状態 +Comment[ka]=PCMCIA სტატუსი +Comment[kk]=PCMCIA күйі +Comment[km]=ស្ថានភាព PCMCIA +Comment[ko]=PCMCIA 현재 상태 +Comment[lt]=PCMCIA būsena +Comment[mk]=Статус на PCMCIA +Comment[ms]=Status PCMCIA +Comment[mt]=Stat PCMCIA +Comment[nb]=PCMCIA-status +Comment[nds]=PCMCIA-Status +Comment[ne]=PCMCIA स्थिति +Comment[nl]=Status van PCMCIA +Comment[nn]=PCMCIA-status +Comment[pa]=PCMCIA ਹਾਲਤ +Comment[pl]=Status kart PCMCIA +Comment[pt]=Estado do PCMCIA +Comment[pt_BR]=Estado do PCMCIA +Comment[ro]=Starea PCMCIA +Comment[ru]=Состояние PCMCIA +Comment[sk]=stav PCMCIA +Comment[sl]=Stanje PCMCIA +Comment[sr]=Статус PCMCIA уређаја +Comment[sr@Latn]=Status PCMCIA uređaja +Comment[sv]=PCMCIA-status +Comment[ta]=PCMCIA நிலை +Comment[tg]=Ҳолати PCMCIA +Comment[th]=สถานะอุปกรณ์ PCMCIA +Comment[tr]=PCMCIA durumu +Comment[uk]=Стан PCMCIA +Comment[uz]=PCMCIA holati +Comment[uz@cyrillic]=PCMCIA ҳолати +Comment[ven]=Maimo a PCMCIA +Comment[vi]=Trạng thái PCMCIA +Comment[wa]=Estat do PCMCIA +Comment[xh]=Indawo esemthethweni ye PCMCIA +Comment[zh_CN]=PCMCIA 状态 +Comment[zh_TW]=PCMCIA 狀態 +Comment[zu]=Izinga le-PCMCIA +Name=PCMCIA +Name[af]=Pcmcia +Name[he]=מצב PCMCIA +Name[hi]=पीसीएमसीआईए +Name[pt_BR]=Cartões PCMCIA +Name[ta]= PCMCIA +Name[th]=อุปกรณ์ PCMCIA + +Categories=Qt;KDE;X-KDE-information; diff --git a/klaptopdaemon/battery.cpp b/klaptopdaemon/battery.cpp new file mode 100644 index 0000000..ef43890 --- /dev/null +++ b/klaptopdaemon/battery.cpp @@ -0,0 +1,390 @@ +/* + * battery.cpp + * + * Copyright (c) 1999 Paul Campbell + * Copyright (c) 2002 Marc Mutz + * Copyright (c) 2006 Flavio Castelli + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// my headers: +#include "battery.h" +#include "version.h" +#include "portable.h" + +// other KDE headers: +#include +#include +#include +#include +#include +#include +#include +#include + +// other Qt headers: +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern void wake_laptop_daemon(); + + +BatteryConfig::BatteryConfig (QWidget * parent, const char *name) + : KCModule(parent, name), + editPoll(0), + iconloader(0), + buttonNoBattery(0), + buttonNoCharge(0), + buttonCharge(0) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + apm = laptop_portable::has_power_management(); + config = new KConfig("kcmlaptoprc"); + instance = new KInstance("klaptopdaemon"); + + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + // do we show the monitor + runMonitor = new QCheckBox( i18n("&Show battery monitor"), this ); + top_layout->addWidget( runMonitor ); + QToolTip::add( runMonitor, i18n( "This box enables the battery state icon in the panel" ) ); + connect( runMonitor, SIGNAL(clicked()), this, SLOT(configChanged()) ); + connect( runMonitor, SIGNAL(clicked()), this, SLOT(runMonitorChanged()) ); + + // show also the battery level percentage + showLevel = new QCheckBox( i18n("Show battery level percentage"), this ); + top_layout->addWidget( showLevel ); + QToolTip::add( showLevel, i18n( "This box enables a text message near the battery state icon containing battery level percentage" ) ); + connect( showLevel, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + notifyMe = new QCheckBox( i18n("&Notify me whenever my battery becomes fully charged"), this ); + top_layout->addWidget( notifyMe ); + QToolTip::add( notifyMe, i18n( "This box enables a dialog box that pops up when your battery becomes fully charged" ) ); + connect( notifyMe, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + blankSaver = new QCheckBox( i18n("&Use a blank screen saver when running on battery"), this ); + top_layout->addWidget( blankSaver ); + connect( blankSaver, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + if (!apm) { + top_layout->addWidget( laptop_portable::no_power_management_explanation(this) ); + } else { + iconloader = new KIconLoader("klaptopdaemon"); + + // the poll time (in seconds) + QHBox *hb = new QHBox( this ); + hb->setSpacing( KDialog::spacingHint() ); + top_layout->addWidget( hb ); + + QLabel* poll_label = new QLabel( i18n("&Check status every:"), hb ); + editPoll = new QSpinBox( 1, 3600, 1, hb ); // min,max,step + QToolTip::add( editPoll, i18n( "Choose how responsive the laptop software will be when it checks the battery status" ) ); + editPoll->setSuffix( i18n("keep short, unit in spinbox", "sec") ); + poll_label->setBuddy( editPoll ); + connect( editPoll, SIGNAL(valueChanged(int)), + this, SLOT(configChanged()) ); + QWidget* spacer = new QWidget( hb ); + hb->setStretchFactor( spacer, 1 ); + + // group box to hold the icons together + QVGroupBox* icons_groupbox = new QVGroupBox( i18n("Select Battery Icons"), this ); + icons_groupbox->layout()->setSpacing( KDialog::spacingHint() ); + top_layout->addWidget( icons_groupbox, 0, Qt::AlignLeft ); + + // layout to hold the icons inside the groupbox + QGrid *icon_grid = new QGrid( 3 /*cols*/, icons_groupbox ); + icon_grid->setSpacing( KDialog::spacingHint() ); + + buttonNoBattery = new KIconButton( iconloader, icon_grid ); + buttonNoCharge = new KIconButton( iconloader, icon_grid ); + buttonCharge = new KIconButton( iconloader, icon_grid ); + (void)new QLabel( buttonNoBattery, i18n("No &battery"), icon_grid); + (void)new QLabel( buttonNoCharge, i18n("&Not charging"), icon_grid); + (void)new QLabel( buttonCharge, i18n("Char&ging"), icon_grid); + buttonNoBattery->setIconType( KIcon::NoGroup, KIcon::Any, 1); + buttonNoCharge->setIconType( KIcon::NoGroup, KIcon::Any, 1); + buttonCharge->setIconType( KIcon::NoGroup, KIcon::Any, 1); + connect(buttonNoBattery, SIGNAL(iconChanged(QString)), this, SLOT(iconChanged())); + connect(buttonNoCharge, SIGNAL(iconChanged(QString)), this, SLOT(iconChanged())); + connect(buttonCharge, SIGNAL(iconChanged(QString)), this, SLOT(configChanged())); + + + int num_batteries; + QStringList battery_names, battery_states, battery_values; + laptop_portable::get_battery_status(num_batteries, battery_names, battery_states, battery_values); + if (num_batteries > 0) { + QHBoxLayout *hl = new QHBoxLayout(); + top_layout->addLayout(hl); + + QHGroupBox *hb = new QHGroupBox(i18n("Current Battery Status"), this); + for (int i = 0; i < num_batteries; i++) { + + QWidget *wp; + if (num_batteries == 1) { + wp = new QWidget(hb); + } else { + wp = new QVGroupBox(battery_names[i], hb); + } + QVBoxLayout *vb = new QVBoxLayout(wp); + + QLabel *l; + + l = new QLabel(wp); // icon indicating state + vb->addWidget(l); + batt_label_1.append(l); + + l = new QLabel(QString(""), wp); + vb->addWidget(l); + batt_label_2.append(l); + + l = new QLabel(QString(""), wp); + vb->addWidget(l); + batt_label_3.append(l); + } + hl->addWidget(hb); + hl->addStretch(1); + (void)startTimer(30*1000); // update 2x every minute + } + + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + QLabel* explain = new KRichTextLabel( i18n("This panel controls whether the battery status monitor\nappears in the system tray and what it looks like.").replace("\n"," "), this); + top_layout->addWidget(explain, 0); + laptop_portable::extra_config(this, config, top_layout); + } + + top_layout->addStretch(1); + startMonitor = new QPushButton( i18n("&Start Battery Monitor"), this); + connect(startMonitor, SIGNAL(clicked()), this, SLOT(slotStartMonitor())); + top_layout->addWidget( startMonitor, 0, Qt::AlignRight ); + + load(); +} + +BatteryConfig::~BatteryConfig() +{ + delete instance; + delete config; +} + + +void BatteryConfig::save() +{ + enablemonitor = runMonitor->isChecked(); + showlevel = showLevel->isChecked(); + useblanksaver = blankSaver->isChecked(); + notifyme = notifyMe->isChecked(); + + if (apm) { + poll_time = editPoll->value(); + nobattery = buttonNoBattery->icon(); + chargebattery = buttonCharge->icon(); + nochargebattery = buttonNoCharge->icon(); + } + config->setGroup("BatteryDefault"); + + config->writeEntry("Enable", enablemonitor); + config->writeEntry("ShowLevel", showlevel); + config->writeEntry("NotifyMe", notifyme); + config->writeEntry("BlankSaver", useblanksaver); + config->writeEntry("Poll", poll_time); + config->writeEntry("NoBatteryPixmap", nobattery); + config->writeEntry("ChargePixmap", chargebattery); + config->writeEntry("NoChargePixmap", nochargebattery); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void BatteryConfig::load() +{ + load( false ); +} + +void BatteryConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + config->setGroup("BatteryDefault"); + + poll_time = config->readNumEntry("Poll", 20); + enablemonitor = config->readBoolEntry("Enable", true); + showlevel = config->readBoolEntry("ShowLevel", false); + notifyme = config->readBoolEntry("NotifyMe", false); + useblanksaver = config->readBoolEntry("BlankSaver", false); + + nobattery = config->readEntry("NoBatteryPixmap", "laptop_nobattery"); + nochargebattery = config->readEntry("NoChargePixmap", "laptop_nocharge"); + chargebattery = config->readEntry("ChargePixmap", "laptop_charge"); + + runMonitor->setChecked(enablemonitor); + showLevel->setChecked(showlevel); + blankSaver->setChecked(useblanksaver); + notifyMe->setChecked(notifyme); + if (apm) { + editPoll->setValue(poll_time); + buttonNoCharge->setIcon(nochargebattery); + buttonCharge->setIcon(chargebattery); + buttonNoBattery->setIcon(nobattery); + } + battery_pm = SmallIcon(nochargebattery, 20, KIcon::DefaultState, instance); + battery_nopm = SmallIcon(nobattery, 20, KIcon::DefaultState, instance); + emit changed(useDefaults); + BatteryStateUpdate(); +} + +void BatteryConfig::defaults() +{ + load( true ); +} + +void BatteryConfig::runMonitorChanged() +{ + showLevel->setEnabled (runMonitor->isChecked()); +} + +void BatteryConfig::configChanged() +{ + emit changed(true); +} + + +QString BatteryConfig::quickHelp() const +{ + return i18n("

Laptop Battery

This module allows you to monitor " + "your batteries. To make use of this module, you must have power management system software " + "installed. (And, of course, you should have batteries in your machine.)"); +} + + +void BatteryConfig::slotStartMonitor() +{ + wake_laptop_daemon(); + if (!enablemonitor) { + KMessageBox::information(0, i18n("The battery monitor has been started, but the tray icon is currently disabled. You can make it appear by selecting the Show battery monitor entry on this page and applying your changes."), QString::null, "howToEnableMonitor"); + } +} + +void +BatteryConfig::ConvertIcon(int percent, QPixmap &pm, QPixmap &result) +{ + QImage image = pm.convertToImage(); + + int w = image.width(); + int h = image.height(); + int count = 0; + QRgb rgb; + int x, y; + for (x = 0; x < w; x++) + for (y = 0; y < h; y++) { + rgb = image.pixel(x, y); + if (qRed(rgb) == 0xff && + qGreen(rgb) == 0xff && + qBlue(rgb) == 0xff) + count++; + } + int c = (count*percent)/100; + if (percent == 100) { + c = count; + } else + if (percent != 100 && c == count) + c = count-1; + + + if (c) { + uint ui; + QRgb blue = qRgb(0x00,0x00,0xff); + + if (image.depth() <= 8) { + ui = image.numColors(); // this fix thanks to Sven Krumpke + image.setNumColors(ui+1); + image.setColor(ui, blue); + } else { + ui = 0xff000000|blue; + } + + for (y = h-1; y >= 0; y--) + for (x = 0; x < w; x++) { + rgb = image.pixel(x, y); + if (qRed(rgb) == 0xff && + qGreen(rgb) == 0xff && + qBlue(rgb) == 0xff) { + image.setPixel(x, y, ui); + c--; + if (c <= 0) + goto quit; + } + } + } +quit: + + result.convertFromImage(image); +} + +void +BatteryConfig::BatteryStateUpdate() +{ + int num_batteries; + QStringList battery_names, battery_states, battery_values; + laptop_portable::get_battery_status(num_batteries, battery_names, battery_states, battery_values); + if (num_batteries > 0) { + for (int i = 0; i < num_batteries; i++) { + if (battery_states[i] == "yes") { + QPixmap result; + ConvertIcon(battery_values[i].toInt(), battery_pm, result); + batt_label_1.at(i)->setPixmap(result); + + batt_label_2.at(i)->setText(battery_values[i]+"%"); + + batt_label_3.at(i)->setText(i18n("Present")); + } else { + batt_label_1.at(i)->setPixmap(battery_nopm); + + batt_label_2.at(i)->setText(""); + + batt_label_3.at(i)->setText(i18n("Not present")); + } + } + } +} + +void BatteryConfig::iconChanged() +{ + nobattery = buttonNoBattery->icon(); + nochargebattery = buttonNoCharge->icon(); + battery_pm = SmallIcon(nochargebattery, 20, KIcon::DefaultState, instance); + battery_nopm = SmallIcon(nobattery, 20, KIcon::DefaultState, instance); + emit changed(true); + BatteryStateUpdate(); +} + +void BatteryConfig::timerEvent(QTimerEvent *) +{ + BatteryStateUpdate(); +} + +#include "battery.moc" + + diff --git a/klaptopdaemon/battery.h b/klaptopdaemon/battery.h new file mode 100644 index 0000000..3e484ef --- /dev/null +++ b/klaptopdaemon/battery.h @@ -0,0 +1,100 @@ +/* + * battery.h + * + * Copyright (c) 1999 Paul Campbell + * Copyright (c) 2002 Marc Mutz + * Copyright (c) 2006 Flavio Castelli + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __BATTERYCONFIG_H__ +#define __BATTERYCONFIG_H__ + +#include +#include +#include +#include + +class QWidget; +class QSpinBox; +class KConfig; +class QCheckBox; +class KIconLoader; +class KIconButton; +class QPushButton; +class QLabel; + + +class BatteryConfig : public KCModule +{ + Q_OBJECT +public: + BatteryConfig( QWidget *parent=0, const char* name=0); + ~BatteryConfig( ); + + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + void runMonitorChanged(); + void slotStartMonitor(); + void iconChanged(); + void BatteryStateUpdate(); + +private: + void timerEvent(QTimerEvent *); + void ConvertIcon(int percent, QPixmap &pm, QPixmap &result); + KConfig *config; + + QSpinBox* editPoll; + QCheckBox* runMonitor; + QCheckBox* showLevel; + QCheckBox* notifyMe; + QCheckBox* blankSaver; + bool enablemonitor; + bool showlevel; + bool enablequitmenu; + bool useblanksaver; + bool notifyme; + + KIconLoader *iconloader; + + KIconButton *buttonNoBattery; + KIconButton *buttonNoCharge; + KIconButton *buttonCharge; + QString nobattery, nochargebattery, chargebattery; + QPushButton *startMonitor; + bool apm; + int poll_time; + + QPtrList batt_label_1, batt_label_2, batt_label_3; + QPixmap battery_pm, battery_nopm; + + KInstance *instance; +}; + +#endif + diff --git a/klaptopdaemon/buttons.cpp b/klaptopdaemon/buttons.cpp new file mode 100644 index 0000000..f9ccce4 --- /dev/null +++ b/klaptopdaemon/buttons.cpp @@ -0,0 +1,620 @@ +/* + * buttons.cpp + * + * Copyright (c) 1999 Paul Campbell + * Copyright (c) 2002 Marc Mutz + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "buttons.h" +#include "portable.h" +#include "version.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +extern void wake_laptop_daemon(); + +ButtonsConfig::ButtonsConfig (QWidget * parent, const char *name) + : KCModule(parent, name), + lidBox(0), + lidStandby(0), + lidSuspend(0), + lidOff(0), + lidHibernate(0), + lidShutdown(0), + lidLogout(0), + lidBrightness(0), + lidValBrightness(0), + lidThrottle(0), + lidValThrottle(0), + lidPerformance(0), + lidValPerformance(0), + + powerBox(0), + powerStandby(0), + powerSuspend(0), + powerOff(0), + powerHibernate(0), + powerShutdown(0), + powerLogout(0), + powerBrightness(0), + powerValBrightness(0), + powerThrottle(0), + powerValThrottle(0), + powerPerformance(0), + powerValPerformance(0) +{ + int can_shutdown = 1; // fix me + int can_logout = 1; // fix me + + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + apm = laptop_portable::has_power_management(); + config = new KConfig("kcmlaptoprc"); + int can_brightness = laptop_portable::has_brightness(); + QStringList throttle_list; + int current_throttle; + bool *active_list; + bool has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + QStringList performance_list; + int current_performance; + bool has_performance = laptop_portable::get_system_performance(0, current_performance, performance_list, active_list); + + if (!apm && !can_brightness && !has_throttle && !has_performance) { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + + KActiveLabel* explain = laptop_portable::no_power_management_explanation(this); + top_layout->addWidget(explain); + + top_layout->addStretch(1); + } else { + int can_standby = laptop_portable::has_standby(); + int can_suspend = laptop_portable::has_suspend(); + int can_hibernate = laptop_portable::has_hibernation(); + + if (!can_standby && !can_suspend && !can_hibernate && !can_brightness && !has_throttle && !has_performance) + apm = 0; + if (!apm) { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + + QLabel* explain = laptop_portable::how_to_do_suspend_resume(this); + top_layout->addWidget(explain); + + top_layout->addStretch(1); + } else { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + QHBoxLayout *hlay = new QHBoxLayout( top_layout ); + + if (laptop_portable::has_button(laptop_portable::LidButton)) { + lidBox = new QVButtonGroup(i18n("Lid Switch Closed"), this); + lidBox->layout()->setSpacing( KDialog::spacingHint() ); + QToolTip::add( lidBox, i18n( "Select which actions will occur when the laptop's lid is closed" ) ); + hlay->addWidget( lidBox ); + + if (can_standby) { + lidStandby = new QRadioButton(i18n("Standb&y"), lidBox); + QToolTip::add( lidStandby, i18n( "Causes the laptop to move into the standby temporary low-power state" ) ); + } + if (can_suspend) { + lidSuspend = new QRadioButton(i18n("&Suspend"), lidBox); + QToolTip::add( lidSuspend, i18n( "Causes the laptop to move into the suspend 'save-to-ram' state" ) ); + } + if (can_hibernate) { + lidHibernate = new QRadioButton(i18n("H&ibernate"), lidBox); + QToolTip::add( lidHibernate, i18n( "Causes the laptop to move into the hibernate 'save-to-disk' state" ) ); + } + if (can_shutdown) { + lidShutdown = new QRadioButton(i18n("System power off"), lidBox); + QToolTip::add( lidShutdown, i18n( "Causes the laptop to power down" ) ); + } + if (can_logout) { + lidLogout = new QRadioButton(i18n("Logout"), lidBox); + QToolTip::add( lidShutdown, i18n( "Causes you to be logged out" ) ); + } + if (can_suspend||can_standby||can_hibernate||can_shutdown||can_logout) + lidOff = new QRadioButton(i18n("&Off"), lidBox); + if (can_brightness) { + lidBrightness = new QCheckBox(i18n("Brightness"), lidBox); + QToolTip::add( lidBrightness, i18n( "Causes the back panel brightness to be set" ) ); + QWidget *wp = new QWidget(lidBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + xl->addWidget(new QLabel("-", wp)); + lidValBrightness = new QSlider(0, 255, 16, 255, Qt::Horizontal, wp); + lidValBrightness->setEnabled(0); + QToolTip::add( lidValBrightness, i18n( "How bright the back panel will be set to" ) ); + connect (lidValBrightness, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + xl->addWidget(lidValBrightness); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } + if (has_performance) { + lidPerformance = new QCheckBox(i18n("System performance"), lidBox); + QToolTip::add( lidPerformance, i18n( "Causes the performance profile to be changed" ) ); + + QWidget *wp = new QWidget(lidBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + lidValPerformance = new KComboBox(0, wp); + QToolTip::add( lidValPerformance, i18n( "The performance profile to switch to" ) ); + lidValPerformance->insertStringList(performance_list); + lidValPerformance->setEnabled(0); + connect (lidValPerformance, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(lidValPerformance); + xl->addStretch(1); + } + if (has_throttle) { + lidThrottle = new QCheckBox(i18n("CPU throttle"), lidBox); + QToolTip::add( lidThrottle, i18n( "Causes the CPU to be throttled back" ) ); + + QWidget *wp = new QWidget(lidBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + lidValThrottle = new KComboBox(0, wp); + QToolTip::add( lidValThrottle, i18n( "How much to throttle back the CPU" ) ); + lidValThrottle->insertStringList(throttle_list); + lidValThrottle->setEnabled(0); + connect (lidValThrottle, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(lidValThrottle); + xl->addStretch(1); + + + } + connect(lidBox, SIGNAL(clicked(int)), this, SLOT(configChanged())); + } + + if (laptop_portable::has_button(laptop_portable::PowerButton)) { + + powerBox = new QVButtonGroup(i18n("Power Switch Pressed"), this); + powerBox->layout()->setSpacing( KDialog::spacingHint() ); + QToolTip::add( powerBox, i18n( "Select which actions will occur when the laptop's power button is pressed" ) ); + hlay->addWidget( powerBox ); + + if (can_standby) { + powerStandby = new QRadioButton(i18n("Sta&ndby"), powerBox); + QToolTip::add( powerStandby, i18n( "Causes the laptop to move into the standby temporary low-power state" ) ); + } + if (can_suspend) { + powerSuspend = new QRadioButton(i18n("S&uspend"), powerBox); + QToolTip::add( powerSuspend, i18n( "Causes the laptop to move into the suspend 'save-to-ram' state" ) ); + } + if (can_hibernate) { + powerHibernate = new QRadioButton(i18n("Hi&bernate"), powerBox); + QToolTip::add( powerHibernate, i18n( "Causes the laptop to move into the hibernate 'save-to-disk' state" ) ); + } + if (can_shutdown) { + powerShutdown = new QRadioButton(i18n("System power off"), powerBox); + QToolTip::add( powerShutdown, i18n( "Causes the laptop to power down" ) ); + } + if (can_logout) { + powerLogout = new QRadioButton(i18n("Logout"), powerBox); + QToolTip::add( powerShutdown, i18n( "Causes you to be logged out" ) ); + } + if (can_suspend||can_standby||can_hibernate||can_shutdown||can_logout) + powerOff = new QRadioButton(i18n("O&ff"), powerBox); + if (can_brightness) { + powerBrightness = new QCheckBox(i18n("Brightness"), powerBox); + QToolTip::add( powerBrightness, i18n( "Causes the back panel brightness to be set" ) ); + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + xl->addWidget(new QLabel("-", wp)); + powerValBrightness = new QSlider(0, 255, 16, 255, Qt::Horizontal, wp); + QToolTip::add( powerValBrightness, i18n( "How bright the back panel will be set to" ) ); + powerValBrightness->setEnabled(0); + connect (powerValBrightness, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + xl->addWidget(powerValBrightness); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } + if (has_performance) { + powerPerformance = new QCheckBox(i18n("System performance"), powerBox); + QToolTip::add( powerPerformance, i18n( "Causes the performance profile to be changed" ) ); + + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + powerValPerformance = new KComboBox(0, wp); + QToolTip::add( powerValPerformance, i18n( "The performance profile to switch to" ) ); + powerValPerformance->insertStringList(performance_list); + powerValPerformance->setEnabled(0); + connect (powerValPerformance, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(powerValPerformance); + xl->addStretch(1); + } + if (has_throttle) { + powerThrottle = new QCheckBox(i18n("CPU throttle"), powerBox); + QToolTip::add( powerThrottle, i18n( "Causes the CPU to be throttled back" ) ); + + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + powerValThrottle = new KComboBox(0, wp); + QToolTip::add( powerValThrottle, i18n( "How much to throttle back the CPU" ) ); + powerValThrottle->insertStringList(throttle_list); + powerValThrottle->setEnabled(0); + connect (powerValThrottle, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(powerValThrottle); + xl->addStretch(1); + } + connect(powerBox, SIGNAL(clicked(int)), this, SLOT(configChanged())); + } + + hlay->addStretch(1); + + QLabel* explain = new QLabel(i18n("This panel enables actions that are triggered when the lid closure switch " + "or power switch on your laptop is pressed. Some laptops may already " + "automatically do things like this, if you cannot disable them in your BIOS " + "you probably should not enable anything in this panel."), this); + explain->setAlignment( Qt::WordBreak ); + top_layout->addWidget(explain); + + top_layout->addStretch(1); + + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this ), 0, Qt::AlignRight ); + } + } + + load(); +} + +ButtonsConfig::~ButtonsConfig() +{ + delete config; +} + +void ButtonsConfig::save() +{ + power = getPower(); + lid = getLid(); + lid_bright_enabled = (lidBrightness?lidBrightness->isChecked():0); + power_bright_enabled = (powerBrightness?powerBrightness->isChecked():0); + lid_bright_val = (lidValBrightness?lidValBrightness->value():0); + power_bright_val = (powerValBrightness?powerValBrightness->value():0); + lid_performance_enabled = (lidPerformance?lidPerformance->isChecked():0); + power_performance_enabled = (powerPerformance?powerPerformance->isChecked():0); + lid_performance_val = (lidValPerformance?lidValPerformance->currentText():""); + power_performance_val = (powerValPerformance?powerValPerformance->currentText():""); + lid_throttle_enabled = (lidThrottle?lidThrottle->isChecked():0); + power_throttle_enabled = (powerThrottle?powerThrottle->isChecked():0); + lid_throttle_val = (lidValThrottle?lidValThrottle->currentText():""); + power_throttle_val = (powerValThrottle?powerValThrottle->currentText():""); + + config->setGroup("LaptopButtons"); + config->writeEntry("LidSuspend", lid); + config->writeEntry("PowerSuspend", power); + config->writeEntry("PowerBrightnessEnabled", power_bright_enabled); + config->writeEntry("LidBrightnessEnabled", lid_bright_enabled); + config->writeEntry("PowerBrightness", power_bright_val); + config->writeEntry("LidBrightness", lid_bright_val); + config->writeEntry("PowerPerformanceEnabled", power_performance_enabled); + config->writeEntry("LidPerformanceEnabled", lid_performance_enabled); + config->writeEntry("PowerPerformance", power_performance_val); + config->writeEntry("LidPerformance", lid_performance_val); + config->writeEntry("PowerThrottleEnabled", power_throttle_enabled); + config->writeEntry("LidThrottleEnabled", lid_throttle_enabled); + config->writeEntry("PowerThrottle", power_throttle_val); + config->writeEntry("LidThrottle", lid_throttle_val); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void ButtonsConfig::load() +{ + load( false ); +} + +void ButtonsConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + + config->setGroup("LaptopButtons"); + lid = config->readNumEntry("LidSuspend", 0); + power = config->readNumEntry("PowerSuspend", 0); + lid_bright_enabled = config->readBoolEntry("LidBrightnessEnabled", 0); + power_bright_enabled = config->readBoolEntry("PowerBrightnessEnabled", 0); + lid_bright_val = config->readNumEntry("LidBrightness", 0); + power_bright_val = config->readNumEntry("PowerBrightness", 0); + lid_performance_enabled = config->readBoolEntry("LidPerformanceEnabled", 0); + power_performance_enabled = config->readBoolEntry("PowerPerformanceEnabled", 0); + lid_performance_val = config->readEntry("LidPerformance", ""); + power_performance_val = config->readEntry("PowerPerformance", ""); + lid_throttle_enabled = config->readBoolEntry("LidThrottleEnabled", 0); + power_throttle_enabled = config->readBoolEntry("PowerThrottleEnabled", 0); + lid_throttle_val = config->readEntry("LidThrottle", ""); + power_throttle_val = config->readEntry("PowerThrottle", ""); + + // the GUI should reflect the real values + setPower(power, lid); + if (lidBrightness) + lidBrightness->setChecked(lid_bright_enabled); + if (powerBrightness) + powerBrightness->setChecked(power_bright_enabled); + if (lidValBrightness) { + lidValBrightness->setValue(lid_bright_val); + lidValBrightness->setEnabled(lid_bright_enabled); + } + if (powerValBrightness) { + powerValBrightness->setValue(power_bright_val); + powerValBrightness->setEnabled(power_bright_enabled); + } + if (lidPerformance) + lidPerformance->setChecked(lid_performance_enabled); + if (powerPerformance) + powerPerformance->setChecked(power_performance_enabled); + if (lidValPerformance) { + int ind = 0; + for (int i = 0; i < lidValPerformance->count(); i++) + if (lidValPerformance->text(i) == lid_performance_val) { + ind = i; + break; + } + lidValPerformance->setCurrentItem(ind); + lidValPerformance->setEnabled(lid_performance_enabled); + } + if (powerValPerformance) { + int ind = 0; + for (int i = 0; i < powerValPerformance->count(); i++) + if (powerValPerformance->text(i) == power_performance_val) { + ind = i; + break; + } + powerValPerformance->setCurrentItem(ind); + powerValPerformance->setEnabled(power_performance_enabled); + } + if (lidThrottle) + lidThrottle->setChecked(lid_throttle_enabled); + if (powerThrottle) + powerThrottle->setChecked(power_throttle_enabled); + if (lidValThrottle) { + int ind = 0; + for (int i = 0; i < lidValThrottle->count(); i++) + if (lidValThrottle->text(i) == lid_throttle_val) { + ind = i; + break; + } + lidValThrottle->setCurrentItem(ind); + lidValThrottle->setEnabled(lid_throttle_enabled); + } + if (powerValThrottle) { + int ind = 0; + for (int i = 0; i < powerValThrottle->count(); i++) + if (powerValThrottle->text(i) == power_throttle_val) { + ind = i; + break; + } + powerValThrottle->setCurrentItem(ind); + powerValThrottle->setEnabled(power_throttle_enabled); + } + emit changed( useDefaults ); +} + +void ButtonsConfig::defaults() +{ + setPower(0, 0); + lid_bright_enabled = 0; + power_bright_enabled = 0; + lid_bright_val = 0; + power_bright_val = 0; + lid_performance_enabled = 0; + power_performance_enabled = 0; + lid_performance_val = ""; + power_performance_val = ""; + lid_throttle_enabled = 0; + power_throttle_enabled = 0; + lid_throttle_val = ""; + power_throttle_val = ""; + if (lidBrightness) + lidBrightness->setChecked(lid_bright_enabled); + if (powerBrightness) + powerBrightness->setChecked(power_bright_enabled); + if (lidValBrightness) { + lidValBrightness->setValue(lid_bright_val); + lidValBrightness->setEnabled(lid_bright_enabled); + } + if (powerValBrightness) { + powerValBrightness->setValue(power_bright_val); + powerValBrightness->setEnabled(power_bright_enabled); + } + + + if (lidPerformance) + lidPerformance->setChecked(lid_performance_enabled); + if (powerPerformance) + powerPerformance->setChecked(power_performance_enabled); + if (lidValPerformance) { + lidValPerformance->setCurrentItem(0); + lidValPerformance->setEnabled(lid_performance_enabled); + } + if (powerValPerformance) { + powerValPerformance->setCurrentItem(0); + powerValPerformance->setEnabled(power_performance_enabled); + } + if (lidThrottle) + lidThrottle->setChecked(lid_throttle_enabled); + if (powerThrottle) + powerThrottle->setChecked(power_throttle_enabled); + if (lidValThrottle) { + lidValThrottle->setCurrentItem(0); + lidValThrottle->setEnabled(lid_throttle_enabled); + } + if (powerValThrottle) { + powerValThrottle->setCurrentItem(0); + powerValThrottle->setEnabled(power_throttle_enabled); + } +} + +int ButtonsConfig::getLid() +{ + if (!apm) + return(lid); + if (lidHibernate && lidHibernate->isChecked()) + return 3; + if (lidStandby && lidStandby->isChecked()) + return 1; + if (lidSuspend && lidSuspend->isChecked()) + return 2; + if (lidLogout && lidLogout->isChecked()) + return 4; + if (lidShutdown && lidShutdown->isChecked()) + return 5; + return(0); +} + +int ButtonsConfig::getPower() +{ + if (!apm) + return(power); + if (powerHibernate && powerHibernate->isChecked()) + return 3; + if (powerStandby && powerStandby->isChecked()) + return 1; + if (powerSuspend && powerSuspend->isChecked()) + return 2; + if (powerLogout && powerLogout->isChecked()) + return 4; + if (powerShutdown && powerShutdown->isChecked()) + return 5; + return(0); +} + +void ButtonsConfig::setPower(int p, int np) +{ + if (!apm) + return; + if (lidSuspend) { + lidSuspend->setChecked(FALSE); + } else { + if (np == 2) np = 0; + } + if (lidShutdown) { + lidShutdown->setChecked(FALSE); + } else { + if (np == 5) np = 0; + } + if (lidLogout) { + lidLogout->setChecked(FALSE); + } else { + if (np == 4) np = 0; + } + if (lidStandby) { + lidStandby->setChecked(FALSE); + } else { + if (np == 1) np = 0; + } + if (lidHibernate) { + lidHibernate->setChecked(FALSE); + } else { + if (np == 3) np = 0; + } + if (lidOff) + lidOff->setChecked(FALSE); + switch (np) { + case 0: if (lidOff) + lidOff->setChecked(TRUE); + break; + case 1: lidStandby->setChecked(TRUE);break; + case 2: lidSuspend->setChecked(TRUE);break; + case 3: lidHibernate->setChecked(TRUE);break; + case 4: lidLogout->setChecked(TRUE);break; + case 5: lidShutdown->setChecked(TRUE);break; + } + if (powerSuspend) { + powerSuspend->setChecked(FALSE); + } else { + if (p == 2) p = 0; + } + if (powerLogout) { + powerLogout->setChecked(FALSE); + } else { + if (p == 4) p = 0; + } + if (powerShutdown) { + powerShutdown->setChecked(FALSE); + } else { + if (p == 5) p = 0; + } + if (powerStandby) { + powerStandby->setChecked(FALSE); + } else { + if (p == 1) p = 0; + } + if (powerHibernate) { + powerHibernate->setChecked(FALSE); + } else { + if (p == 3) p = 0; + } + if (powerOff) + powerOff->setChecked(FALSE); + switch (p) { + case 0: if (powerOff) + powerOff->setChecked(TRUE); + break; + case 1: powerStandby->setChecked(TRUE);break; + case 2: powerSuspend->setChecked(TRUE);break; + case 3: powerHibernate->setChecked(TRUE);break; + case 4: powerLogout->setChecked(TRUE);break; + case 5: powerShutdown->setChecked(TRUE);break; + } +} + + + +void ButtonsConfig::configChanged() +{ + if (powerBrightness) + powerValBrightness->setEnabled(powerBrightness->isChecked()); + if (lidBrightness) + lidValBrightness->setEnabled(lidBrightness->isChecked()); + + if (powerPerformance) + powerValPerformance->setEnabled(powerPerformance->isChecked()); + if (lidPerformance) + lidValPerformance->setEnabled(lidPerformance->isChecked()); + + if (powerThrottle) + powerValThrottle->setEnabled(powerThrottle->isChecked()); + if (lidThrottle) + lidValThrottle->setEnabled(lidThrottle->isChecked()); + + emit changed(true); +} + + +QString ButtonsConfig::quickHelp() const +{ + return i18n("

Laptop Power Control

This module allows you to " + "configure the power switch or lid closure switch on your laptop " + "so they can trigger system actions"); + +} + +#include "buttons.moc" diff --git a/klaptopdaemon/buttons.h b/klaptopdaemon/buttons.h new file mode 100644 index 0000000..5abd088 --- /dev/null +++ b/klaptopdaemon/buttons.h @@ -0,0 +1,92 @@ +/* + * pcmcia.h + * + * Copyright (c) 1999 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __BUTTONSCONFIG_H__ +#define __BUTTONSCONFIG_H__ + +#include +#include + +class QWidget; +class QSlider; +class QButtonGroup; +class QRadioButton; +class QSpinBox; +class KConfig; +class QCheckBox; +class KComboBox; + +class ButtonsConfig : public KCModule +{ + Q_OBJECT +public: + ButtonsConfig( QWidget *parent=0, const char* name=0); + ~ButtonsConfig(); + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + + +private: + + int getPower(); + int getLid(); + void setPower( int, int ); + + QButtonGroup *lidBox; + QRadioButton *lidStandby, *lidSuspend, *lidOff, *lidHibernate, *lidShutdown, *lidLogout; + QCheckBox *lidBrightness; + QSlider *lidValBrightness; + QCheckBox *lidThrottle; + KComboBox *lidValThrottle; + QCheckBox *lidPerformance; + KComboBox *lidValPerformance; + QButtonGroup *powerBox; + QRadioButton *powerStandby, *powerSuspend, *powerOff, *powerHibernate, *powerShutdown, *powerLogout; + QCheckBox *powerBrightness; + QSlider *powerValBrightness; + QCheckBox *powerThrottle; + KComboBox *powerValThrottle; + QCheckBox *powerPerformance; + KComboBox *powerValPerformance; + int power_bright_val, lid_bright_val; + bool lid_bright_enabled, power_bright_enabled; + bool lid_throttle_enabled, power_throttle_enabled; + QString lid_throttle_val, power_throttle_val; + bool lid_performance_enabled, power_performance_enabled; + QString lid_performance_val, power_performance_val; + + KConfig *config; + int power, lid, apm; +}; + +#endif + diff --git a/klaptopdaemon/checkcrc.h b/klaptopdaemon/checkcrc.h new file mode 100644 index 0000000..149f28b --- /dev/null +++ b/klaptopdaemon/checkcrc.h @@ -0,0 +1,53 @@ +/* + * checkcrc.h + * + * Copyright (c) 2003 Paul Campbell + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CHECKCRC_H_ +#define _CHECKCRC_H_ + + + +#include +#include + +static void +checkcrc(const char *name, unsigned long &len_res, unsigned long &crc_res) +{ + unsigned long crc = ::crc32(0L, Z_NULL, 0); + unsigned long len = 0; + + FILE *f = ::fopen(name, "r"); + if (f) { + unsigned char buffer[1024]; + for (;;) { + int l = ::fread(buffer, 1, sizeof(buffer), f); + if (l <= 0) + break; + len += l; + crc = ::crc32(crc, buffer, l); + } + ::fclose(f); + } + crc_res = crc; + len_res = len; +} + +#endif diff --git a/klaptopdaemon/configure.in.bot b/klaptopdaemon/configure.in.bot new file mode 100644 index 0000000..51630ed --- /dev/null +++ b/klaptopdaemon/configure.in.bot @@ -0,0 +1,9 @@ +if test -z "$TPCTL"; then + echo "" + echo "You're missing tpctl. If you're using a ThinkPad, you may miss" + echo "some functionality of klaptopdaemon." + echo "You can get them from http://tpctl.sourceforge.net/tpctlhome.htm" + echo "" + all_tests=bad +fi + diff --git a/klaptopdaemon/configure.in.in b/klaptopdaemon/configure.in.in new file mode 100644 index 0000000..c1c5427 --- /dev/null +++ b/klaptopdaemon/configure.in.in @@ -0,0 +1,49 @@ +KDE_FIND_PATH(tpctl, TPCTL, [$exec_prefix/bin $prefix/bin /usr/bin /usr/local/bin /opt/local/bin], [TPCTL=""]) +AC_DEFINE_UNQUOTED(PATH_TPCTL, "$TPCTL", [Defines the executable of tpctl]) + +AC_CHECK_HEADERS(machine/apm_bios.h) + +if test "x$kde_use_qt_mac" = "xyes"; then + DO_NOT_COMPILE="$DO_NOT_COMPILE klaptopdaemon" +fi + + +xss_save_ldflags="$LDFLAGS" +LDFLAGS="$X_LDFLAGS" + +LIB_XSS= + +AC_ARG_WITH([xscreensaver], + AC_HELP_STRING([--without-xscreensaver], [Disable XScreenSaver support (default: check)]) ) + +if test "x$with_xscreensaver" != "xno"; then + KDE_CHECK_HEADER(X11/extensions/scrnsaver.h, + [ + AC_CHECK_LIB(Xext,XScreenSaverQueryInfo, + [ + AC_DEFINE(HAVE_XSCREENSAVER, 1, [Define if you have the XScreenSaver extension]) + LIB_XSS="-lXext" + ], + [ + ld_shared_flag= + xss_save_cxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" + KDE_CHECK_COMPILER_FLAG(shared, [ld_shared_flag="-shared"]) + AC_CHECK_LIB(Xss,XScreenSaverQueryInfo, + [ + AC_DEFINE(HAVE_XSCREENSAVER, 1, [Define if you have the XScreenSaver extension]) + LIB_XSS="-lXss" + ], + [], + [ $ld_shared_flag $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS ]) + CXXFLAGS="$xss_save_cxxflags" + ], + [ $X_PRE_LIBS -lX11 $X_EXTRA_LIBS ]) + ], [], + [ + #include + ] ) +fi + +AC_SUBST(LIB_XSS) +LDFLAGS="$xss_save_ldflags" diff --git a/klaptopdaemon/daemon_state.cpp b/klaptopdaemon/daemon_state.cpp new file mode 100644 index 0000000..5ca0d28 --- /dev/null +++ b/klaptopdaemon/daemon_state.cpp @@ -0,0 +1,282 @@ +/* + * daemon_state.cpp + * Copyright (C) 1999, 2003 Paul Campbell + * + * this replaces kcmlaptop - there are 2 parts - one is the panels that + * put the setup configuration in the "kcmlaptop" configm, the other + * is the laptop_daemon (this guy) who watches the battery state + * and does stuff as a result + * + * This file contains the implementation of the main laptop battery monitoring daemon + * + * $Id$ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include + +#include +#include +#include +#include "daemon_state.h" +#include "portable.h" +#include +#include +#include +#include +#include +#include +#include + + +#include +#include + +daemon_state::daemon_state() +{ + exists = laptop_portable::has_power_management(); + has_brightness = laptop_portable::has_brightness(); + QStringList profile_list; + int current_profile; + bool *active_list; + has_performance = laptop_portable::get_system_performance(0, current_profile, profile_list, active_list); + QStringList throttle_list; + int current_throttle; + has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + +} + +daemon_state::~daemon_state() +{ +} + +void daemon_state::load() +{ + KConfig *config = new KConfig("kcmlaptoprc"); + + if (config == 0) { + ::fprintf(stderr, "laptop_daemon: can't open kcmlaptop config files\n"); + ::exit(2); + } + + + // acpi settings + config->setGroup("AcpiDefault"); + bool enablestandby = config->readBoolEntry("EnableStandby", false); + bool enablesuspend = config->readBoolEntry("EnableSuspend", false); + bool enablehibernate = config->readBoolEntry("EnableHibernate", false); + bool enableperformance = config->readBoolEntry("EnablePerformance", false); + bool enablethrottle = config->readBoolEntry("EnableThrottle", false); + laptop_portable::acpi_set_mask(enablestandby, enablesuspend, enablehibernate, enableperformance, enablethrottle); + + config->setGroup("ApmDefault"); + enablestandby = config->readBoolEntry("EnableStandby", false); + enablesuspend = config->readBoolEntry("EnableSuspend", false); + laptop_portable::apm_set_mask(enablestandby, enablesuspend); + + config->setGroup("SoftwareSuspendDefault"); + enablehibernate = config->readBoolEntry("EnableHibernate", false); + laptop_portable::software_suspend_set_mask(enablehibernate); + + exists = laptop_portable::has_power_management(); + has_brightness = laptop_portable::has_brightness(); + QStringList profile_list; + int current_profile; + bool *active_list; + has_performance = laptop_portable::get_system_performance(0, current_profile, profile_list, active_list); + QStringList throttle_list; + int current_throttle; + has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + + bool can_suspend = laptop_portable::has_suspend(); + bool can_hibernate = laptop_portable::has_hibernation(); + bool can_standby = laptop_portable::has_standby(); + + // power control settings + config->setGroup("LaptopPower"); + power_action[0] = config->readNumEntry("PowerSuspend", 0); + switch (power_action[0]) { + case 1: if (!can_standby) power_action[0] = 0; break; + case 2: if (!can_suspend) power_action[0] = 0; break; + case 3: if (!can_hibernate) power_action[0] = 0; break; + } + power_action[1] = config->readNumEntry("NoPowerSuspend", 1); + switch (power_action[1]) { + case 1: if (!can_standby) power_action[1] = 0; break; + case 2: if (!can_suspend) power_action[1] = 0; break; + case 3: if (!can_hibernate) power_action[1] = 0; break; + } + power_brightness_enabled[0] = config->readBoolEntry("PowerBrightnessEnabled", 0)&has_brightness; + power_brightness_enabled[1] = config->readBoolEntry("NoPowerBrightnessEnabled", 0)&has_brightness; + power_brightness[0] = config->readNumEntry("PowerBrightness", 255); + power_brightness[1] = config->readNumEntry("NoPowerBrightness", 0); + power_performance_enabled[0] = config->readBoolEntry("PowerPerformanceEnabled", 0)&has_performance; + power_performance_enabled[1] = config->readBoolEntry("NoPowerPerformanceEnabled", 0)&has_performance; + power_performance[0] = config->readEntry("PowerPerformance", ""); + power_performance[1] = config->readEntry("NoPowerPerformance", ""); + power_throttle_enabled[0] = config->readBoolEntry("PowerThrottleEnabled", 0)&has_throttle; + power_throttle_enabled[1] = config->readBoolEntry("NoPowerThrottleEnabled", 0)&has_throttle; + power_throttle[0] = config->readEntry("PowerThrottle", ""); + power_throttle[1] = config->readEntry("NoPowerThrottle", ""); + power_wait[0] = 60*config->readNumEntry("PowerWait", 20); + power_wait[1] = 60*config->readNumEntry("NoPowerWait", 5); + lav_enabled[0] = config->readBoolEntry("LavEnabled", 0); + lav_enabled[1] = config->readBoolEntry("NoLavEnabled", 0); + lav_val[0] = config->readDoubleNumEntry("PowerLav", -1); + lav_val[1] = config->readDoubleNumEntry("NoPowerLav", -1); + + // General settings + config->setGroup("BatteryDefault"); + poll = config->readNumEntry("Poll", 20); + enabled = config->readBoolEntry("Enable", true)&exists; + notifyMeWhenFull = config->readBoolEntry("NotifyMe", false)&exists; + useBlankSaver = config->readBoolEntry("BlankSaver", false); + noBatteryIcon = config->readEntry("NoBatteryPixmap", "laptop_nobattery"); + noChargeIcon = config->readEntry("NoChargePixmap", "laptop_nocharge"); + chargeIcon = config->readEntry("ChargePixmap", "laptop_charge"); + + + config->setGroup("BatteryLow"); + time_based_action_low = config->readBoolEntry("TimeBasedAction", true); + low[0] = config->readNumEntry("LowValTime", 15); + low[1] = config->readNumEntry("LowValPercent", 7); + runCommand[0] = config->readBoolEntry("RunCommand", false)&exists; + runCommandPath[0] = config->readEntry("RunCommandPath"); + playSound[0] = config->readBoolEntry("PlaySound", false)&exists; + playSoundPath[0] = config->readEntry("PlaySoundPath"); + systemBeep[0] = config->readBoolEntry("SystemBeep", true)&exists; + logout[0] = config->readBoolEntry("Logout", false)&exists; + shutdown[0] = config->readBoolEntry("Shutdown", false)&exists; + notify[0] = config->readBoolEntry("Notify", true)&exists; + do_hibernate[0] = config->readBoolEntry("Hibernate", false)&can_hibernate&exists; + do_suspend[0] = config->readBoolEntry("Suspend", false)&can_suspend&exists; + do_standby[0] = config->readBoolEntry("Standby", false)&can_standby&exists; + do_brightness[0] = config->readBoolEntry("Brightness", false)&has_brightness&exists; + val_brightness[0] = config->readNumEntry("BrightnessValue", 0); + do_performance[0] = config->readBoolEntry("Performance", false)&has_performance&exists; + val_performance[0] = config->readEntry("PerformanceValue", ""); + do_throttle[0] = config->readBoolEntry("Throttle", false)&has_throttle&exists; + val_throttle[0] = config->readEntry("ThrottleValue", ""); + have_time = config->readNumEntry("HaveTime", 2); + + if (!have_time && laptop_portable::has_battery_time()) + have_time = 1; + + config->setGroup("BatteryCritical"); + time_based_action_critical = config->readBoolEntry("TimeBasedAction", true); + low[2] = config->readNumEntry("CriticalValTime", 5); + low[3] = config->readNumEntry("CriticalValPercent", 3); + runCommand[1] = config->readBoolEntry("RunCommand", false)&exists; + runCommandPath[1] = config->readEntry("RunCommandPath"); + playSound[1] = config->readBoolEntry("PlaySound", false)&exists; + playSoundPath[1] = config->readEntry("PlaySoundPath"); + systemBeep[1] = config->readBoolEntry("SystemBeep", true)&exists; + logout[1] = config->readBoolEntry("Logout", false)&exists; + shutdown[1] = config->readBoolEntry("Shutdown", false)&exists; + notify[1] = config->readBoolEntry("Notify", (can_suspend?false:true))&exists; + do_hibernate[1] = config->readBoolEntry("Hibernate", false)&can_hibernate&exists; + do_suspend[1] = config->readBoolEntry("Suspend", (can_suspend?true:false))&can_suspend&exists; + do_standby[1] = config->readBoolEntry("Standby", false)&can_standby&exists; + do_brightness[1] = config->readBoolEntry("Brightness", false)&has_brightness&exists; + val_brightness[1] = config->readNumEntry("BrightnessValue", 0); + do_performance[1] = config->readBoolEntry("Performance", false)&has_performance&exists; + val_performance[1] = config->readEntry("PerformanceValue", ""); + do_throttle[1] = config->readBoolEntry("Throttle", false)&has_throttle&exists; + val_throttle[1] = config->readEntry("ThrottleValue", ""); + + config->setGroup("ProfileDefault"); + bright_pon = config->readBoolEntry("EnableBrightnessOn", false)&has_brightness; + bright_poff = config->readBoolEntry("EnableBrightnessOff", false)&has_brightness; + performance_pon = config->readBoolEntry("EnablePerformanceOn", false)&has_performance; + performance_poff = config->readBoolEntry("EnablePerformanceOff", false)&has_performance; + throttle_pon = config->readBoolEntry("EnableThrottleOn", false)&has_throttle; + throttle_poff = config->readBoolEntry("EnableThrottleOff", false)&has_throttle; + bright_son = config->readNumEntry("BrightnessOnLevel", 255); + bright_soff = config->readNumEntry("BrightnessOffLevel", 160); + performance_val_on = config->readEntry("PerformanceOnLevel", ""); + performance_val_off = config->readEntry("PerformanceOffLevel", ""); + throttle_val_on = config->readEntry("ThrottleOnLevel", ""); + throttle_val_off = config->readEntry("ThrottleOffLevel", ""); + + config->setGroup("LaptopButtons"); + enable_lid_button = laptop_portable::has_button(laptop_portable::LidButton); + enable_power_button = laptop_portable::has_button(laptop_portable::PowerButton); + button_lid = (enable_lid_button?config->readNumEntry("LidSuspend", 0):0); + if (!enable_lid_button) { + button_lid = 0; + } else + switch (button_lid) { + case 1: if (!can_standby) button_lid = 0; break; + case 2: if (!can_suspend) button_lid = 0; break; + case 3: if (!can_hibernate) button_lid = 0; break; + } + button_power = (enable_power_button?config->readNumEntry("PowerSuspend", 0):0); + if (!enable_power_button) { + button_power = 0; + } else + switch (button_power) { + case 1: if (!can_standby) button_power = 0; break; + case 2: if (!can_suspend) button_power = 0; break; + case 3: if (!can_hibernate) button_power = 0; break; + } + button_lid_bright_enabled = config->readBoolEntry("LidBrightnessEnabled", 0)&enable_lid_button&has_brightness; + button_power_bright_enabled = config->readBoolEntry("PowerBrightnessEnabled", 0)&enable_power_button&has_brightness; + button_lid_bright_val = config->readNumEntry("LidBrightness", 0); + button_power_bright_val = config->readNumEntry("PowerBrightness", 0); + button_lid_performance_enabled = config->readBoolEntry("LidPerformanceEnabled", 0)&enable_lid_button&has_performance; + button_power_performance_enabled = config->readBoolEntry("PowerPerformanceEnabled", 0)&enable_power_button&has_performance; + button_lid_performance_val = config->readEntry("LidPerformance", ""); + button_power_performance_val = config->readEntry("PowerPerformance", ""); + button_lid_throttle_enabled = config->readBoolEntry("LidThrottleEnabled", 0)&enable_lid_button&has_throttle; + button_power_throttle_enabled = config->readBoolEntry("PowerThrottleEnabled", 0)&enable_power_button&has_throttle; + button_lid_throttle_val = config->readEntry("LidThrottle", ""); + button_power_throttle_val = config->readEntry("PowerThrottle", ""); + + config->setGroup("SonyDefault"); + sony_enablescrollbar = config->readBoolEntry("EnableScrollBar", false); + sony_middleemulation = config->readBoolEntry("EnableMiddleEmulation", false); + + delete config; +} + +bool +daemon_state::need_to_run() +{ + // + // look for reasons NOT to run the daemon + // + if (!exists) + return(0); + if (!enabled && !notifyMeWhenFull && + !runCommand[0] && !playSound[0] && !systemBeep[0] && !notify[0] && !do_suspend[0] && + !do_standby[0] && !logout[0] && !shutdown[0] && !do_hibernate[0] && + !runCommand[1] && !playSound[1] && !systemBeep[1] && !notify[1] && !do_suspend[1] && + !do_standby[1] && !logout[1] && !shutdown[1] && !do_hibernate[0] && + !sony_enablescrollbar && !sony_middleemulation && !do_brightness[0] && !do_brightness[1] && + button_lid==0 && button_power==0 && !button_lid_bright_enabled && !button_power_bright_enabled && + !button_lid_performance_enabled && !button_power_performance_enabled && !button_lid_throttle_enabled && !button_power_throttle_enabled && + !do_performance[0] && !do_performance[1] && !do_throttle[0] && !do_throttle[1] && + !bright_pon && !bright_poff && !performance_pon && !performance_poff && !throttle_pon && !throttle_poff && + !power_brightness_enabled[0] && !power_brightness_enabled[0] && + !power_performance_enabled[0] && !power_performance_enabled[1] && !power_throttle_enabled[0] && !power_throttle_enabled[1] && + power_action[0] == 0 && power_action[1] == 0) // if no reason to be running quit + return(0); + return(1); +} + diff --git a/klaptopdaemon/daemon_state.h b/klaptopdaemon/daemon_state.h new file mode 100644 index 0000000..6da4e73 --- /dev/null +++ b/klaptopdaemon/daemon_state.h @@ -0,0 +1,141 @@ +#ifndef __DAEMON_STATE_H +#define __DAEMON_STATE_H 1 +/* + * daemon_state.h + * Copyright (C) 1999, 2003 Paul Campbell + * + * This file contains the saved config state for the laptop daemon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +class KDE_EXPORT daemon_state +{ +public: + daemon_state(); + ~daemon_state(); + void load(); + bool need_to_run(); + + bool exists; + bool has_brightness; + bool has_performance; + bool has_throttle; + + QString noBatteryIcon; + QString chargeIcon; + QString noChargeIcon; + + // + // power out actions + // + + int power_wait[2]; // how close to the end when we trigger the action + int power_action[2]; // what to do when this action is triggered + int power_brightness[2]; // which brightness level to switch to + bool power_brightness_enabled[2]; // and whether to switch + QString power_performance[2]; // which performance level to switch to + bool power_performance_enabled[2]; // and whether to switch + QString power_throttle[2]; // which throttling level to switch to + bool power_throttle_enabled[2]; // and whether to switch + bool lav_enabled[2]; // check LAV first + float lav_val[2]; // don't act if higher than this + + // + // power out warnings + // + + bool systemBeep[2]; + bool logout[2]; + bool shutdown[2]; + bool runCommand[2]; + QString runCommandPath[2]; + bool playSound[2]; + QString playSoundPath[2]; + bool notify[2]; + bool do_suspend[2]; + bool do_hibernate[2]; + bool do_standby[2]; + bool do_brightness[2]; + int val_brightness[2]; + bool do_performance[2]; + QString val_performance[2]; + bool do_throttle[2]; + QString val_throttle[2]; + bool time_based_action_low, time_based_action_critical; + int low[4]; + int poll; // how often to pol + + + + bool enabled; + bool notifyMeWhenFull; + bool useBlankSaver; + + + int have_time; + + // sony jog-bar support + + bool sony_enablescrollbar; // enable jog bar support + bool sony_middleemulation; // press on jog bar emulates mouse middle button + + // brightness + + bool bright_pon; // auto set brightness when powered + int bright_son; // value to set + bool bright_poff; // auto set brightness when on battery + int bright_soff; // value to set + + // performance + + bool performance_pon, performance_poff; + QString performance_val_on, performance_val_off; + + // throttle + + bool throttle_pon, throttle_poff; + QString throttle_val_on, throttle_val_off; + + // button triggered stuff + int button_lid; + int button_power; + bool button_lid_bright_enabled; + bool button_power_bright_enabled; + int button_lid_bright_val; + int button_power_bright_val; + bool button_lid_performance_enabled; + bool button_power_performance_enabled; + QString button_lid_performance_val; + QString button_power_performance_val; + bool button_lid_throttle_enabled; + bool button_power_throttle_enabled; + QString button_lid_throttle_val; + QString button_power_throttle_val; + bool enable_lid_button; + bool enable_power_button; + +}; +#endif diff --git a/klaptopdaemon/daemondock.cpp b/klaptopdaemon/daemondock.cpp new file mode 100644 index 0000000..3551931 --- /dev/null +++ b/klaptopdaemon/daemondock.cpp @@ -0,0 +1,756 @@ +/* + * daemondock.cpp + * Copyright (C) 1999 Paul Campbell + * Copyright (C) 2006 Flavio Castelli + * + * This file contains the docked widget for the laptop battery monitor + * + * $Id$ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include "kpcmciainfo.h" +#include "daemondock.h" +#include "portable.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern void wake_laptop_daemon(); + +laptop_dock::laptop_dock( laptop_daemon* parent ) + : KSystemTray() +{ + setCaption(i18n("KLaptop Daemon")); + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + _pcmcia = NULL; + pdaemon = parent; + current_code = -1; + brightness_widget = 0; + instance = new KInstance("klaptopdaemon"); + // popup menu for right mouse button + rightPopup = contextMenu(); + SetupPopup(); +} + +void +laptop_dock::SetupPopup() +{ + rightPopup->clear(); + rightPopup->insertTitle(SmallIcon("laptop_battery"), "KLaptop", 999); // otherwise we look like KDED + + int has_brightness = laptop_portable::has_brightness(); + int can_standby = laptop_portable::has_standby(); + int can_suspend = laptop_portable::has_suspend(); + int can_hibernate = laptop_portable::has_hibernation(); + QStringList profile_list; + int current_profile; + bool *active_list; + bool has_performance = laptop_portable::get_system_performance(0, current_profile, profile_list, active_list); + QStringList throttle_list; + int current_throttle; + bool has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + rightPopup->insertItem(SmallIcon("configure"), i18n("&Configure KLaptop..."), this, SLOT(invokeSetup())); + + if (has_brightness) + rightPopup->insertItem(i18n("Screen Brightness..."), this, SLOT(invokeBrightness())); + if (has_performance) { + performance_popup = new QPopupMenu(0, "performance"); + performance_popup->setCheckable(1); + rightPopup->insertItem(i18n("Performance Profile..."), performance_popup); + connect( performance_popup, SIGNAL( activated( int ) ), this, SLOT( activate_performance( int ) ) ); + connect( performance_popup, SIGNAL( aboutToShow() ), this, SLOT( fill_performance() ) ); + } else { + performance_popup = 0; + } + if (has_throttle) { + throttle_popup = new QPopupMenu(0, "throttle"); + throttle_popup->setCheckable(1); + rightPopup->insertItem(i18n("CPU Throttling..."), throttle_popup); + connect( throttle_popup, SIGNAL( activated( int ) ), this, SLOT( activate_throttle( int ) ) ); + connect( throttle_popup, SIGNAL( aboutToShow() ), this, SLOT( fill_throttle() ) ); + } else { + throttle_popup = 0; + } + + if (can_standby || can_suspend || can_hibernate) { + rightPopup->insertSeparator(); + if (can_standby) rightPopup->insertItem(i18n("Standby..."), this, SLOT(invokeStandby())); + if (can_suspend) rightPopup->insertItem(i18n("&Lock && Suspend..."), this, SLOT(invokeLockSuspend())); + if (can_suspend) rightPopup->insertItem(i18n("&Suspend..."), this, SLOT(invokeSuspend())); + if (can_hibernate) rightPopup->insertItem(i18n("&Lock && Hibernate..."), this, SLOT(invokeLockHibernation())); + if (can_hibernate) rightPopup->insertItem(i18n("&Hibernate..."), this, SLOT(invokeHibernation())); + } + + rightPopup->insertSeparator(); + rightPopup->insertItem(i18n("&Hide Monitor"), this, SLOT(slotHide())); + rightPopup->insertItem(SmallIcon("exit"), KStdGuiItem::quit().text(), this, SLOT(slotQuit())); +} + +laptop_dock::~laptop_dock() +{ + delete instance; + if (brightness_widget) + delete brightness_widget; + if (throttle_popup) + delete throttle_popup; + if (performance_popup) + delete performance_popup; +} + +void +laptop_dock::activate_throttle(int ind) +{ + pdaemon->SetThrottle(throttle_popup->text(ind)); +} + +void +laptop_dock::fill_throttle() +{ + throttle_popup->clear(); + int current; + QStringList list; + bool *active_list; + bool has_throttle = laptop_portable::get_system_throttling(1, current, list, active_list); + if (!has_throttle && !list.empty()) + return; + int n=0; + for (QValueListIterator i = list.begin();i != list.end();i++) { + throttle_popup->insertItem(*i, n); + throttle_popup->setItemEnabled(n, active_list[n]); + n++; + } + throttle_popup->setItemChecked(current, 1); +} + +void +laptop_dock::activate_performance(int ind) +{ + pdaemon->SetPerformance(performance_popup->text(ind)); +} + +void +laptop_dock::fill_performance() +{ + performance_popup->clear(); + int current; + QStringList list; + bool *active_list; + bool has_performance = laptop_portable::get_system_performance(1, current, list, active_list); + if (!has_performance && !list.empty()) + return; + int n=0; + for (QValueListIterator i = list.begin();i != list.end();i++) { + performance_popup->insertItem(*i, n); + performance_popup->setItemEnabled(n, active_list[n]); + n++; + } + performance_popup->setItemChecked(current, 1); +} + +void +laptop_dock::invokeBrightnessSlider(int v) +{ + v=255-v; + pdaemon->SetBrightness(0, v); + brightness = v; +} + +void +laptop_dock::invokeBrightness() +{ + brightness = pdaemon->GetBrightness(); + + if (brightness < 0) + brightness = 255; + + if (brightness_widget == 0) { + brightness_widget = new QVBox(0L, "Brightness", WStyle_Customize | WType_Popup); + brightness_widget->setFrameStyle(QFrame::PopupPanel); + brightness_widget->setMargin(KDialog::marginHint()); + brightness_slider = new QSlider(0, 255, 16, 255-brightness, Qt::Vertical, brightness_widget, 0); + brightness_slider->setMinimumHeight(40); + brightness_slider->setMinimumWidth(15); + connect(brightness_slider, SIGNAL(valueChanged(int)), this, SLOT(invokeBrightnessSlider(int))); + brightness_widget->resize(brightness_widget->sizeHint()); + } else { + brightness_slider->setValue(255-brightness); + } + if (!brightness_widget->isVisible()) { + QRect desktop = KGlobalSettings::desktopGeometry(this); + int sw = desktop.width(); + int sh = desktop.height(); + int sx = desktop.x(); + int sy = desktop.y(); + QPoint pos = QCursor::pos(); + int x = pos.x(); + int y = pos.y(); + y -= brightness_widget->geometry().height(); + int w = brightness_widget->width(); + int h = brightness_widget->height(); + if (x+w > sw) + x = pos.x()-w; + if (y+h > sh) + y = pos.y()-h; + if (x < sx) + x = pos.x(); + if (y < sy) + y = pos.y(); + brightness_widget->move(x, y); + brightness_widget->show(); + } +} + +void laptop_dock::slotGoRoot(int /*id*/) { +#ifdef NOTDEF + QString kdesu = KStandardDirs::findExe("kdesu"); + if (!kdesu.isEmpty()) { + int rc = KMessageBox::warningContinueCancel(0, + i18n("You will need to supply a root password " + "to allow KLaptopDaemon to restart " + "itself as the superuser. It may take " + "up to a minute for the new daemon to " + "start up and the old one to close."), + i18n("KLaptopDaemon"), KStdGuiItem::cont(), + "switchToPCMCIAPrompt"); + if (rc == KMessageBox::Continue) { + KProcess *_rootProcess; + _rootProcess = new KProcess; + *_rootProcess << kdesu; + *_rootProcess << "-u"; + *_rootProcess << "root"; + //*_rootProcess << "--nonewdcop"; + *_rootProcess << KStandardDirs::findExe("klaptopdaemon"); + connect(_rootProcess, SIGNAL(processExited(KProcess*)), + this, SLOT(rootExited(KProcess*))); + _rootProcess->start(KProcess::NotifyOnExit); + // We should disable this menu item here now. + } + } else { + KMessageBox::sorry(0, i18n("PCMCIA cannot be enabled since kdesu cannot be found. Please make sure that it is installed correctly."), + i18n("KLaptopDaemon")); + } +#else + KMessageBox::sorry(0, i18n("PCMCIA cannot be enabled just now."), + i18n("KLaptopDaemon")); +#endif +} + + +void laptop_dock::slotHide() { + int confirm = KMessageBox::questionYesNo(0, i18n("Are you sure you want to hide the battery monitor? Your battery will still be monitored in the background."), QString::null, i18n("Hide Monitor"), i18n("Do Not Hide"), "hideConfirm"); + + if (confirm != KMessageBox::Yes) + return; + + // just tell ourselves to hide the battery + KConfig *config = new KConfig("kcmlaptoprc"); + if (config) { + config->setGroup("BatteryDefault"); + config->writeEntry("Enable", false); + config->sync(); + delete config; + } + wake_laptop_daemon(); +} + + +void laptop_dock::slotQuit() { + int confirm = KMessageBox::questionYesNo(0, i18n("Are you sure you want to quit the battery monitor?"), QString::null, KStdGuiItem::quit(), KStdGuiItem::cancel(), "quitConfirm"); + + if (confirm != KMessageBox::Yes) + return; + + confirm = KMessageBox::questionYesNo(0, i18n("Do you wish to disable the battery monitor from starting in the future?"), QString::null, i18n("Disable"), i18n("Keep Enabled"), "restartMonitor"); + + if (confirm == KMessageBox::Yes) { + // just tell ourselves to hide the battery + KConfig *config = new KConfig("kcmlaptoprc"); + if (config) { + config->setGroup("BatteryDefault"); + config->writeEntry("Enable", false); + config->sync(); + delete config; + } + } + pdaemon->quit(); +} + + +void laptop_dock::rootExited(KProcess *p) { + if (p && p->isRunning()) { + p->detach(); + } + exit(0); +} + + +void laptop_dock::slotEjectAction(int id) { +KPCMCIACard *f = NULL; + f = _ejectActions[id]; + + if (f) f->eject(); +} + + +void laptop_dock::slotSuspendAction(int id) { +KPCMCIACard *f = NULL; + f = _suspendActions[id]; + + if (f) f->suspend(); +} + + +void laptop_dock::slotResumeAction(int id) { +KPCMCIACard *f = NULL; + f = _resumeActions[id]; + + if (f) f->resume(); +} + + +void laptop_dock::slotResetAction(int id) { +KPCMCIACard *f = NULL; + f = _resetActions[id]; + + if (f) f->reset(); +} + + +void laptop_dock::slotInsertAction(int id) { +KPCMCIACard *f = NULL; + f = _insertActions[id]; + + if (f) f->insert(); +} + + +void laptop_dock::slotDisplayAction(int id) { +KPCMCIAInfo *f = new KPCMCIAInfo(_pcmcia); + f->showTab(_displayActions[id]->num()); +} + +void laptop_dock::mousePressEvent( QMouseEvent *event ) +{ + if(event->button() == LeftButton) { + QPopupMenu *popup = new QPopupMenu(0, "popup"); + + if (!pdaemon->exists()) { + popup->insertItem(i18n("Power Manager Not Found")); + } else { + QString tmp; + + if (pdaemon->val >= 0) { + if (pdaemon->left >= 0) { + QString num3; + num3.setNum(pdaemon->left%60); + num3 = num3.rightJustify(2, '0'); + tmp = i18n("%1:%2 hours left").arg(pdaemon->left/60).arg(num3); + } else { + // no remaining time available + tmp = i18n("%1% charged").arg(pdaemon->val); + } + } else { + tmp = i18n("No Battery"); + } + popup->insertItem(tmp); + popup->setItemEnabled(0, 0); + popup->insertSeparator(); + if (pdaemon->powered && pdaemon->val >= 0) { + popup->insertItem(i18n("Charging")); + } else { + popup->insertItem(i18n("Not Charging")); + } + popup->setItemEnabled(1, 0); + } + + /** + * CPU Frequency scaling support + * - show the cpu profile and current frequency + */ + if (laptop_portable::has_cpufreq()) { + QString speed = laptop_portable::cpu_frequency(); + if (!speed.isEmpty()) { + popup->insertSeparator(); + popup->insertItem(i18n("CPU: %1").arg(speed)); + } + } + + /** + * ADD the PCMCIA entries here + */ + if (_pcmcia && _pcmcia->haveCardServices()) { + QString slotname = i18n("Slot %1"); // up here so we only construct it once + int id; + popup->insertSeparator(); + _ejectActions.clear(); + _resetActions.clear(); + _insertActions.clear(); + _suspendActions.clear(); + _resumeActions.clear(); + _displayActions.clear(); + id = popup->insertItem(i18n("Card Slots..."), this, SLOT(slotDisplayAction(int))); + _displayActions.insert(id, _pcmcia->getCard(0)); + for (int i = 0; i < _pcmcia->getCardCount(); i++) { + KPCMCIACard *thiscard; + thiscard = _pcmcia->getCard(i); + if (thiscard && (thiscard->present())) { + QPopupMenu *thisSub = new QPopupMenu(popup, thiscard->name().latin1()); + id = thisSub->insertItem(i18n("Details..."), this, SLOT(slotDisplayAction(int))); + _displayActions.insert(id, thiscard); + + // add the actions + QPopupMenu *actionsSub = new QPopupMenu(thisSub, "actions"); + id = actionsSub->insertItem(i18n("Eject"), this, SLOT(slotEjectAction(int))); + actionsSub->setItemEnabled(id, !(thiscard->status() & CARD_STATUS_BUSY)); + _ejectActions.insert(id, thiscard); + id = actionsSub->insertItem(i18n("Suspend"), this, SLOT(slotSuspendAction(int))); + actionsSub->setItemEnabled(id, !(thiscard->status() & (CARD_STATUS_SUSPEND|CARD_STATUS_BUSY))); + _suspendActions.insert(id, thiscard); + id = actionsSub->insertItem(i18n("Resume"), this, SLOT(slotResumeAction(int))); + actionsSub->setItemEnabled(id, (thiscard->status() & CARD_STATUS_SUSPEND)); + _resumeActions.insert(id, thiscard); + id = actionsSub->insertItem(i18n("Reset"), this, SLOT(slotResetAction(int))); + _resetActions.insert(id, thiscard); + id = actionsSub->insertItem(i18n("Insert"), this, SLOT(slotInsertAction(int))); + _insertActions.insert(id, thiscard); + actionsSub->setItemEnabled(id, !(thiscard->status() & (CARD_STATUS_READY|CARD_STATUS_SUSPEND))); + thisSub->insertItem(i18n("Actions"), actionsSub); + + // add a few bits of information + thisSub->insertSeparator(); + thisSub->insertItem(slotname.arg(thiscard->num()+1)); + if (thiscard->status() & CARD_STATUS_READY) + thisSub->insertItem(i18n("Ready")); + if (thiscard->status() & CARD_STATUS_BUSY) + thisSub->insertItem(i18n("Busy")); + if (thiscard->status() & CARD_STATUS_SUSPEND) + thisSub->insertItem(i18n("Suspended")); + popup->insertItem(thiscard->name(), thisSub); + } + } + } else if (_pcmcia && geteuid() != 0) { + popup->insertItem(i18n("Enable PCMCIA")); + } + + popup->popup(QCursor::pos()); + } + +} +void laptop_dock::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( !rect().contains( e->pos() ) ) + return; + + switch ( e->button() ) { + case LeftButton: + break; + case MidButton: + // fall through + case RightButton: + { + KPopupMenu *menu = contextMenu(); + contextMenuAboutToShow( menu ); + menu->popup( e->globalPos() ); + } + break; + default: + // nothing + break; + } +} +void laptop_dock::showEvent( QShowEvent * ) +{ + +} +void laptop_dock::invokeHibernation() +{ + laptop_portable::invoke_hibernation(); +} + +void laptop_dock::invokeLockHibernation() +{ + DCOPRef dr("kdesktop", "KScreensaverIface"); + DCOPReply reply=dr.call("lock"); + + laptop_portable::invoke_hibernation(); +} +void laptop_dock::invokeStandby() +{ + laptop_portable::invoke_standby(); +} + +void laptop_dock::invokeSuspend() +{ + laptop_portable::invoke_suspend(); +} + +void laptop_dock::invokeLockSuspend() +{ + DCOPClient* client = kapp->dcopClient(); + if (client) + client->send("kdesktop", "KScreensaverIface", "lock()", ""); + laptop_portable::invoke_suspend(); +} + +void laptop_dock::invokeSetup() +{ + KProcess proc; + proc << KStandardDirs::findExe("kcmshell"); + proc << "laptop"; + proc.start(KProcess::DontCare); + proc.detach(); +} + +void +laptop_dock::reload_icon() +{ + // we will try to deduce the pixmap (or gif) name now. it will + // vary depending on the dock and power + QString pixmap_name; + + if (!pdaemon->exists()) + pixmap_name = pdaemon->noBatteryIcon(); + else if (!pdaemon->powered) + pixmap_name = pdaemon->noChargeIcon(); + else + pixmap_name = pdaemon->chargeIcon(); + + pm = loadIcon( pixmap_name, instance ); +} + +void laptop_dock::displayPixmap() +{ + int new_code; + + if (!pdaemon->exists()) + new_code = 1; + else if (!pdaemon->powered) + new_code = 2; + else + new_code = 3; + + if (current_code != new_code) { + current_code = new_code; + reload_icon(); + } + + // at this point, we have the file to display. so display it + + QImage image = pm.convertToImage(); + const QBitmap *bmmask = pm.mask(); + QImage mask; + if (bmmask) + mask = bmmask->convertToImage(); + + int w = image.width(); + int h = image.height(); + int count = 0; + QRgb rgb; + int x, y; + for (x = 0; x < w; x++) + for (y = 0; y < h; y++) + if (!bmmask || mask.pixelIndex(x, y) != 0){ + rgb = image.pixel(x, y); + if (qRed(rgb) == 0xff && + qGreen(rgb) == 0xff && + qBlue(rgb) == 0xff) + count++; + } + int c = (count*pdaemon->val)/100; + if (pdaemon->val == 100) { + c = count; + } else + if (pdaemon->val != 100 && c == count) + c = count-1; + + + if (c) { + uint ui; + QRgb blue = qRgb(0x00,0x00,0xff); + + if (image.depth() <= 8) { + ui = image.numColors(); // this fix thanks to Sven Krumpke + image.setNumColors(ui+1); + image.setColor(ui, blue); + } else { + ui = 0xff000000|blue; + } + + for (y = h-1; y >= 0; y--) + for (x = 0; x < w; x++) + if (!bmmask || mask.pixelIndex(x, y) != 0){ + rgb = image.pixel(x, y); + if (qRed(rgb) == 0xff && + qGreen(rgb) == 0xff && + qBlue(rgb) == 0xff) { + image.setPixel(x, y, ui); + c--; + if (c <= 0) + goto quit; + } + } + } +quit: + + QString tmp; + QString levelString; + + if (!pdaemon->exists()) { + tmp = i18n("Laptop power management not available"); + levelString = i18n("N/A"); + } else + if (pdaemon->powered) { + if (pdaemon->val == 100) { + tmp = i18n("Plugged in - fully charged");; + levelString = "100%"; + } else if (pdaemon->val >= 0) { + levelString.sprintf ("%i%%", pdaemon->val); + if (pdaemon->left >= 0) { + QString num3; + num3.setNum(pdaemon->left%60); + num3 = num3.rightJustify(2, '0'); + tmp = i18n("Plugged in - %1% charged (%2:%3 hours left)") + .arg(pdaemon->val).arg(pdaemon->left/60).arg(num3); + } else { + // no remaining time available + tmp = i18n("Plugged in - %1% charged").arg(pdaemon->val); + } + } else { + tmp = i18n("Plugged in - no battery"); + levelString = i18n("N/A"); + } + } else { + if (pdaemon->val >= 0) { + levelString.sprintf ("%i%%", pdaemon->val); + if (pdaemon->left >= 0) { + QString num3; + num3.setNum(pdaemon->left%60); + num3 = num3.rightJustify(2, '0'); + tmp = i18n("Running on batteries - %1% charged (%2:%3 hours left)") + .arg(pdaemon->val).arg(pdaemon->left/60).arg(num3); + } else { + tmp = i18n("Running on batteries - %1% charged").arg(pdaemon->val); + } + } else { + // running without any power source... + // happens eg. due to ACPI not being able to handle battery hot-plugin + tmp = i18n("No power source found"); + levelString = i18n("N/A"); + } + } + + + // prepare icon for systemtray + + KConfig* config = new KConfig("kcmlaptoprc"); + bool showlevel = false; + + if (config) + { + config->setGroup("BatteryDefault"); + showlevel= config->readBoolEntry("ShowLevel", false); + delete config; + } + + if (showlevel) + { + // lot of code taken from kmail kmsystemtray class + + int oldPixmapWidth = image.size().width(); + int oldPixmapHeight = image.size().height(); + + QFont percentageFont = KGlobalSettings::generalFont(); + percentageFont.setBold(true); + + // decrease the size of the font for the number of unread messages if the + // number doesn't fit into the available space + float percentageFontSize = percentageFont.pointSizeFloat(); + QFontMetrics qfm( percentageFont ); + int width = qfm.width( levelString ); + if( width > oldPixmapWidth ) + { + percentageFontSize *= float( oldPixmapWidth ) / float( width ); + percentageFont.setPointSizeFloat( percentageFontSize ); + } + + // Create an image which represents the number of unread messages + // and which has a transparent background. + // Unfortunately this required the following twisted code because for some + // reason text that is drawn on a transparent pixmap is invisible + // (apparently the alpha channel isn't changed when the text is drawn). + // Therefore I have to draw the text on a solid background and then remove + // the background by making it transparent with QPixmap::setMask. This + // involves the slow createHeuristicMask() function (from the API docs: + // "This function is slow because it involves transformation to a QImage, + // non-trivial computations and a transformation back to a QBitmap."). Then + // I have to convert the resulting QPixmap to a QImage in order to overlay + // the light KMail icon with the number (because KIconEffect::overlay only + // works with QImage). Finally the resulting QImage has to be converted + // back to a QPixmap. + // That's a lot of work for overlaying the KMail icon with the number of + // unread messages, but every other approach I tried failed miserably. + // IK, 2003-09-22 + QPixmap percentagePixmap( oldPixmapWidth, oldPixmapHeight ); + percentagePixmap.fill( Qt::white ); + QPainter p( &percentagePixmap ); + p.setFont( percentageFont ); + p.setPen( Qt::black ); + p.drawText( percentagePixmap.rect(), Qt::AlignCenter, levelString ); + percentagePixmap.setMask( percentagePixmap.createHeuristicMask() ); + QImage percentageImage = percentagePixmap.convertToImage(); + + // Overlay the light KMail icon with the number image + QImage iconWithPercentageImage = image.copy(); + KIconEffect::overlay( iconWithPercentageImage, percentageImage ); + + QPixmap iconWithPercentage; + iconWithPercentage.convertFromImage( iconWithPercentageImage ); + + setPixmap( iconWithPercentage ); + } + else + { + QPixmap q; + q.convertFromImage(image); + if (bmmask) + q.setMask(*bmmask); + setPixmap(q); + } + adjustSize(); + + QToolTip::add(this, tmp); +} + +#include "daemondock.moc" + diff --git a/klaptopdaemon/daemondock.h b/klaptopdaemon/daemondock.h new file mode 100644 index 0000000..7577ffd --- /dev/null +++ b/klaptopdaemon/daemondock.h @@ -0,0 +1,108 @@ +#ifndef DAEMONDOCK +#define DAEMONDOCK 1 +/* + * daemondock.h + * Copyright (C) 1999 Paul Campbell + * Copyright (C) 2006 Flavio Castelli + * + * This file contains the docked widget for the laptop battery monitor + * + * $Id$ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include "laptop_daemon.h" +#include + +class laptop_daemon; +class KPCMCIA; +class KPCMCIACard; +class QPopupMenu; +class QVBox; +class QSlider; +class KPopupMenu; + +#include + +class laptop_dock : public KSystemTray { + + Q_OBJECT + +public: + laptop_dock(laptop_daemon* parent); + ~laptop_dock(); + void displayPixmap(); + + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + void showEvent( QShowEvent * ); + void reload_icon(); + + inline void setPCMCIA(KPCMCIA *p) { _pcmcia = p; } + + void SetupPopup(); + +private slots: + void invokeStandby(); + void invokeSuspend(); + void invokeLockSuspend(); + void invokeHibernation(); + void invokeLockHibernation(); + void invokeSetup(); + void invokeBrightness(); + void invokeBrightnessSlider(int v); + + void slotEjectAction(int id); + void slotResumeAction(int id); + void slotSuspendAction(int id); + void slotInsertAction(int id); + void slotResetAction(int id); + void slotDisplayAction(int id); + + void activate_throttle(int ind); + void fill_throttle(); + void activate_performance(int ind); + void fill_performance(); + + + void rootExited(KProcess *p); + void slotGoRoot(int id); + void slotQuit(); + void slotHide(); + +private: + int brightness; + QVBox *brightness_widget; + QSlider *brightness_slider; + laptop_daemon *pdaemon; + QPixmap pm; + QPopupMenu *performance_popup, *throttle_popup; + int current_code; + KPCMCIA *_pcmcia; + QMap _ejectActions, + _suspendActions, + _resumeActions, + _resetActions, + _displayActions, + _insertActions; + + KInstance *instance; // handle so we get our pretty icons right + KPopupMenu *rightPopup; + +}; +#endif + diff --git a/klaptopdaemon/kpcmcia.cpp b/klaptopdaemon/kpcmcia.cpp new file mode 100644 index 0000000..9dec605 --- /dev/null +++ b/klaptopdaemon/kpcmcia.cpp @@ -0,0 +1,547 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/* + * Much of the linux code was migrated from: + * kardinfo Copyright 1999, Mirko Sucker + */ + +#include +#include +#include + +#include +#include +#include + + +#include "kpcmcia.h" + + +#ifdef __linux__ + extern "C" { + #include + #include + #include + #include + #include + #include + #include + #include "linux/version.h" + #include "linux/cs_types.h" + #include "linux/cs.h" + #include "linux/cistpl.h" + #include "linux/ds.h" + } + +// Taken from cardinfo.c +typedef struct event_tag_t { + event_t event; + const char *name; +} event_tag_t; + + +static event_tag_t event_tag[] = { + { CS_EVENT_CARD_INSERTION, "card insertion" }, + { CS_EVENT_CARD_REMOVAL, "card removal" }, + { CS_EVENT_RESET_PHYSICAL, "prepare for reset" }, + { CS_EVENT_CARD_RESET, "card reset successful" }, + { CS_EVENT_RESET_COMPLETE, "reset request complete" }, + { CS_EVENT_EJECTION_REQUEST, "user eject request" }, + { CS_EVENT_INSERTION_REQUEST, "user insert request" }, + { CS_EVENT_PM_SUSPEND, "suspend card" }, + { CS_EVENT_PM_RESUME, "resume card" }, + { CS_EVENT_REQUEST_ATTENTION, "request attention" } +}; + +#define NTAGS (sizeof(event_tag)/sizeof(event_tag_t)) + +static int lookupDevice(const char *x); +static int openDevice(dev_t dev); + +#else +#include +#endif + + + +KPCMCIACard::KPCMCIACard() { + _fd = -1; + _num = 9999999; + _status = 0; + _last = 0; + _interrupt = -1; + _ports = ""; + _device = ""; + _module = ""; + _type = ""; + _iotype = 0; + _cardname = i18n("Empty slot."); + _vcc = _vpp = _vpp2 = 0; + _inttype = 0; + _cfgbase = 0; +} + + +KPCMCIACard::~KPCMCIACard() { + if (_fd != -1) close(_fd); +} + + + +// RETURN: <0 => error +// =0 => no error, no update +// >0 => no error, update happened +// +int KPCMCIACard::refresh() { +////////////////////////////////////////////// +///////////// LINUX ONLY +/////////////////////////////////////////////// +#ifdef __linux__ +struct timeval tv; +cs_status_t status; +fd_set rfds; +int rc; +event_t event; +struct stat sb; +config_info_t cfg; +KPCMCIACard oldValues(*this); +int updated = 0; +oldValues._fd = -1; + +#define CHECK_CHANGED(x, y) do { if (x.y != y) updated = 1; } while(0) + + /** + * Get any events on the pcmcia device + */ +tv.tv_sec = 0; tv.tv_usec = 0; + FD_ZERO(&rfds); + FD_SET(_fd, &rfds); + rc = select(_fd+1, &rfds, NULL, NULL, &tv); + if (rc > 0) { + rc = read(_fd, (void *)&event, 4); + if (rc == 4) { + int thisEvent = -1; // thisEvent is the index of event in event_tag + for (unsigned int j = 0; j < NTAGS; j++) { + if (event_tag[j].event == event) { + thisEvent = j; + break; + } + if (thisEvent < 0) return -1; + } + } else { + return -1; + } + } else return updated; + + if (event == CS_EVENT_EJECTION_REQUEST) { + _interrupt = -1; + _ports = ""; + _device = ""; + _module = ""; + _type = ""; + _iotype = 0; + _inttype = 0; + _cfgbase = 0; + _cardname = i18n("Empty slot."); + _vcc = _vpp = _vpp2 = 0; + return updated; + } + + /** + * Read in the stab file. + */ + if (!stat(_stabPath.latin1(), &sb) && sb.st_mtime >= _last) { + QFile f(_stabPath.latin1()); + + if (f.open(IO_ReadOnly)) { + QTextStream ts(&f); + bool foundit = false; + QString _thisreg = "^Socket %1: "; + QRegExp thisreg ( _thisreg.arg(_num) ); + + if (flock(f.handle(), LOCK_SH)) return updated; + + _last = sb.st_mtime; + + // find the card + while(!foundit) { + QString s; + if (ts.eof()) break; + s = ts.readLine(); + if (s.contains(thisreg)) { + _cardname = s.right(s.length() - s.find(':') - 1); + _cardname = _cardname.stripWhiteSpace(); + foundit = true; + CHECK_CHANGED(oldValues, _cardname); + } + } + + // read it in + if (foundit && !ts.eof()) { // FIXME: ts.eof() is a bad error!! + QString s = ts.readLine(); + int end; + s.simplifyWhiteSpace(); + + end = s.find(QRegExp("[ \r\t\n]")); + s = s.remove(0, end+1); + + end = s.find(QRegExp("[ \r\t\n]")); + _type = s; + _type.truncate(end); + s = s.remove(0, end+1); + + end = s.find(QRegExp("[ \r\t\n]")); + _module = s; + _module.truncate(end); + s = s.remove(0, end+1); + + end = s.find(QRegExp("[ \r\t\n]")); + s = s.remove(0, end+1); + + end = s.find(QRegExp("[ \r\t\n]")); + _device = s; + _device.truncate(end); + s = s.remove(0, end+1); + CHECK_CHANGED(oldValues, _type); + CHECK_CHANGED(oldValues, _module); + CHECK_CHANGED(oldValues, _device); + } + + flock(f.handle(), LOCK_UN); + f.close(); + } else return -1; + } else return updated; + + + /** + * Get the card's status and configuration information + */ + status.Function = 0; + ioctl(_fd, DS_GET_STATUS, &status); + memset(&cfg, 0, sizeof(cfg)); + ioctl(_fd, DS_GET_CONFIGURATION_INFO, &cfg); + // status is looked up in the table at the top + if (cfg.Attributes & CONF_VALID_CLIENT) { + if (cfg.AssignedIRQ == 0) + _interrupt = -1; + else _interrupt = cfg.AssignedIRQ; + + if (cfg.NumPorts1 > 0) { + int stop = cfg.BasePort1 + cfg.NumPorts1; + if (cfg.NumPorts2 > 0) { + if (stop == cfg.BasePort2) { + _ports.sprintf("%#x-%#x", cfg.BasePort1, stop+cfg.NumPorts2-1); + } else { + _ports.sprintf("%#x-%#x, %#x-%#x", cfg.BasePort1, stop-1, + cfg.BasePort2, cfg.BasePort2+cfg.NumPorts2-1); + } + } else { + _ports.sprintf("%#x-%#x", cfg.BasePort1, stop-1); + } + } + CHECK_CHANGED(oldValues, _ports); + CHECK_CHANGED(oldValues, _interrupt); + } + + _vcc = cfg.Vcc; + _vpp = cfg.Vpp1; + _vpp2 = cfg.Vpp2; + CHECK_CHANGED(oldValues, _vcc); + CHECK_CHANGED(oldValues, _vpp); + CHECK_CHANGED(oldValues, _vpp2); + _inttype = cfg.IntType; + CHECK_CHANGED(oldValues, _inttype); + _iotype = cfg.IOAddrLines; + CHECK_CHANGED(oldValues, _iotype); + _cfgbase = cfg.ConfigBase; + CHECK_CHANGED(oldValues, _cfgbase); + + if (status.CardState & CS_EVENT_CARD_DETECT) + _status |= CARD_STATUS_PRESENT; + if (status.CardState & CS_EVENT_CARD_REMOVAL) + _status &= ~CARD_STATUS_PRESENT; + if (event & CS_EVENT_CARD_REMOVAL) + _status &= ~CARD_STATUS_PRESENT; + + if (!(status.CardState & CS_EVENT_PM_SUSPEND)) { + if (status.CardState & CS_EVENT_READY_CHANGE) { + _status |= CARD_STATUS_READY; + _status &= ~(CARD_STATUS_BUSY|CARD_STATUS_SUSPEND); + } else { + _status |= CARD_STATUS_BUSY; + _status &= ~(CARD_STATUS_READY|CARD_STATUS_SUSPEND); + } + } else if (status.CardState & CS_EVENT_PM_SUSPEND) { + _status |= CARD_STATUS_SUSPEND; + _status &= ~(CARD_STATUS_READY|CARD_STATUS_BUSY); + } + + CHECK_CHANGED(oldValues, _status); + +return updated; +#else +return 0; +#endif +} + + +int KPCMCIACard::insert() { +#ifdef __linux__ + ioctl(_fd, DS_INSERT_CARD); + return 0; +#else + return -1; +#endif +} + + + +int KPCMCIACard::eject() { +#ifdef __linux__ + ioctl(_fd, DS_EJECT_CARD); + return 0; +#else + return -1; +#endif +} + + + +int KPCMCIACard::reset() { +#ifdef __linux__ + ioctl(_fd, DS_RESET_CARD); + return 0; +#else + return -1; +#endif +} + + + +int KPCMCIACard::suspend() { +#ifdef __linux__ + ioctl(_fd, DS_SUSPEND_CARD); + return 0; +#else + return -1; +#endif +} + + + +int KPCMCIACard::resume() { +#ifdef __linux__ + ioctl(_fd, DS_RESUME_CARD); + return 0; +#else + return -1; +#endif +} + + + + + +KPCMCIA::KPCMCIA(int maxSlots, const char *stabpath) : _maxSlots(maxSlots), + _stabPath(stabpath) { + +_refreshSpeed = 750; + +_haveCardServices = false; +_timer = new QTimer(this); +connect(_timer, SIGNAL(timeout()), this, SLOT(updateCardInfo())); +_cards = new QMemArray(_maxSlots+1); +_cardCnt = 0; + + +/////////////////////////////////////////////////// +// LINUX code +/////////////////////////////////////////////////// +#ifdef __linux__ +servinfo_t serv; + + int device = lookupDevice("pcmcia"); + + if (device >= 0) { + for (int z = 0; z < _maxSlots; z++) { + int fd = openDevice((device << 8) + z); + if (fd < 0) break; + (*_cards)[_cardCnt] = new KPCMCIACard; + (*_cards)[_cardCnt]->_stabPath = _stabPath; + (*_cards)[_cardCnt]->_fd = fd; + (*_cards)[_cardCnt]->_num = _cardCnt; + //(*_cards)[_cardCnt]->refresh(); + _cardCnt++; + //kdDebug() << "Found a pcmcia slot" << endl; + } + + if (_cardCnt > 0) { + if (ioctl((*_cards)[0]->_fd, DS_GET_CARD_SERVICES_INFO, &serv) == 0) { + // FIXME: what to do here? + } + _haveCardServices = true; + } + } + + + +_timer->start(_refreshSpeed, true); + +/////////////////////////////////////////////////// +// No supported platform. +/////////////////////////////////////////////////// +#else + +#endif +} + + + + + + + + +KPCMCIA::~KPCMCIA() { +/////////////////////////////////////////////////// +// LINUX code +/////////////////////////////////////////////////// +#ifdef __linux__ + + +/////////////////////////////////////////////////// +// No supported platform. +/////////////////////////////////////////////////// +#else + +#endif + + +delete _timer; +delete _cards; +} + + + + + + + +KPCMCIACard* KPCMCIA::getCard(int num) { + if (num >= _cardCnt || num < 0) return NULL; + return (*_cards)[num]; +} + + + + +void KPCMCIA::updateCardInfo() { + for (int i = 0; i < _cardCnt; i++) { + int rc = (*_cards)[i]->refresh(); + /* + kdDebug() << "CARD UPDATED: " << i << endl + << " Name: " << (*_cards)[i]->_cardname << endl + << " Device: " << (*_cards)[i]->_device << endl + << " VCC: " << (*_cards)[i]->_vcc << endl + << " VPP: " << (*_cards)[i]->_vpp << endl + << " IRQ: " << (*_cards)[i]->_interrupt << endl + << " Ports: " << (*_cards)[i]->_ports << endl + << " Type: " << (*_cards)[i]->_type << endl + << " Module: " << (*_cards)[i]->_module << endl + << endl; + */ + if (rc > 0) emit cardUpdated(i); + } +_timer->start(_refreshSpeed, true); +} + + + +void KPCMCIA::setRefreshSpeed(int msec) { + _refreshSpeed = msec; +} + + +int KPCMCIA::getCardCount() { + return _cardCnt; +} + + +bool KPCMCIA::haveCardServices() { + return _haveCardServices; +} + + +#include "kpcmcia.moc" + + + +#ifdef __linux__ +static int lookupDevice(const char *x) { +QFile df("/proc/devices"); +QString thisreg; + + thisreg = "^[0-9]+ %1$"; + thisreg = thisreg.arg(x); + + if (df.open(IO_ReadOnly)) { + QTextStream t(&df); + QString s; + while (!t.eof()) { + s = t.readLine(); + + if (s.contains(QRegExp(thisreg))) { + int n = (s.left(3).stripWhiteSpace()).toInt(); + df.close(); + return n; + } + } + df.close(); + } +return -1; +} + +static int openDevice(dev_t dev) { +QString tmp_path = locateLocal("tmp", KGlobal::instance()->instanceName()); +QString ext = "_socket%1"; + + tmp_path += ext.arg((int)dev); + + int rc = mknod(tmp_path.latin1(), (S_IFCHR | S_IREAD), dev); + if (rc < 0) return -1; + + int fd = open(tmp_path.latin1(), O_RDONLY); + if (fd < 0) { + unlink(tmp_path.latin1()); + return -1; + } + + if (unlink(tmp_path.latin1()) < 0) { + close(fd); + return -1; + } + + return fd; +} + +#endif + + diff --git a/klaptopdaemon/kpcmcia.h b/klaptopdaemon/kpcmcia.h new file mode 100644 index 0000000..c821926 --- /dev/null +++ b/klaptopdaemon/kpcmcia.h @@ -0,0 +1,214 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef _KPCMCIA_H +#define _KPCMCIA_H + +class QTimer; +class KPCMCIA; + +#include + +#include + +#define CARD_STATUS_PRESENT 1 +#define CARD_STATUS_READY 2 +#define CARD_STATUS_BUSY 4 +#define CARD_STATUS_SUSPEND 8 +#define CARD_STATUS_SUSPENDED 8 + + +class KPCMCIACard { +friend class KPCMCIA; +protected: + KPCMCIACard(); + ~KPCMCIACard(); + + int _fd; + + int _interrupt; + QString _device, _ports; + QString _module; + QString _cardname; + QString _type; + int _vcc, _vpp, _vpp2; + QString _stabPath; + int _iotype; + int _inttype; + int _cfgbase; + + int _status; + int _num; + + // Other fields for the future + // etc look in linux/cs.h for more info + +public: + + /** + * Base address for configuration + */ + inline int configBase() { return _cfgbase; } + + /** + * Interrupt type + */ + inline int intType() { return _inttype; } + + /** + * 16/32 bit + */ + inline int busWidth() { return _iotype; } + + /** + * True if the card is present + */ + inline bool present() { return _status & CARD_STATUS_PRESENT; } + + /** + * Return the card status + */ + inline int status() { return _status; } + + /** + * Request to eject the card + */ + int eject(); + + /** + * Request to resume from suspend + */ + int resume(); + + /** + * Request to suspend + */ + int suspend(); + + /** + * Request to reset the card + */ + int reset(); + + /** + * Insert a card (mostly not needed?) + */ + int insert(); + + /** + * Return the card number + */ + inline int num() { return _num; } + + /** + * Return the interrupt in use (or -1 if none) + */ + inline int irq() { return _interrupt; } + + /** + * Return the VCC status + */ + inline int vcc() { return _vcc; } + + /** + * Return the card programming power (1) + */ + inline int vpp() { return _vpp; } + + /** + * Return the card programming power (2) + */ + inline int vpp2() { return _vpp2; } + + /** + * Return the card name + */ + inline QString& name() { return _cardname; } + + /** + * Return the port range + */ + inline QString& ports() { return _ports; } + + /** + * Return the device name + */ + inline QString& device() { return _device; } + + /** + * Return the device type (ie network, modem, etc) + */ + inline QString& type() { return _type; } + + /** + * Return the driver (module) name + */ + inline QString& driver() { return _module; } + + /** + * Refresh the card information - return < 0 on error. + * (this is called automatically [by KPCMCIA] on a timer normally) + */ + int refresh(); + +private: + time_t _last; +}; + + + + +class KPCMCIA : public QObject { +Q_OBJECT +public: + + KPCMCIA(int maxSlots = 8, const char *stabPath = "/var/run/stab"); + ~KPCMCIA(); + + void setRefreshSpeed(int msec); + int getCardCount(); + KPCMCIACard *getCard(int num); + + bool haveCardServices(); + +signals: + void cardUpdated(int num); + + +public slots: + void updateCardInfo(); + +private: + int _refreshSpeed; + QTimer *_timer; + QMemArray *_cards; + int _cardCnt; + bool _haveCardServices; + int _maxSlots; + QString _stabPath; + +}; + + + + +#endif + diff --git a/klaptopdaemon/kpcmciainfo.cpp b/klaptopdaemon/kpcmciainfo.cpp new file mode 100644 index 0000000..82da914 --- /dev/null +++ b/klaptopdaemon/kpcmciainfo.cpp @@ -0,0 +1,313 @@ + +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "kpcmcia.h" + +#include "kpcmciainfo.h" + + +KPCMCIAInfo::KPCMCIAInfo(KPCMCIA *pcmcia, QWidget *parent, const char *name) + : KDialog(parent, name, false), _pcmcia(pcmcia) { + + setMinimumSize(300,400); + + _mainGrid = new QGridLayout(this, 9, 5); + + _mainTab = new QTabWidget(this); + _mainGrid->addMultiCellWidget(_mainTab, 0, 6, 0, 4); + _mainGrid->setRowStretch(0, 1); + _mainGrid->setRowStretch(1, 1); + _mainGrid->setRowStretch(2, 1); + _mainGrid->setRowStretch(3, 1); + _mainGrid->setRowStretch(4, 1); + _mainGrid->setRowStretch(5, 1); + _mainGrid->setRowStretch(6, 1); + + setCaption(i18n("PCMCIA & CardBus Slots")); + + prepareCards(); + + _mainTab->resize(KDialog::sizeHint()); + resize(KDialog::sizeHint()); + + connect(_pcmcia, SIGNAL(cardUpdated(int)), this, SLOT(updateCard(int))); + + _sb = new KStatusBar(this); + _sb->insertItem(i18n("Ready."), 0, 1, true); + _sb->resize(KDialog::sizeHint()); + _mainGrid->addMultiCellWidget(_sb, 8, 8, 0, 4); + _mainGrid->setRowStretch(8, 0); + + _updateButton = new QPushButton(i18n("&Update"), this); + _mainGrid->addWidget(_updateButton, 7, 3); + connect(_updateButton, SIGNAL(pressed()), this, SLOT(update())); + _closeButton = new KPushButton(KStdGuiItem::close(), this); + _mainGrid->addWidget(_closeButton, 7, 4); + connect(_closeButton, SIGNAL(pressed()), this, SLOT(slotClose())); + _mainGrid->setRowStretch(7, 0); + + show(); +} + + + +KPCMCIAInfo::~KPCMCIAInfo() { + +} + + +void KPCMCIAInfo::showTab(int num) { + _mainTab->showPage(_pages[num]); +} + + +void KPCMCIAInfo::slotResetStatus() { + _sb->changeItem(i18n("Ready."), 0); +} + + +void KPCMCIAInfo::statusNotice(const QString& text, int life) { + _sb->changeItem(text, 0); + if (life > 0) + QTimer::singleShot(life, this, SLOT(slotResetStatus())); +} + + + +void KPCMCIAInfo::slotTabSetStatus(const QString& text) { + statusNotice(text); +} + + +void KPCMCIAInfo::slotClose() { + delete this; +} + + +void KPCMCIAInfo::update() { + emit updateNow(); +} + + +void KPCMCIAInfo::updateCard(int num) { + _pages[num]->update(); +} + + +void KPCMCIAInfo::prepareCards() { + if (!_pcmcia) { + // FIXME: display error + return; + } + + for (int i = 0; i < _pcmcia->getCardCount(); i++) { + QString tabname = i18n("Card Slot %1"); + KPCMCIAInfoPage *tp = new KPCMCIAInfoPage(_pcmcia->getCard(i), _mainTab); + connect(this, SIGNAL(updateNow()), tp, SLOT(update())); + connect(tp, SIGNAL(setStatusBar(const QString&)), this, SLOT(slotTabSetStatus(const QString&))); + tp->resize(_mainTab->sizeHint()); + _mainTab->addTab(tp, tabname.arg(i+1)); + _pages.insert(i, tp); + } +} + + + + + + +/////////////////////////////////////////////////////////////////////////// + + +KPCMCIAInfoPage::KPCMCIAInfoPage(KPCMCIACard *card, QWidget *parent, const char *name) + : QFrame(parent, name), _card(card) { + _mainGrid = new QGridLayout(this, 10, 10); + if (!_card) { + // display an error + } else { + _card_name = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_name, 0, 0, 0, 5); + _card_type = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_type, 0, 0, 6, 9); + _card_driver = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_driver, 1, 1, 0, 4); + _card_irq = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_irq, 2, 2, 0, 3); + _card_io = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_io, 3, 3, 0, 6); + _card_dev = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_dev, 4, 4, 0, 4); + _card_vcc = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_vcc, 5, 5, 0, 2); + _card_vpp = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_vpp, 5, 5, 5, 9); + _card_bus = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_bus, 6, 6, 0, 4); + _card_cfgbase = new QLabel(this); + _mainGrid->addMultiCellWidget(_card_cfgbase, 6, 6, 5, 9); + + _card_ej_ins = new QPushButton(i18n("&Eject"), this); + _card_sus_res = new QPushButton(i18n("&Suspend"), this); + _card_reset = new QPushButton(i18n("&Reset"), this); + _mainGrid->addWidget(_card_ej_ins, 9, 5); + _mainGrid->addWidget(_card_sus_res, 9, 6); + _mainGrid->addWidget(_card_reset, 9, 7); + connect(_card_reset, SIGNAL(pressed()), this, SLOT(slotResetCard())); + connect(_card_sus_res, SIGNAL(pressed()), this, SLOT(slotSuspendResume())); + connect(_card_ej_ins, SIGNAL(pressed()), this, SLOT(slotInsertEject())); + + update(); + } +} + + +KPCMCIAInfoPage::~KPCMCIAInfoPage() { + +} + + + +void KPCMCIAInfoPage::slotResetCard() { + emit setStatusBar(i18n("Resetting card...")); + _card->reset(); +} + + +void KPCMCIAInfoPage::slotInsertEject() { + if (!(_card->status() & (CARD_STATUS_READY|CARD_STATUS_SUSPEND))) { + emit setStatusBar(i18n("Inserting new card...")); + _card->insert(); + _card->reset(); + } else { + emit setStatusBar(i18n("Ejecting card...")); + if (_card->status() & CARD_STATUS_SUSPEND) + _card->resume(); + _card->eject(); + } +} + + +void KPCMCIAInfoPage::slotSuspendResume() { + if (!(_card->status() & CARD_STATUS_BUSY)) + if (!(_card->status() & CARD_STATUS_SUSPEND)) { + emit setStatusBar(i18n("Suspending card...")); + _card->suspend(); + } else { + emit setStatusBar(i18n("Resuming card...")); + _card->resume(); + } +} + + +void KPCMCIAInfoPage::update() { + if (_card) { + QString tmp; + _card_name->setText(_card->name()); + _card_name->resize(_card_name->sizeHint()); + tmp = i18n("Card type: %1 "); + _card_type->setText(tmp.arg(_card->type())); + _card_type->resize(_card_type->sizeHint()); + tmp = i18n("Driver: %1"); + _card_driver->setText(tmp.arg(_card->driver())); + _card_driver->resize(_card_driver->sizeHint()); + tmp = i18n("IRQ: %1%2"); + QString tmp2; + switch (_card->intType()) { + case 1: + tmp2 = i18n(" (used for memory)"); + break; + case 2: + tmp2 = i18n(" (used for memory and I/O)"); + break; + case 4: + tmp2 = i18n(" (used for CardBus)"); + break; + default: + tmp2 = ""; + }; + if (_card->irq() <= 0) + _card_irq->setText(tmp.arg(i18n("none")).arg("")); + else _card_irq->setText(tmp.arg(_card->irq()).arg(tmp2)); + _card_irq->resize(_card_irq->sizeHint()); + tmp = i18n("I/O port(s): %1"); + if (_card->ports().isEmpty()) + _card_io->setText(tmp.arg(i18n("none"))); + else _card_io->setText(tmp.arg(_card->ports())); + _card_io->resize(_card_io->sizeHint()); + tmp = i18n("Bus: %1 bit %2"); + if (_card->busWidth() == 0) + _card_bus->setText(i18n("Bus: unknown")); + else _card_bus->setText(tmp.arg(_card->busWidth()).arg(_card->busWidth() == 16 ? i18n("PC Card") : i18n("Cardbus"))); + _card_bus->resize(_card_bus->sizeHint()); + tmp = i18n("Device: %1"); + _card_dev->setText(tmp.arg(_card->device())); + _card_dev->resize(_card_dev->sizeHint()); + tmp = i18n("Power: +%1V"); + _card_vcc->setText(tmp.arg(_card->vcc()/10)); + _card_vcc->resize(_card_vcc->sizeHint()); + tmp = i18n("Programming power: +%1V, +%2V"); + _card_vpp->setText(tmp.arg(_card->vpp()/10).arg(_card->vpp2()/10)); + _card_vpp->resize(_card_vpp->sizeHint()); + tmp = i18n("Configuration base: 0x%1"); + if (_card->configBase() == 0) + _card_cfgbase->setText(i18n("Configuration base: none")); + else _card_cfgbase->setText(tmp.arg(_card->configBase(), -1, 16)); + _card_cfgbase->resize(_card_cfgbase->sizeHint()); + + if (!(_card->status() & (CARD_STATUS_READY|CARD_STATUS_SUSPEND))) { + _card_ej_ins->setText(i18n("&Insert")); + } else { + _card_ej_ins->setText(i18n("&Eject")); + } + if (!(_card->status() & (CARD_STATUS_BUSY|CARD_STATUS_SUSPEND))) { + _card_sus_res->setText(i18n("&Suspend")); + } else { + _card_sus_res->setText(i18n("Resu&me")); + } + if (!(_card->status() & (CARD_STATUS_READY|CARD_STATUS_SUSPEND))) { + _card_sus_res->setEnabled(false); + _card_reset->setEnabled(false); + } else { + _card_sus_res->setEnabled(true); + if (!(_card->status() & CARD_STATUS_SUSPEND)) + _card_reset->setEnabled(true); + else _card_reset->setEnabled(false); + } + } +} + + + + +#include "kpcmciainfo.moc" + diff --git a/klaptopdaemon/kpcmciainfo.h b/klaptopdaemon/kpcmciainfo.h new file mode 100644 index 0000000..0cc7cea --- /dev/null +++ b/klaptopdaemon/kpcmciainfo.h @@ -0,0 +1,116 @@ + +/* This file is part of the KDE project + * + * Copyright (C) 2001 George Staikos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef _KPCMCIAINFO_H +#define _KPCMCIAINFO_H + +#include +#include + +class KPCMCIA; +class KPCMCIACard; +class KPCMCIAInfoPage; +class QTabWidget; +class KStatusBar; +class QGridLayout; +class QPushButton; +class KPushButton; + +#include + +class KPCMCIAInfo : public KDialog { +Q_OBJECT +public: + + KPCMCIAInfo(KPCMCIA *pcmcia, QWidget *parent = NULL, const char *name = 0); + virtual ~KPCMCIAInfo(); + + void showTab(int num); + void statusNotice(const QString& text, int life = 1500); + +public slots: + void slotClose(); + void update(); + void updateCard(int num); + void slotResetStatus(); + void slotTabSetStatus(const QString& text); + +signals: + void updateNow(); + +private: + QFrame *_mainFrame; + QTabWidget *_mainTab; + QGridLayout *_mainGrid; + KPCMCIA *_pcmcia; + QMap _pages; + KStatusBar *_sb; + KPushButton *_closeButton; + QPushButton *_updateButton; + + + void prepareCards(); +}; + + +class QLabel; + + +class KPCMCIAInfoPage : public QFrame { +Q_OBJECT +public: + KPCMCIAInfoPage(KPCMCIACard *card, QWidget *parent = NULL, const char *name = 0); + virtual ~KPCMCIAInfoPage(); + +public slots: + void update(); + void slotResetCard(); + void slotInsertEject(); + void slotSuspendResume(); + +signals: + void setStatusBar(const QString&); + +private: + + KPCMCIACard *_card; + QGridLayout *_mainGrid; + + QLabel *_card_name; + QLabel *_card_type; + QLabel *_card_irq; + QLabel *_card_io; + QLabel *_card_dev; + QLabel *_card_driver; + QLabel *_card_vcc; + QLabel *_card_vpp; + QLabel *_card_cfgbase; + QLabel *_card_bus; + + QPushButton *_card_ej_ins; + QPushButton *_card_sus_res; + QPushButton *_card_reset; + +}; + +#endif + diff --git a/klaptopdaemon/krichtextlabel.cpp b/klaptopdaemon/krichtextlabel.cpp new file mode 100644 index 0000000..458ade6 --- /dev/null +++ b/klaptopdaemon/krichtextlabel.cpp @@ -0,0 +1,112 @@ +/* This file is part of the KDE libraries + Copyright (C) 2005 Waldo Bastian + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "krichtextlabel.h" + +#include +#include +#include + +#include + +static QString qrichtextify( const QString& text ) +{ + if ( text.isEmpty() || text[0] == '<' ) + return text; + + QStringList lines = QStringList::split('\n', text); + for(QStringList::Iterator it = lines.begin(); it != lines.end(); ++it) + { + *it = QStyleSheet::convertFromPlainText( *it, QStyleSheetItem::WhiteSpaceNormal ); + } + + return lines.join(QString::null); +} + +KRichTextLabel::KRichTextLabel( const QString &text , QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + m_defaultWidth = QMIN(400, KGlobalSettings::desktopGeometry(this).width()*2/5); + setAlignment( Qt::WordBreak ); + setText(text); +} + +KRichTextLabel::KRichTextLabel( QWidget *parent, const char *name ) + : QLabel ( parent, name ) { + m_defaultWidth = QMIN(400, KGlobalSettings::desktopGeometry(this).width()*2/5); + setAlignment( Qt::WordBreak ); +} + +void KRichTextLabel::setDefaultWidth(int defaultWidth) +{ + m_defaultWidth = defaultWidth; + updateGeometry(); +} + +QSizePolicy KRichTextLabel::sizePolicy() const +{ + return QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum, false); +} + +QSize KRichTextLabel::minimumSizeHint() const +{ + QString qt_text = qrichtextify( text() ); + int pref_width = 0; + int pref_height = 0; + QSimpleRichText rt(qt_text, font()); + pref_width = m_defaultWidth; + rt.setWidth(pref_width); + int used_width = rt.widthUsed(); + if (used_width <= pref_width) + { + while(true) + { + int new_width = (used_width * 9) / 10; + rt.setWidth(new_width); + int new_height = rt.height(); + if (new_height > pref_height) + break; + used_width = rt.widthUsed(); + if (used_width > new_width) + break; + } + pref_width = used_width; + } + else + { + if (used_width > (pref_width *2)) + pref_width = pref_width *2; + else + pref_width = used_width; + } + + return QSize(pref_width, rt.height()); +} + +QSize KRichTextLabel::sizeHint() const +{ + return minimumSizeHint(); +} + +void KRichTextLabel::setText( const QString &text ) { + QLabel::setText(text); +} + +void KRichTextLabel::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +#include "krichtextlabel.moc" diff --git a/klaptopdaemon/krichtextlabel.h b/klaptopdaemon/krichtextlabel.h new file mode 100644 index 0000000..e03fe25 --- /dev/null +++ b/klaptopdaemon/krichtextlabel.h @@ -0,0 +1,65 @@ +/* This file is part of the KDE libraries + Copyright (C) 2005 Waldo Bastian + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KRICHTEXTLABEL_H +#define KRICHTEXTLABEL_H + +#include + +#include + +/** + * @short A replacement for QLabel that supports richtext and proper layout management + * + * @author Waldo Bastian + */ + +/* + * QLabel + */ +class KDEUI_EXPORT KRichTextLabel : public QLabel { + Q_OBJECT + +public: + /** + * Default constructor. + */ + KRichTextLabel( QWidget *parent, const char *name = 0 ); + KRichTextLabel( const QString &text, QWidget *parent, const char *name = 0 ); + + int defaultWidth() const { return m_defaultWidth; } + void setDefaultWidth(int defaultWidth); + + virtual QSize minimumSizeHint() const; + virtual QSize sizeHint() const; + QSizePolicy sizePolicy() const; + +public slots: + void setText( const QString & ); + +protected: + int m_defaultWidth; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KRichTextLabelPrivate; + KRichTextLabelPrivate *d; +}; + +#endif // KRICHTEXTLABEL_H diff --git a/klaptopdaemon/laptop_check.cpp b/klaptopdaemon/laptop_check.cpp new file mode 100644 index 0000000..7ba7b40 --- /dev/null +++ b/klaptopdaemon/laptop_check.cpp @@ -0,0 +1,53 @@ +/* + * laptop_check.cpp + * Copyright (C) 2003 Paul Campbell + * + * quick check application - runs from kcminit - makes the check + * to see if kded should be told to run the laptop daemon at + * book time + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include "daemon_state.h" +#include +#include +#include +#include +#include +static const char description[] = + I18N_NOOP("KDE laptop daemon starter"); + +static const char version[] = "v0.0.1"; + +extern void wake_laptop_daemon(); + +int +main(int argc, char **argv) +{ + KAboutData aboutData( "klaptop_check", I18N_NOOP("KLaptop"), + version, description, KAboutData::License_GPL, + "(c) 2003, Paul Campbell"); + aboutData.addAuthor("Paul Campbell",0, "paul@taniwha.com"); + KCmdLineArgs::init( argc, argv, &aboutData ); + + KApplication a; + daemon_state s; + s.load(); + if (s.need_to_run()) + wake_laptop_daemon(); + return(0); +} diff --git a/klaptopdaemon/laptop_daemon.cpp b/klaptopdaemon/laptop_daemon.cpp new file mode 100644 index 0000000..6b66a64 --- /dev/null +++ b/klaptopdaemon/laptop_daemon.cpp @@ -0,0 +1,1083 @@ +/* + * laptop_daemon.cpp + * Copyright (C) 1999 Paul Campbell + * + * this replaces kcmlaptop - there are 2 parts - one is the panels that + * put the setup configuration in the "kcmlaptop" configm, the other + * is the laptop_daemon (this guy) who watches the battery state + * and does stuff as a result + * + * This file contains the implementation of the main laptop battery monitoring daemon + * + * $Id$ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include + +#include +#include +#include +#include "laptop_daemon.h" +#include "portable.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern "C" +{ + KDE_EXPORT KDEDModule *create_klaptopdaemon(const QCString& name) { + return new laptop_daemon(name); + } +} + + +class XWidget: public QWidget { +public: + XWidget(laptop_daemon *p):QWidget(0) { pd = p; } +private: + bool x11Event(XEvent *event); + laptop_daemon *pd; +}; +bool XWidget::x11Event(XEvent *event) { return pd->x11Event(event); } + +laptop_daemon::laptop_daemon(const QCString& obj): KDEDModule(obj) +{ + xwidget = new XWidget(this); + xwidget->hide(); + kapp->installX11EventFilter(xwidget); + + mLavEnabled = false; + backoffTimer = 0; + need_wait = 0; + saved_brightness = 0; + saved_throttle = 0; + saved_performance = 0; + wake_timer = 0; + button_bright_saved=0; + button_bright_val=0; + button_saved_performance = 0; + button_saved_throttle = 0; + power_button_off = 0; + + if (laptop_portable::has_brightness()) { + brightness = laptop_portable::get_brightness(); + } else { + brightness = 0; + } + buttonThread.sethandle(this); + triggered[0] = 0; + triggered[1] = 0; + timer = 0; + dock_widget = 0; + oldTimer = 0; + sony_fd = -1; + sony_notifier = 0; + knownFullyCharged = 0; + sony_disp = 0; + connect(this, SIGNAL(signal_checkBattery()), SLOT(checkBatteryNow())); + + //hasAudio = (audioServer.serverStatus() == 0) ? true : false; + + // FIXME: make these configurable. Some system definitely don't + // use /var/run/stab + if (!access("/var/run/stab", R_OK|F_OK)) + _pcmcia = new KPCMCIA(8, "/var/run/stab"); + else if (!access("/var/lib/pcmcia/stab", R_OK|F_OK)) + _pcmcia = new KPCMCIA(8, "/var/lib/pcmcia/stab"); + else _pcmcia = NULL; + + if (_pcmcia) + connect(_pcmcia, SIGNAL(cardUpdated(int)), this, SLOT(updatePCMCIA(int))); + connect( &autoLock, SIGNAL(timeout()), this, SLOT(timerDone()) ); + +} + +laptop_daemon::~laptop_daemon() +{ + delete xwidget; + delete _pcmcia; + delete dock_widget; + delete sony_notifier; + if (sony_disp) + XCloseDisplay(sony_disp); +} + +void +laptop_daemon::quit() +{ + deleteLater(); +} + +void laptop_daemon::restart() +{ + if (oldTimer > 0) { + killTimer(oldTimer); + oldTimer=0; + } + if (timer) { + autoLock.stop(); + timer = 0; + } + s.load(); + if (s.has_brightness) { + brightness = laptop_portable::get_brightness(); + } else { + brightness = 0; + } + + if (!s.need_to_run()) { + quit(); + return; + } + + if (sony_fd < 0) + sony_fd = ::open("/dev/sonypi", O_RDONLY|O_NONBLOCK); + if (s.sony_enablescrollbar||s.sony_middleemulation) { + if (sony_disp == 0 && sony_fd >= 0) + sony_disp = XOpenDisplay(NULL); + if (sony_fd < 0 || sony_disp == 0) { + s.sony_enablescrollbar = 0; + s.sony_middleemulation = 0; + } + } + + // change the dock state if necessary + + if (s.enabled) { + if (!dock_widget) { + dock_widget = new laptop_dock(this); + dock_widget->setPCMCIA(_pcmcia); + dock_widget->show(); + } + dock_widget->reload_icon(); + dock_widget->SetupPopup(); + } else { + if (dock_widget) { + delete dock_widget; + dock_widget = 0; + } + } + + if (s.enable_lid_button && (lid_state = laptop_portable::get_button(laptop_portable::LidButton))) { + if (s.button_lid_bright_enabled) + SetBrightness(0, s.button_lid_bright_val); + if (s.button_lid_performance_enabled) + SetPerformance(s.button_lid_performance_val); + if (s.button_lid_throttle_enabled) + SetThrottle(s.button_lid_throttle_val); + switch (s.button_lid) { + case 1: invokeStandby(); + break; + case 2: invokeSuspend(); + break; + case 3: invokeHibernate(); + break; + case 4: invokeLogout(); + break; + case 5: invokeShutdown(); + break; + } + } + if (s.enable_power_button && (power_state = laptop_portable::get_button(laptop_portable::PowerButton))) { + if (s.button_power_bright_enabled) + SetBrightness(0, s.button_power_bright_val); + if (s.button_power_performance_enabled) + SetPerformance(s.button_power_performance_val); + if (s.button_power_throttle_enabled) + SetThrottle(s.button_power_throttle_val); + switch (s.button_power) { + case 1: invokeStandby(); + break; + case 2: invokeSuspend(); + break; + case 3: invokeHibernate(); + break; + case 4: invokeLogout(); + break; + case 5: invokeShutdown(); + break; + } + } + if (s.button_power_bright_enabled || s.button_power_performance_enabled || s.button_power_throttle_enabled || + s.button_lid_bright_enabled || s.button_lid_performance_enabled || s.button_lid_throttle_enabled || + s.button_lid != 0 || s.button_power != 0) { // need a fast thread to poll every sec + if (!buttonThread.running()) { + buttonThread.start(); + } + } else { + if (buttonThread.running()) { + buttonThread.quit(); + buttonThread.done(); + } + } + + + // Do setup + struct power_result p = laptop_portable::poll_battery_state(); + powered = p.powered; + + need_wait = 0; + saved_brightness = 0; + saved_throttle = 0; + saved_performance = 0; + if (s.power_action[0] || s.power_action[1] || s.power_brightness_enabled[0] || s.power_brightness_enabled[0] || + s.power_performance_enabled[0] || s.power_performance_enabled[1] || s.power_throttle_enabled[0] || s.power_throttle_enabled[1]) { + power_time = s.power_wait[powered?0:1]; + timer = 1; + setLoadAverage(s.lav_enabled[powered?0:1], s.lav_val[powered?0:1]); + autoLock.setTimeout(power_time); + autoLock.start(); + } else { + timer = 0; + } + + + if (s.useBlankSaver) { + setBlankSaver(!p.powered); + } + + start_monitor(); + + // brightness control + + if (s.has_brightness) { + if (s.bright_pon && powered) { + SetBrightness(0, s.bright_son); + } else + if (s.bright_poff && !powered) { + SetBrightness(0, s.bright_soff); + } + } + if (s.has_performance) { + if (s.performance_pon && powered) { + SetPerformance(s.performance_val_on); + } else + if (s.performance_poff && !powered) { + SetPerformance(s.performance_val_off); + } + } + if (s.has_throttle) { + if (s.throttle_pon && powered) { + SetThrottle(s.throttle_val_on); + } else + if (s.throttle_poff && !powered) { + SetThrottle(s.throttle_val_off); + } + } + + // sony support + + if (s.sony_enablescrollbar||s.sony_middleemulation) { + if (sony_notifier == 0) { + sony_notifier = new QSocketNotifier( sony_fd, QSocketNotifier::Read, this ); + if (sony_notifier) + QObject::connect( sony_notifier, SIGNAL(activated(int)), + this, SLOT(sonyDataReceived()) ); + } + } else { + if (sony_notifier) { + delete sony_notifier; + sony_notifier = 0; + } + } +} + + +void laptop_daemon::setBlankSaver(bool blanked) +{ + QByteArray ba; + QDataStream ds(ba, IO_WriteOnly); + ds << bool(blanked); + // can't use kapp->dcopClient() because it breaks KUniqueApplication + DCOPClient c; + c.attach(); + c.send("kdesktop", "KScreensaverIface", "setBlankOnly(bool)", ba); + c.detach(); +} + + +void laptop_daemon::timerDone() +{ + if (mLavEnabled && laptop_portable::get_load_average() >= mLav) { + autoLock.postpone(); // will call timerDone() again later + return; + } + int action; + + timer = 0; + autoLock.stop(); // stop - see the note below about backoff + if (powered) { + action = s.power_action[0]; + } else { + action = s.power_action[1]; + } + switch (action) { + case 1: invokeStandby(); + break; + case 2: invokeSuspend(); + break; + case 3: invokeHibernate(); + break; + } + if ((powered?s.power_brightness_enabled[0]:s.power_brightness_enabled[1])) { + need_wait = 1; + if (!saved_brightness) { + saved_brightness = 1; + saved_brightness_val = brightness; + } + SetBrightness(1, powered?s.power_brightness[0]:s.power_brightness[1]); + } + if ((powered?s.power_performance_enabled[0]:s.power_performance_enabled[1])) { + need_wait = 1; + if (!saved_performance) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_performance(1, current_profile, profile_list, active_list)) { + saved_performance = 1; + saved_performance_val = profile_list[current_profile]; + } + } + SetPerformance(powered?s.power_performance[0]:s.power_performance[1]); + } + if ((powered?s.power_throttle_enabled[0]:s.power_throttle_enabled[1])) { + need_wait = 1; + if (!saved_throttle) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_throttling(1, current_profile, profile_list, active_list)) { + saved_throttle = 1; + saved_throttle_val = profile_list[current_profile]; + } + } + SetPerformance(powered?s.power_throttle[0]:s.power_throttle[1]); + } + // + // we must give ourself enough time to handle any necessary evil before we start looking again + // (many of the above things cause unexpected time discontinuities) + // + if (need_wait) { + wakepos.setX(QCursor::pos().x()); + wakepos.setY(QCursor::pos().y()); + if (!wake_timer) { + wake_timer = new QTimer(this); + connect(wake_timer, SIGNAL(timeout()), this, SLOT(WakeCheck())); + wake_timer->start(1*1000, 1); + } + } else { + if (!backoffTimer) { + backoffTimer = new QTimer(this); + connect(backoffTimer, SIGNAL(timeout()), this, SLOT(BackoffRestart())); + backoffTimer->start(60*1000, 1); + } + } +} + +void +laptop_daemon::BackoffRestart() +{ + delete backoffTimer; + backoffTimer = 0; + if (!timer) { + timer = 1; + autoLock.start(); + } +} + +void +laptop_daemon::WakeCheck() +{ + if (!wake_timer) + return; + if (!need_wait) { + wake_timer->stop(); + delete wake_timer; + wake_timer = 0; + return; + } + if (wakepos.x() != QCursor::pos().x() || wakepos.y() != QCursor::pos().y()) { + wake_timer->stop(); + delete wake_timer; + wake_timer = 0; + WakeUpAuto(); + } +} + +void +laptop_daemon::WakeUpAuto() +{ + if (!need_wait) + return; + need_wait = 0; + if (saved_brightness) { + SetBrightness(0, saved_brightness_val); + saved_brightness = 0; + } + if (saved_throttle) { + SetThrottle(saved_throttle_val); + saved_throttle = 0; + } + if (saved_performance) { + SetPerformance(saved_performance_val); + saved_performance = 0; + } + if (!timer) { + timer = 1; + autoLock.start(); + } +} + +bool +laptop_daemon::x11Event(XEvent *event) +{ + switch (event->type) { + case KeyPress: + case ButtonPress: + if (need_wait) + WakeUpAuto(); + break; + + } + return(0); +} + +void laptop_daemon::dock_quit() +{ + if (dock_widget) + delete dock_widget; + dock_widget = 0; +} + + +void laptop_daemon::updatePCMCIA(int num) +{ + Q_UNUSED(num); + //kdDebug() << "PCMCIA card " << num << " was updated." << endl; + + // Two things we do here. We provide notifications for cards + // being inserted / cards going to sleep / cards waking up + // and cards being safe to eject. + // The second thing we do is provide the desktop icon actions + // via dcop. +} + + +void laptop_daemon::haveBatteryLow(int t, const int num, const int type) +{ + displayPixmap(); + + // beep if we are allowed to + if (s.systemBeep[t]) { + //KNotifyClient::beep(); + (void)kapp->beep(); + } + + // run a command if we have to + if (s.runCommand[t]) { + // make sure the command exists + if (!s.runCommandPath[t].isEmpty()) { + KProcess command; + command << s.runCommandPath[t]; + command.start(KProcess::DontCare); + } + } + + if (s.do_brightness[t]) + SetBrightness(0, s.val_brightness[t]); + if (s.do_throttle[t]) + SetThrottle(s.val_throttle[t]); + if (s.do_performance[t]) + SetPerformance(s.val_performance[t]); + + // play a sound if we have to + if (s.playSound[t]) { + KAudioPlayer::play(s.playSoundPath[t]); + } + + + if (s.do_hibernate[t]) + invokeHibernate(); + if (s.do_suspend[t]) + invokeSuspend(); + if (s.do_standby[t]) + invokeStandby(); + if (s.logout[t]) + invokeLogout(); + if (s.shutdown[t]) + invokeShutdown(); + // notify if we must (must be last since it's synchronous) + if (s.notify[t]) { + if (type) { + if (s.time_based_action_critical) { + KPassivePopup::message(i18n("Battery power is running out."), + i18n("%1 % charge left.").arg(num), + BarIcon("laptop_battery"), dock_widget, + 0, 20000); + } else { + // Will this ever be reached? + KPassivePopup::message(i18n("Battery power is running out."), + i18n("%1 % charge left.").arg(num), + BarIcon("laptop_battery"), dock_widget, + 0, 20000); + } + } + else { + if (s.time_based_action_low) { + KPassivePopup::message(i18n("Battery power is running out."), + i18n("1 minute left.","%n minutes left.", num), + BarIcon("laptop_battery"), dock_widget, + 0, 20000); + } else { + KPassivePopup::message(i18n("Battery power is running out."), + i18n("1% left.", "%n percent left.", num), + BarIcon("laptop_battery"), dock_widget, + 0, 20000); + } + } + } +} + +int laptop_daemon::calcBatteryTime(int percent, long time, bool restart) +{ +#define MAX_SAMPLES_USED 3 + static int percents[MAX_SAMPLES_USED]; + static long times[MAX_SAMPLES_USED]; + static int lastused=-1; + int r=-1; + + if ( (lastused==-1) || restart ) + { + percents[0]=percent; + times[0]=time; + lastused=0; + } + else + { + // Add the % and time to the arrays + // (or just update the time if the % hasn't changed) + if (percents[lastused]!=percent) + if (lastused!=MAX_SAMPLES_USED-1) + { + lastused++; + percents[lastused]=percent; + times[lastused]=time; + } + else + { + for (int i=1;i1; c--) + { + for (int i=0; i(tt[0]-(tp[0]/(tp[1]-tp[0]))*(tt[1]-tt[0])-time); + + + } + + return r; +} + +void laptop_daemon::checkBatteryNow() +{ + struct power_result p; + + p = laptop_portable::poll_battery_state(); + + if (s.useBlankSaver && oldpowered != p.powered) { + setBlankSaver(!p.powered); + } + + powered = p.powered; + left = p.time; + val = p.percentage; + + if (oldpowered != powered && s.has_brightness) { + if (s.bright_pon && powered) { + SetBrightness(0, s.bright_son); + } else + if (s.bright_poff && !powered) { + SetBrightness(0, s.bright_soff); + } + if (s.performance_pon && powered) { + SetPerformance(s.performance_val_on); + } else + if (s.performance_poff && !powered) { + SetPerformance(s.performance_val_off); + } + if (s.throttle_pon && powered) { + SetThrottle(s.throttle_val_on); + } else + if (s.throttle_poff && !powered) { + SetThrottle(s.throttle_val_off); + } + + } + + if (left==-1) // Let's try to calculate the expected battery time left + { + timeval tv; + gettimeofday(&tv, 0); + left=calcBatteryTime(((powered)?100-val:val), tv.tv_sec, oldpowered!=powered ); + } + + if (timer && oldpowered != powered) { + need_wait = 0; + saved_brightness = 0; + saved_throttle = 0; + saved_performance = 0; + setLoadAverage(s.lav_enabled[powered?0:1], s.lav_val[powered?0:1]); + if (power_time != s.power_wait[powered?0:1]) { + power_time = s.power_wait[powered?0:1]; + autoLock.stop(); + autoLock.setTimeout(power_time); + autoLock.start(); + } + } + if (!knownFullyCharged) { + knownFullyCharged = 1; + } else + if (s.notifyMeWhenFull && oldval != val && val == 100) + KMessageBox::queuedMessageBox(0, KMessageBox::Information, i18n("Your battery is now fully charged."), i18n("Laptop Battery")); + changed = oldpowered != powered||oldexists != s.exists||oldval != val || oldleft!=left; + oldpowered = powered; + oldexists = s.exists; + oldval = val; + oldleft = left; + if (changed) + displayPixmap(); +} + +void laptop_daemon::start_monitor() +{ + checkBatteryNow(); + displayPixmap(); + oldTimer = startTimer(s.poll * 1000); +} + +void laptop_daemon::setPollInterval(const int interval) +{ + s.poll = interval; + + // Kill any old timers that may be running + if (oldTimer > 0) { + killTimer(oldTimer); + + // Start a new timer will the specified time + oldTimer = startTimer(interval * 1000); + + emit(signal_checkBattery()); + } +} + +void laptop_daemon::timerEvent(QTimerEvent *) +{ + emit(signal_checkBattery()); +} + +void laptop_daemon::displayPixmap() +{ + if (s.have_time == 2 && s.exists && !powered) { // in some circumstances + s.have_time = (val < 0 ? 0 : 1); // the battery is not charging + KConfig *config = new KConfig("kcmlaptoprc"); + if (config) { + config->setGroup("BatteryLow"); // we can;t figure this out 'till + config->writeEntry("HaveTime", s.have_time); + config->sync(); + delete config; + } + } + + if (dock_widget) + dock_widget->displayPixmap(); + + if (left >= 0) { + if (!triggered[0]) { + if (s.time_based_action_low) { + if (s.exists && !powered && left <= s.low[0]) { + triggered[0] = 1; + haveBatteryLow(0, left, 0); + } + } else { + if (s.exists && !powered && val <= s.low[1]) { + triggered[0] = 1; + haveBatteryLow(0, val, 0); + } + } + } + if (!triggered[1]) { + if (s.time_based_action_critical) { + if (s.exists && !powered && left <= s.low[2]) { + triggered[1] = 1; + haveBatteryLow(1, left, 0); + } + } else { + if (s.exists && !powered && val <= s.low[3]) { + triggered[1] = 1; + haveBatteryLow(1, val, 0); + } + } + } + } + + if (s.time_based_action_low || s.time_based_action_critical) { + if (left > (s.low[2]+1)) + triggered[1] = 0; + if (left > s.low[0]) + triggered[0] = 0; + } else { + if (val > (s.low[3]+1)) + triggered[1] = 0; + if (val > s.low[1]) + triggered[0] = 0; + } + + if (s.have_time != 1) { + if (!triggered[0]) { + if (s.exists && !powered && val <= s.low[0]) { + triggered[0] = 1; + haveBatteryLow(0, val, 1); + } + } else { + if (!triggered[1]) { + if (s.exists && !powered && val <= s.low[1]) { + triggered[1] = 1; + haveBatteryLow(1, val, 1); + } + } + if (val > (s.low[1]+1)) + triggered[1] = 0; + if (val > s.low[0]) + triggered[0] = 0; + } + } +} + +void laptop_daemon::invokeStandby() +{ + laptop_portable::invoke_standby(); +} + +void laptop_daemon::invokeSuspend() +{ + laptop_portable::invoke_suspend(); +} + +void laptop_daemon::invokeHibernate() +{ + laptop_portable::invoke_hibernation(); +} + +void laptop_daemon::invokeLogout() +{ + bool rc = kapp->requestShutDown(KApplication::ShutdownConfirmNo, KApplication::ShutdownTypeNone, KApplication::ShutdownModeForceNow); + if (!rc) + KMessageBox::sorry(0, i18n("Logout failed.")); +} + +void laptop_daemon::invokeShutdown() +{ + bool rc = kapp->requestShutDown(KApplication::ShutdownConfirmNo, KApplication::ShutdownTypeHalt, KApplication::ShutdownModeForceNow); + if (!rc) + KMessageBox::sorry(0, i18n("Shutdown failed.")); +} + +/* + * Portions of the following code borrowed with thanks from: + * + * Sony Programmable I/O Control Device driver for VAIO. + * Userspace X11 Daemon Utility + * + * Copyright 2001 Stelian Pop, Alcove + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +static void simulateButton(Display *disp, int button) { + XTestGrabControl(disp, True); + XTestFakeButtonEvent(disp, button, True, 0); + XTestFakeButtonEvent(disp, button, False, 0); + XSync(disp, False); + XTestGrabControl(disp, False); +} + +static void simulateButtonDown(Display *disp, int button) { + XTestGrabControl(disp, True); + XTestFakeButtonEvent(disp, button, True, 0); + XSync(disp, False); + XTestGrabControl(disp, False); +} + +static void simulateButtonUp(Display *disp, int button) { + XTestGrabControl(disp, True); + XTestFakeButtonEvent(disp, button, False, 0); + XSync(disp, False); + XTestGrabControl(disp, False); +} + +#define SONYPI_EVENT_JOGDIAL_DOWN 1 +#define SONYPI_EVENT_JOGDIAL_UP 2 +#define SONYPI_EVENT_JOGDIAL_DOWN_PRESSED 3 +#define SONYPI_EVENT_JOGDIAL_UP_PRESSED 4 +#define SONYPI_EVENT_JOGDIAL_PRESSED 5 +#define SONYPI_EVENT_JOGDIAL_RELEASED 6 + +void laptop_daemon::sonyDataReceived() +{ + unsigned char event; + + if (::read(sony_fd, &event, sizeof(event)) != sizeof(event)) + return; + switch(event) { + case SONYPI_EVENT_JOGDIAL_UP: + if (sony_disp && s.sony_enablescrollbar) { + simulateButton(sony_disp, 4); + } + break; + case SONYPI_EVENT_JOGDIAL_DOWN: + if (sony_disp && s.sony_enablescrollbar) { + simulateButton(sony_disp, 5); + } + break; + case SONYPI_EVENT_JOGDIAL_PRESSED: + if (sony_disp && s.sony_middleemulation) { + simulateButtonDown(sony_disp, 2); + } + break; + case SONYPI_EVENT_JOGDIAL_RELEASED: + if (sony_disp && s.sony_middleemulation) { + simulateButtonUp(sony_disp, 2); + } + break; + default: + break; + } +} + +void laptop_daemon::SetBrightness(bool blank, int v) +{ + if (v < 0) + return; + brightness = v; + laptop_portable::set_brightness(blank, v); +} + +void laptop_daemon::SetThrottle(QString v) +{ + laptop_portable::set_system_throttling(v); +} + +void laptop_daemon::SetPerformance(QString v) +{ + laptop_portable::set_system_performance(v); +} + +void +ButtonThread::run() +{ + while (!quitting) { + handle->ButtonThreadInternals(); + msleep(500); // have to run fast because if the power button is held down for too long + } // the system actually gets powered off +} + +void +laptop_daemon::ButtonThreadInternals() +{ + // + // the lid button turns stuff on when it's down and back off again when it's raised + // (kind of like the fridge door light) + // + if (lid_state != laptop_portable::get_button(laptop_portable::LidButton)) { + lid_state = !lid_state; + if (lid_state) { + if (s.button_lid_bright_enabled) { + if (!button_bright_val) + button_bright_val = brightness; + button_bright_saved = 1; + SetBrightness(1, s.button_lid_bright_val); + } + if (s.button_lid_performance_enabled) { + if (!button_saved_performance) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_performance(1, current_profile, profile_list, active_list)) { + button_saved_performance = 1; + button_saved_performance_val = profile_list[current_profile]; + } + } + SetPerformance(s.button_lid_performance_val); + } + if (s.button_lid_throttle_enabled) { + if (!button_saved_throttle) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_throttling(1, current_profile, profile_list, active_list)) { + button_saved_throttle = 1; + button_saved_throttle_val = profile_list[current_profile]; + } + } + SetThrottle(s.button_lid_throttle_val); + } + switch (s.button_lid) { + case 1: invokeStandby(); + break; + case 2: invokeSuspend(); + break; + case 3: invokeHibernate(); + break; + case 4: invokeLogout(); + break; + case 5: invokeShutdown(); + break; + } + } else { + if (button_bright_saved) { + SetBrightness(0, button_bright_val); + button_bright_saved = 0; + } + if (button_saved_performance) { + button_saved_performance = 0; + SetPerformance( button_saved_performance_val); + } + if (button_saved_throttle) { + button_saved_throttle = 0; + SetThrottle(button_saved_throttle_val); + } + } + } + // + // the power button on the other hand is an off/on switch for non-suspend type ops + // + if (power_state != laptop_portable::get_button(laptop_portable::PowerButton)) { + power_state = !power_state; + if (power_state) { + if (power_button_off) { + if (button_bright_saved) { + SetBrightness(0, button_bright_val); + button_bright_saved = 0; + } + if (button_saved_performance) { + button_saved_performance = 0; + SetPerformance( button_saved_performance_val); + } + if (button_saved_throttle) { + button_saved_throttle = 0; + SetThrottle(button_saved_throttle_val); + } + } else { + if (s.button_power_bright_enabled) { + if (!button_bright_val) + button_bright_val = brightness; + button_bright_saved = 1; + SetBrightness(1, s.button_power_bright_val); + } + if (s.button_power_performance_enabled) { + if (!button_saved_performance) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_performance(1, current_profile, profile_list, active_list)) { + button_saved_performance = 1; + button_saved_performance_val = profile_list[current_profile]; + } + } + SetPerformance(s.button_power_performance_val); + } + if (s.button_power_throttle_enabled) { + if (!button_saved_throttle) { + QStringList profile_list; + int current_profile; + bool *active_list; + if (laptop_portable::get_system_throttling(1, current_profile, profile_list, active_list)) { + button_saved_throttle = 1; + button_saved_throttle_val = profile_list[current_profile]; + } + } + SetThrottle(s.button_power_throttle_val); + } + } + switch (s.button_power) { + case 1: invokeStandby(); + break; + case 2: invokeSuspend(); + break; + case 3: invokeHibernate(); + break; + case 4: invokeLogout(); + break; + case 5: invokeShutdown(); + break; + } + power_button_off = !power_button_off; + } + } +} + +#include "laptop_daemon.moc" diff --git a/klaptopdaemon/laptop_daemon.h b/klaptopdaemon/laptop_daemon.h new file mode 100644 index 0000000..b1537e1 --- /dev/null +++ b/klaptopdaemon/laptop_daemon.h @@ -0,0 +1,186 @@ +#ifndef LAPTOPDAEMON +#define LAPTOPDAEMON 1 +/* + * laptop_daemon.h + * Copyright (C) 1999 Paul Campbell + * + * This file contains the implementation of the main laptop battery monitoring daemon + * + * $Id$ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "daemon_state.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +//#include +#include + +#include +#include + +#include + + + +#include +#include + +#include "kpcmcia.h" + +#include "daemondock.h" +#include "xautolock.h" +#include + + +class laptop_daemon; +class XWidget; + +class ButtonThread : public QThread { +public: + ButtonThread() { quitting = 0; } + void sethandle(laptop_daemon *h) { handle = h; } + void quit() { quitting = 1; } // make it quit + void done() { while (!finished()) msleep(100); quitting = 0; }// wait 'till it's done + virtual void run(); +private: + bool quitting; + laptop_daemon *handle; +}; + +class laptop_dock; +class laptop_daemon: public KDEDModule +{ + Q_OBJECT + K_DCOP +public: + laptop_daemon(const QCString& obj); + ~laptop_daemon(); + void setPollInterval(const int poll=60); + void SetBrightness(bool blank, int v); // routine to do it + int GetBrightness() { return brightness; } + void SetThrottle(QString v); + void SetPerformance(QString v); + void ButtonThreadInternals(); +k_dcop: + void restart(); + void quit(); +signals: + void signal_checkBattery(); +protected: + void timerEvent(QTimerEvent *); +protected slots: + void checkBatteryNow(); + void timerDone(); + void dock_quit(); + void updatePCMCIA(int num); + void sonyDataReceived(); + void BackoffRestart(); + void WakeCheck(); +private: + void haveBatteryLow(int t, const int num, const int type); + int calcBatteryTime(int percent, long time, bool restart); + void start_monitor(); + void invokeStandby(); + void invokeSuspend(); + void invokeHibernate(); + void invokeShutdown(); + void invokeLogout(); + void displayPixmap(); + void setBlankSaver(bool); + void setLoadAverage(bool enable, float value) {mLavEnabled=enable&&(value>=0.0); mLav=value;} + + laptop_dock *dock_widget; + + // Capability + bool hasAudio; + //KAudio audioServer; + + // General settings +public: + int val; + int powered; + int left; + bool x11Event(XEvent *event); + bool exists() { return s.exists; } + QString noBatteryIcon() { return s.noBatteryIcon; } + QString chargeIcon() { return s.chargeIcon; } + QString noChargeIcon() { return s.noChargeIcon; } +protected: + int triggered[2]; + + int oldval, oldexists, oldpowered, oldleft, knownFullyCharged; + + int changed; + + int oldTimer; + bool timer; // autolock timer is active + + int power_time; + + // PCMCIA related + KPCMCIA *_pcmcia; + + // sony jog-bar support + + int sony_fd; // file desc form open /dev/sonypi + Display *sony_disp; // X display + QSocketNotifier *sony_notifier; // how we know data is waiting + + // brightness + + int brightness; // actual brightness, -1 if not known + + bool lid_state; + bool power_state; + ButtonThread buttonThread; + + + // + XAutoLock autoLock; // timer/UI maint + float mLav; + bool mLavEnabled; + bool need_wait; // undo sleep stuff + bool saved_brightness, saved_throttle, saved_performance; + int saved_brightness_val; + QString saved_performance_val, saved_throttle_val; + QTimer *wake_timer; // the timer for the above running + QPoint wakepos; // the mouse pos at the beginning of time + void WakeUpAuto(); + QTimer *backoffTimer; // backoff + + bool power_button_off; // imagined state of the power button + bool button_bright_saved; // saved button state + int button_bright_val; + bool button_saved_performance; + QString button_saved_performance_val; + bool button_saved_throttle; + QString button_saved_throttle_val; + + daemon_state s; // saved daemon state from config file + + XWidget *xwidget; +}; +#endif diff --git a/klaptopdaemon/linux/bulkmem.h b/klaptopdaemon/linux/bulkmem.h new file mode 100644 index 0000000..e0bafc8 --- /dev/null +++ b/klaptopdaemon/linux/bulkmem.h @@ -0,0 +1,184 @@ +/* + * Definitions for bulk memory services + * + * bulkmem.h 1.8 1998/05/10 12:10:34 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + * bulkmem.h 1.3 1995/05/27 04:49:49 + */ + +#ifndef _LINUX_BULKMEM_H +#define _LINUX_BULKMEM_H + +/* For GetFirstRegion and GetNextRegion */ +typedef struct region_info_t { + u_int Attributes; + u_int CardOffset; + u_int RegionSize; + u_int AccessSpeed; + u_int BlockSize; + u_int PartMultiple; + u_char JedecMfr, JedecInfo; + memory_handle_t next; +} region_info_t; + +#define REGION_TYPE 0x0001 +#define REGION_TYPE_CM 0x0000 +#define REGION_TYPE_AM 0x0001 +#define REGION_PREFETCH 0x0008 +#define REGION_CACHEABLE 0x0010 +#define REGION_BAR_MASK 0xe000 +#define REGION_BAR_SHIFT 13 + +/* For OpenMemory */ +typedef struct open_mem_t { + u_int Attributes; + u_int Offset; +} open_mem_t; + +/* Attributes for OpenMemory */ +#define MEMORY_TYPE 0x0001 +#define MEMORY_TYPE_CM 0x0000 +#define MEMORY_TYPE_AM 0x0001 +#define MEMORY_EXCLUSIVE 0x0002 +#define MEMORY_PREFETCH 0x0008 +#define MEMORY_CACHEABLE 0x0010 +#define MEMORY_BAR_MASK 0xe000 +#define MEMORY_BAR_SHIFT 13 + +typedef struct eraseq_entry_t { + memory_handle_t Handle; + u_char State; + u_int Size; + u_int Offset; + void *Optional; +} eraseq_entry_t; + +typedef struct eraseq_hdr_t { + int QueueEntryCnt; + eraseq_entry_t *QueueEntryArray; +} eraseq_hdr_t; + +#define ERASE_QUEUED 0x00 +#define ERASE_IN_PROGRESS(n) (((n) > 0) && ((n) < 0x80)) +#define ERASE_IDLE 0xff +#define ERASE_PASSED 0xe0 +#define ERASE_FAILED 0xe1 + +#define ERASE_MISSING 0x80 +#define ERASE_MEDIA_WRPROT 0x84 +#define ERASE_NOT_ERASABLE 0x85 +#define ERASE_BAD_OFFSET 0xc1 +#define ERASE_BAD_TECH 0xc2 +#define ERASE_BAD_SOCKET 0xc3 +#define ERASE_BAD_VCC 0xc4 +#define ERASE_BAD_VPP 0xc5 +#define ERASE_BAD_SIZE 0xc6 + +/* For CopyMemory */ +typedef struct copy_op_t { + u_int Attributes; + u_int SourceOffset; + u_int DestOffset; + u_int Count; +} copy_op_t; + +/* For ReadMemory and WriteMemory */ +typedef struct mem_op_t { + u_int Attributes; + u_int Offset; + u_int Count; +} mem_op_t; + +#define MEM_OP_BUFFER 0x01 +#define MEM_OP_BUFFER_USER 0x00 +#define MEM_OP_BUFFER_KERNEL 0x01 +#define MEM_OP_DISABLE_ERASE 0x02 +#define MEM_OP_VERIFY 0x04 + +/* For RegisterMTD */ +typedef struct mtd_reg_t { + u_int Attributes; + u_int Offset; + u_long MediaID; +} mtd_reg_t; + +/* + * Definitions for MTD requests + */ + +typedef struct mtd_request_t { + u_int SrcCardOffset; + u_int DestCardOffset; + u_int TransferLength; + u_int Function; + u_long MediaID; + u_int Status; + u_int Timeout; +} mtd_request_t; + +/* Fields in MTD Function */ +#define MTD_REQ_ACTION 0x003 +#define MTD_REQ_ERASE 0x000 +#define MTD_REQ_READ 0x001 +#define MTD_REQ_WRITE 0x002 +#define MTD_REQ_COPY 0x003 +#define MTD_REQ_NOERASE 0x004 +#define MTD_REQ_VERIFY 0x008 +#define MTD_REQ_READY 0x010 +#define MTD_REQ_TIMEOUT 0x020 +#define MTD_REQ_LAST 0x040 +#define MTD_REQ_FIRST 0x080 +#define MTD_REQ_KERNEL 0x100 + +/* Status codes */ +#define MTD_WAITREQ 0x00 +#define MTD_WAITTIMER 0x01 +#define MTD_WAITRDY 0x02 +#define MTD_WAITPOWER 0x03 + +/* + * Definitions for MTD helper functions + */ + +/* For MTDModifyWindow */ +typedef struct mtd_mod_win_t { + u_int Attributes; + u_int AccessSpeed; + u_int CardOffset; +} mtd_mod_win_t; + +/* For MTDSetVpp */ +typedef struct mtd_vpp_req_t { + u_char Vpp1, Vpp2; +} mtd_vpp_req_t; + +/* For MTDRDYMask */ +typedef struct mtd_rdy_req_t { + u_int Mask; +} mtd_rdy_req_t; + +enum mtd_helper { + MTDRequestWindow, MTDModifyWindow, MTDReleaseWindow, + MTDSetVpp, MTDRDYMask +}; + +#ifdef IN_CARD_SERVICES +extern int MTDHelperEntry(int func, void *a1, void *a2); +#else +extern int MTDHelperEntry(int func, ...); +#endif + +#endif /* _LINUX_BULKMEM_H */ diff --git a/klaptopdaemon/linux/ciscode.h b/klaptopdaemon/linux/ciscode.h new file mode 100644 index 0000000..1c536d1 --- /dev/null +++ b/klaptopdaemon/linux/ciscode.h @@ -0,0 +1,96 @@ +/* + * ciscode.h 1.31 1999/02/16 01:16:46 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_CISCODE_H +#define _LINUX_CISCODE_H + +/* Manufacturer and Product ID codes */ + +#define MANFID_3COM 0x0101 +#define PRODID_3COM_3CXEM556 0x0035 +#define PRODID_3COM_3CCFEM556 0x0556 +#define PRODID_3COM_3C562 0x0562 + +#define MANFID_ADAPTEC 0x012f +#define PRODID_ADAPTEC_SCSI 0x0001 + +#define MANFID_ATT 0xffff +#define PRODID_ATT_KIT 0x0100 + +#define MANFID_CONTEC 0xc001 + +#define MANFID_FUJITSU 0x0004 +#define PRODID_FUJITSU_MBH10302 0x0004 +#define PRODID_FUJITSU_MBH10304 0x1003 +#define PRODID_FUJITSU_LA501 0x2000 + +#define MANFID_IBM 0x00a4 +#define PRODID_IBM_HOME_AND_AWAY 0x002e + +#define MANFID_INTEL 0x0089 +#define PRODID_INTEL_DUAL_RS232 0x0301 +#define PRODID_INTEL_2PLUS 0x8422 + +#define MANFID_LINKSYS 0x0143 +#define PRODID_LINKSYS_PCMLM28 0xc0ab +#define PRODID_LINKSYS_3400 0x3341 + +#define MANFID_MEGAHERTZ 0x0102 +#define PRODID_MEGAHERTZ_VARIOUS 0x0000 +#define PRODID_MEGAHERTZ_EM3288 0x0006 + +#define MANFID_MACNICA 0xc00b + +#define MANFID_MOTOROLA 0x0109 +#define PRODID_MOTOROLA_MARINER 0x0501 + +#define MANFID_NEW_MEDIA 0x0057 + +#define MANFID_OLICOM 0x0121 +#define PRODID_OLICOM_OC2231 0x3122 +#define PRODID_OLICOM_OC2232 0x3222 + +#define MANFID_OMEGA 0x0137 +#define PRODID_OMEGA_QSP_100 0x0025 + +#define MANFID_OSITECH 0x0140 +#define PRODID_OSITECH_JACK_144 0x0001 +#define PRODID_OSITECH_JACK_288 0x0002 +#define PRODID_OSITECH_JACK_336 0x0007 + +#define MANFID_PSION 0x016c + +#define MANFID_QUATECH 0x0137 +#define PRODID_QUATECH_DUAL_RS232 0x0012 +#define PRODID_QUATECH_DUAL_RS232_D1 0x0007 +#define PRODID_QUATECH_QUAD_RS232 0x001b + +#define MANFID_SMC 0x0108 +#define PRODID_SMC_ETHER 0x0105 + +#define MANFID_SOCKET 0x0104 +#define PRODID_SOCKET_DUAL_RS232 0x0006 +#define PRODID_SOCKET_LPE 0x000d + +#define MANFID_SUNDISK 0x0045 + +#define MANFID_TDK 0x0105 + +#define MANFID_XIRCOM 0x0105 + +#endif /* _LINUX_CISCODE_H */ diff --git a/klaptopdaemon/linux/cisreg.h b/klaptopdaemon/linux/cisreg.h new file mode 100644 index 0000000..ebe54fc --- /dev/null +++ b/klaptopdaemon/linux/cisreg.h @@ -0,0 +1,105 @@ +/* + * cisreg.h 1.11 1998/09/11 08:54:47 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_CISREG_H +#define _LINUX_CISREG_H + +/* Offsets from ConfigBase for CIS registers */ +#define CISREG_COR 0x00 +#define CISREG_CCSR 0x02 +#define CISREG_PRR 0x04 +#define CISREG_SCR 0x06 +#define CISREG_ESR 0x08 +#define CISREG_IOBASE_0 0x0a +#define CISREG_IOBASE_1 0x0c +#define CISREG_IOBASE_2 0x0e +#define CISREG_IOBASE_3 0x10 +#define CISREG_IOSIZE 0x12 + +/* + * Configuration Option Register + */ +#define COR_CONFIG_MASK 0x3f +#define COR_MFC_CONFIG_MASK 0x38 +#define COR_FUNC_ENA 0x01 +#define COR_ADDR_DECODE 0x02 +#define COR_IREQ_ENA 0x04 +#define COR_LEVEL_REQ 0x40 +#define COR_SOFT_RESET 0x80 + +/* + * Card Configuration and Status Register + */ +#define CCSR_INTR_ACK 0x01 +#define CCSR_INTR_PENDING 0x02 +#define CCSR_POWER_DOWN 0x04 +#define CCSR_AUDIO_ENA 0x08 +#define CCSR_IOIS8 0x20 +#define CCSR_SIGCHG_ENA 0x40 +#define CCSR_CHANGED 0x80 + +/* + * Pin Replacement Register + */ +#define PRR_WP_STATUS 0x01 +#define PRR_READY_STATUS 0x02 +#define PRR_BVD2_STATUS 0x04 +#define PRR_BVD1_STATUS 0x08 +#define PRR_WP_EVENT 0x10 +#define PRR_READY_EVENT 0x20 +#define PRR_BVD2_EVENT 0x40 +#define PRR_BVD1_EVENT 0x80 + +/* + * Socket and Copy Register + */ +#define SCR_SOCKET_NUM 0x0f +#define SCR_COPY_NUM 0x70 + +/* + * Extended Status Register + */ +#define ESR_REQ_ATTN_ENA 0x01 +#define ESR_REQ_ATTN 0x10 + +/* + * CardBus Function Status Registers + */ +#define CBFN_EVENT 0x00 +#define CBFN_MASK 0x04 +#define CBFN_STATE 0x08 +#define CBFN_FORCE 0x0c + +/* + * These apply to all the CardBus function registers + */ +#define CBFN_WP 0x0001 +#define CBFN_READY 0x0002 +#define CBFN_BVD2 0x0004 +#define CBFN_BVD1 0x0008 +#define CBFN_GWAKE 0x0010 +#define CBFN_INTR 0x8000 + +/* + * Extra bits in the Function Event Mask Register + */ +#define FEMR_BAM_ENA 0x0020 +#define FEMR_PWM_ENA 0x0040 +#define FEMR_WKUP_MASK 0x4000 + +#endif /* _LINUX_CISREG_H */ diff --git a/klaptopdaemon/linux/cistpl.h b/klaptopdaemon/linux/cistpl.h new file mode 100644 index 0000000..8fee55b --- /dev/null +++ b/klaptopdaemon/linux/cistpl.h @@ -0,0 +1,543 @@ +/* + * cistpl.h 1.27 1998/09/30 18:08:46 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_CISTPL_H +#define _LINUX_CISTPL_H + +#define CISTPL_NULL 0x00 +#define CISTPL_DEVICE 0x01 +#define CISTPL_LONGLINK_CB 0x02 +#define CISTPL_CONFIG_CB 0x04 +#define CISTPL_CFTABLE_ENTRY_CB 0x05 +#define CISTPL_LONGLINK_MFC 0x06 +#define CISTPL_BAR 0x07 +#define CISTPL_CHECKSUM 0x10 +#define CISTPL_LONGLINK_A 0x11 +#define CISTPL_LONGLINK_C 0x12 +#define CISTPL_LINKTARGET 0x13 +#define CISTPL_NO_LINK 0x14 +#define CISTPL_VERS_1 0x15 +#define CISTPL_ALTSTR 0x16 +#define CISTPL_DEVICE_A 0x17 +#define CISTPL_JEDEC_C 0x18 +#define CISTPL_JEDEC_A 0x19 +#define CISTPL_CONFIG 0x1a +#define CISTPL_CFTABLE_ENTRY 0x1b +#define CISTPL_DEVICE_OC 0x1c +#define CISTPL_DEVICE_OA 0x1d +#define CISTPL_DEVICE_GEO 0x1e +#define CISTPL_DEVICE_GEO_A 0x1f +#define CISTPL_MANFID 0x20 +#define CISTPL_FUNCID 0x21 +#define CISTPL_FUNCE 0x22 +#define CISTPL_SWIL 0x23 +#define CISTPL_END 0xff +/* Layer 2 tuples */ +#define CISTPL_VERS_2 0x40 +#define CISTPL_FORMAT 0x41 +#define CISTPL_GEOMETRY 0x42 +#define CISTPL_BYTEORDER 0x43 +#define CISTPL_DATE 0x44 +#define CISTPL_BATTERY 0x45 +/* Layer 3 tuples */ +#define CISTPL_ORG 0x46 + +typedef struct cistpl_longlink_t { + u_int addr; +} cistpl_longlink_t; + +typedef struct cistpl_checksum_t { + u_short addr; + u_short len; + u_char sum; +} cistpl_checksum_t; + +#define CISTPL_MAX_FUNCTIONS 8 +#define CISTPL_MFC_ATTR 0x00 +#define CISTPL_MFC_COMMON 0x01 + +typedef struct cistpl_longlink_mfc_t { + u_char nfn; + struct { + u_char space; + u_int addr; + } fn[CISTPL_MAX_FUNCTIONS]; +} cistpl_longlink_mfc_t; + +#define CISTPL_MAX_ALTSTR_STRINGS 4 + +typedef struct cistpl_altstr_t { + u_char ns; + u_char ofs[CISTPL_MAX_ALTSTR_STRINGS]; + char str[254]; +} cistpl_altstr_t; + +#define CISTPL_DTYPE_NULL 0x00 +#define CISTPL_DTYPE_ROM 0x01 +#define CISTPL_DTYPE_OTPROM 0x02 +#define CISTPL_DTYPE_EPROM 0x03 +#define CISTPL_DTYPE_EEPROM 0x04 +#define CISTPL_DTYPE_FLASH 0x05 +#define CISTPL_DTYPE_SRAM 0x06 +#define CISTPL_DTYPE_DRAM 0x07 +#define CISTPL_DTYPE_FUNCSPEC 0x0d +#define CISTPL_DTYPE_EXTEND 0x0e + +#define CISTPL_MAX_DEVICES 4 + +typedef struct cistpl_device_t { + u_char ndev; + struct { + u_char type; + u_char wp; + u_int speed; + u_int size; + } dev[CISTPL_MAX_DEVICES]; +} cistpl_device_t; + +#define CISTPL_DEVICE_MWAIT 0x01 +#define CISTPL_DEVICE_3VCC 0x02 + +typedef struct cistpl_device_o_t { + u_char flags; + cistpl_device_t device; +} cistpl_device_o_t; + +#define CISTPL_VERS_1_MAX_PROD_STRINGS 4 + +typedef struct cistpl_vers_1_t { + u_char major; + u_char minor; + u_char ns; + u_char ofs[CISTPL_VERS_1_MAX_PROD_STRINGS]; + char str[254]; +} cistpl_vers_1_t; + +typedef struct cistpl_jedec_t { + u_char nid; + struct { + u_char mfr; + u_char info; + } id[CISTPL_MAX_DEVICES]; +} cistpl_jedec_t; + +typedef struct cistpl_manfid_t { + u_short manf; + u_short card; +} cistpl_manfid_t; + +#define CISTPL_FUNCID_MULTI 0x00 +#define CISTPL_FUNCID_MEMORY 0x01 +#define CISTPL_FUNCID_SERIAL 0x02 +#define CISTPL_FUNCID_PARALLEL 0x03 +#define CISTPL_FUNCID_FIXED 0x04 +#define CISTPL_FUNCID_VIDEO 0x05 +#define CISTPL_FUNCID_NETWORK 0x06 +#define CISTPL_FUNCID_AIMS 0x07 +#define CISTPL_FUNCID_SCSI 0x08 + +#define CISTPL_SYSINIT_POST 0x01 +#define CISTPL_SYSINIT_ROM 0x02 + +typedef struct cistpl_funcid_t { + u_char func; + u_char sysinit; +} cistpl_funcid_t; + +typedef struct cistpl_funce_t { + u_char type; + u_char data[1]; +} cistpl_funce_t; + +/*====================================================================== + + Modem Function Extension Tuples + +======================================================================*/ + +#define CISTPL_FUNCE_SERIAL 0x00 +#define CISTPL_FUNCE_SERIAL_DATA 0x08 +#define CISTPL_FUNCE_SERIAL_FAX 0x09 +#define CISTPL_FUNCE_SERIAL_VOICE 0x0a +#define CISTPL_FUNCE_CAP 0x01 +#define CISTPL_FUNCE_CAP_DATA 0x05 +#define CISTPL_FUNCE_CAP_FAX 0x06 +#define CISTPL_FUNCE_CAP_VOICE 0x07 +#define CISTPL_FUNCE_SERV_DATA 0x02 +#define CISTPL_FUNCE_SERV_FAX_1 0x13 +#define CISTPL_FUNCE_SERV_FAX_2 0x23 +#define CISTPL_FUNCE_SERV_FAX_3 0x33 +#define CISTPL_FUNCE_SERV_VOICE 0x84 + +/* UART identification */ +#define CISTPL_SERIAL_UART_8250 0x00 +#define CISTPL_SERIAL_UART_16450 0x01 +#define CISTPL_SERIAL_UART_16550 0x02 + +/* UART capabilities */ +#define CISTPL_SERIAL_UART_SPACE 0x01 +#define CISTPL_SERIAL_UART_MARK 0x02 +#define CISTPL_SERIAL_UART_ODD 0x04 +#define CISTPL_SERIAL_UART_EVEN 0x08 +#define CISTPL_SERIAL_UART_5BIT 0x01 +#define CISTPL_SERIAL_UART_6BIT 0x02 +#define CISTPL_SERIAL_UART_7BIT 0x04 +#define CISTPL_SERIAL_UART_8BIT 0x08 +#define CISTPL_SERIAL_UART_1STOP 0x10 +#define CISTPL_SERIAL_UART_MSTOP 0x20 +#define CISTPL_SERIAL_UART_2STOP 0x40 + +typedef struct cistpl_serial_t { + u_char uart_type; + u_char uart_cap_0; + u_char uart_cap_1; +} cistpl_serial_t; + +typedef struct cistpl_modem_cap_t { + u_char flow; + u_char cmd_buf; + u_int rcv_buf:24; + u_int xmit_buf:24; +} cistpl_modem_cap_t; + +typedef struct cistpl_data_serv_t { + u_char max_data_0; + u_char max_data_1; + u_char modulation_0; + u_char modulation_1; + u_char error_control; + u_char compression; + u_char cmd_protocol; + u_char escape; + u_char encrypt; + u_char misc_features; + u_char ccitt_code[1]; +} cistpl_data_serv_t; + +typedef struct cistpl_fax_serv_t { + u_char max_data_0; + u_char max_data_1; + u_char modulation; + u_char encrypt; + u_char features_0; + u_char features_1; + u_char ccitt_code[1]; +} cistpl_fax_serv_t; + +typedef struct cistpl_voice_serv_t { + u_char max_data_0; + u_char max_data_1; +} cistpl_voice_serv_t; + +/*====================================================================== + + LAN Function Extension Tuples + +======================================================================*/ + +#define CISTPL_FUNCE_LAN_TECH 0x01 +#define CISTPL_FUNCE_LAN_SPEED 0x02 +#define CISTPL_FUNCE_LAN_MEDIA 0x03 +#define CISTPL_FUNCE_LAN_NODE_ID 0x04 +#define CISTPL_FUNCE_LAN_CONNECTOR 0x05 + +/* LAN technologies */ +#define CISTPL_LAN_TECH_ARCNET 0x01 +#define CISTPL_LAN_TECH_ETHERNET 0x02 +#define CISTPL_LAN_TECH_TOKENRING 0x03 +#define CISTPL_LAN_TECH_LOCALTALK 0x04 +#define CISTPL_LAN_TECH_FDDI 0x05 +#define CISTPL_LAN_TECH_ATM 0x06 +#define CISTPL_LAN_TECH_WIRELESS 0x07 + +typedef struct cistpl_lan_tech_t { + u_char tech; +} cistpl_lan_tech_t; + +typedef struct cistpl_lan_speed_t { + u_int speed; +} cistpl_lan_speed_t; + +/* LAN media definitions */ +#define CISTPL_LAN_MEDIA_UTP 0x01 +#define CISTPL_LAN_MEDIA_STP 0x02 +#define CISTPL_LAN_MEDIA_THIN_COAX 0x03 +#define CISTPL_LAN_MEDIA_THICK_COAX 0x04 +#define CISTPL_LAN_MEDIA_FIBER 0x05 +#define CISTPL_LAN_MEDIA_900MHZ 0x06 +#define CISTPL_LAN_MEDIA_2GHZ 0x07 +#define CISTPL_LAN_MEDIA_5GHZ 0x08 +#define CISTPL_LAN_MEDIA_DIFF_IR 0x09 +#define CISTPL_LAN_MEDIA_PTP_IR 0x0a + +typedef struct cistpl_lan_media_t { + u_char media; +} cistpl_lan_media_t; + +typedef struct cistpl_lan_node_id_t { + u_char nb; + u_char id[16]; +} cistpl_lan_node_id_t; + +typedef struct cistpl_lan_connector_t { + u_char code; +} cistpl_lan_connector_t; + +/*====================================================================== + + IDE Function Extension Tuples + +======================================================================*/ + +#define CISTPL_IDE_INTERFACE 0x01 + +typedef struct cistpl_ide_interface_t { + u_char interface; +} cistpl_ide_interface_t; + +/* First feature byte */ +#define CISTPL_IDE_SILICON 0x04 +#define CISTPL_IDE_UNIQUE 0x08 +#define CISTPL_IDE_DUAL 0x10 + +/* Second feature byte */ +#define CISTPL_IDE_HAS_SLEEP 0x01 +#define CISTPL_IDE_HAS_STANDBY 0x02 +#define CISTPL_IDE_HAS_IDLE 0x04 +#define CISTPL_IDE_LOW_POWER 0x08 +#define CISTPL_IDE_REG_INHIBIT 0x10 +#define CISTPL_IDE_HAS_INDEX 0x20 +#define CISTPL_IDE_IOIS16 0x40 + +typedef struct cistpl_ide_feature_t { + u_char feature1; + u_char feature2; +} cistpl_ide_feature_t; + +#define CISTPL_FUNCE_IDE_IFACE 0x01 +#define CISTPL_FUNCE_IDE_MASTER 0x02 +#define CISTPL_FUNCE_IDE_SLAVE 0x03 + +/*====================================================================== + + Configuration Table Entries + +======================================================================*/ + +#define CISTPL_BAR_SPACE 0x07 +#define CISTPL_BAR_SPACE_IO 0x10 +#define CISTPL_BAR_PREFETCH 0x20 +#define CISTPL_BAR_CACHEABLE 0x40 +#define CISTPL_BAR_1MEG_MAP 0x80 + +typedef struct cistpl_bar_t { + u_char attr; + u_int size; +} cistpl_bar_t; + +typedef struct cistpl_config_t { + u_char last_idx; + u_int base; + u_int rmask[4]; + u_char subtuples; +} cistpl_config_t; + +/* These are bits in the 'present' field, and indices in 'param' */ +#define CISTPL_POWER_VNOM 0 +#define CISTPL_POWER_VMIN 1 +#define CISTPL_POWER_VMAX 2 +#define CISTPL_POWER_ISTATIC 3 +#define CISTPL_POWER_IAVG 4 +#define CISTPL_POWER_IPEAK 5 +#define CISTPL_POWER_IDOWN 6 + +#define CISTPL_POWER_HIGHZ_OK 0x01 +#define CISTPL_POWER_HIGHZ_REQ 0x02 + +typedef struct cistpl_power_t { + u_char present; + u_char flags; + u_int param[7]; +} cistpl_power_t; + +typedef struct cistpl_timing_t { + u_int wait, waitscale; + u_int ready, rdyscale; + u_int reserved, rsvscale; +} cistpl_timing_t; + +#define CISTPL_IO_LINES_MASK 0x1f +#define CISTPL_IO_8BIT 0x20 +#define CISTPL_IO_16BIT 0x40 +#define CISTPL_IO_RANGE 0x80 + +#define CISTPL_IO_MAX_WIN 16 + +typedef struct cistpl_io_t { + u_char flags; + u_char nwin; + struct { + u_int base; + u_int len; + } win[CISTPL_IO_MAX_WIN]; +} cistpl_io_t; + +typedef struct cistpl_irq_t { + u_int IRQInfo1; + u_int IRQInfo2; +} cistpl_irq_t; + +#define CISTPL_MEM_MAX_WIN 8 + +typedef struct cistpl_mem_t { + u_char flags; + u_char nwin; + struct { + u_int len; + u_int card_addr; + u_int host_addr; + } win[CISTPL_MEM_MAX_WIN]; +} cistpl_mem_t; + +#define CISTPL_CFTABLE_DEFAULT 0x0001 +#define CISTPL_CFTABLE_BVDS 0x0002 +#define CISTPL_CFTABLE_WP 0x0004 +#define CISTPL_CFTABLE_RDYBSY 0x0008 +#define CISTPL_CFTABLE_MWAIT 0x0010 +#define CISTPL_CFTABLE_AUDIO 0x0800 +#define CISTPL_CFTABLE_READONLY 0x1000 +#define CISTPL_CFTABLE_PWRDOWN 0x2000 + +typedef struct cistpl_cftable_entry_t { + u_char index; + u_short flags; + u_char interface; + cistpl_power_t vcc, vpp1, vpp2; + cistpl_timing_t timing; + cistpl_io_t io; + cistpl_irq_t irq; + cistpl_mem_t mem; + u_char subtuples; +} cistpl_cftable_entry_t; + +#define CISTPL_CFTABLE_MASTER 0x000100 +#define CISTPL_CFTABLE_INVALIDATE 0x000200 +#define CISTPL_CFTABLE_VGA_PALETTE 0x000400 +#define CISTPL_CFTABLE_PARITY 0x000800 +#define CISTPL_CFTABLE_WAIT 0x001000 +#define CISTPL_CFTABLE_SERR 0x002000 +#define CISTPL_CFTABLE_FAST_BACK 0x004000 +#define CISTPL_CFTABLE_BINARY_AUDIO 0x010000 +#define CISTPL_CFTABLE_PWM_AUDIO 0x020000 + +typedef struct cistpl_cftable_entry_cb_t { + u_char index; + u_int flags; + cistpl_power_t vcc, vpp1, vpp2; + u_char io; + cistpl_irq_t irq; + u_char mem; + u_char subtuples; +} cistpl_cftable_entry_cb_t; + +typedef struct cistpl_device_geo_t { + u_char ngeo; + struct { + u_char buswidth; + u_int erase_block; + u_int read_block; + u_int write_block; + u_int partition; + u_int interleave; + } geo[CISTPL_MAX_DEVICES]; +} cistpl_device_geo_t; + +typedef struct cistpl_vers_2_t { + u_char vers; + u_char comply; + u_short dindex; + u_char vspec8, vspec9; + u_char nhdr; + u_char vendor, info; + char str[244]; +} cistpl_vers_2_t; + +typedef struct cistpl_org_t { + u_char data_org; + char desc[30]; +} cistpl_org_t; + +#define CISTPL_ORG_FS 0x00 +#define CISTPL_ORG_APPSPEC 0x01 +#define CISTPL_ORG_XIP 0x02 + +typedef union cisparse_t { + cistpl_device_t device; + cistpl_checksum_t checksum; + cistpl_longlink_t longlink; + cistpl_longlink_mfc_t longlink_mfc; + cistpl_vers_1_t version_1; + cistpl_altstr_t altstr; + cistpl_jedec_t jedec; + cistpl_manfid_t manfid; + cistpl_funcid_t funcid; + cistpl_funce_t funce; + cistpl_bar_t bar; + cistpl_config_t config; + cistpl_cftable_entry_t cftable_entry; + cistpl_cftable_entry_cb_t cftable_entry_cb; + cistpl_device_geo_t device_geo; + cistpl_vers_2_t vers_2; + cistpl_org_t org; +} cisparse_t; + +typedef struct tuple_t { + u_int Attributes; + cisdata_t DesiredTuple; + u_int Flags; /* internal use */ + u_int LinkOffset; /* internal use */ + u_int CISOffset; /* internal use */ + cisdata_t TupleCode; + cisdata_t TupleLink; + cisdata_t TupleOffset; + cisdata_t TupleDataMax; + cisdata_t TupleDataLen; + cisdata_t *TupleData; +} tuple_t; + +/* Special cisdata_t value */ +#define RETURN_FIRST_TUPLE 0xff + +/* Attributes for tuple calls */ +#define TUPLE_RETURN_LINK 0x01 +#define TUPLE_RETURN_COMMON 0x02 + +/* For ValidateCIS */ +typedef struct cisinfo_t { + u_int Chains; +} cisinfo_t; + +#define CISTPL_MAX_CIS_SIZE 0x200 + +/* For ReplaceCIS */ +typedef struct cisdump_t { + u_int Length; + cisdata_t Data[CISTPL_MAX_CIS_SIZE]; +} cisdump_t; + +#endif /* LINUX_CISTPL_H */ diff --git a/klaptopdaemon/linux/cs.h b/klaptopdaemon/linux/cs.h new file mode 100644 index 0000000..b8610ca --- /dev/null +++ b/klaptopdaemon/linux/cs.h @@ -0,0 +1,455 @@ +/* + * cs.h 1.63 1998/12/09 07:36:24 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_CS_H +#define _LINUX_CS_H + +/* For AccessConfigurationRegister */ +typedef struct conf_reg_t { + u_char Function; + u_int Action; + off_t Offset; + u_int Value; +} conf_reg_t; + +/* Actions */ +#define CS_READ 1 +#define CS_WRITE 2 + +/* for AdjustResourceInfo */ +typedef struct adjust_t { + u_int Action; + u_int Resource; + u_int Attributes; + union { + struct memory { + u_long Base; + u_long Size; + } memory; + struct io { + ioaddr_t BasePort; + ioaddr_t NumPorts; + u_int IOAddrLines; + } io; + struct irq { + u_int IRQ; + } irq; + } resource; +} adjust_t; + +/* Action field */ +#define REMOVE_MANAGED_RESOURCE 1 +#define ADD_MANAGED_RESOURCE 2 +#define GET_FIRST_MANAGED_RESOURCE 3 +#define GET_NEXT_MANAGED_RESOURCE 4 +/* Resource field */ +#define RES_MEMORY_RANGE 1 +#define RES_IO_RANGE 2 +#define RES_IRQ 3 +/* Attribute field */ +#define RES_IRQ_TYPE 0x03 +#define RES_IRQ_TYPE_EXCLUSIVE 0 +#define RES_IRQ_TYPE_TIME 1 +#define RES_IRQ_TYPE_DYNAMIC 2 +#define RES_IRQ_CSC 0x04 +#define RES_SHARED 0x08 +#define RES_RESERVED 0x10 +#define RES_ALLOCATED 0x20 +#define RES_REMOVED 0x40 + +typedef struct servinfo_t { + char Signature[2]; + u_int Count; + u_int Revision; + u_int CSLevel; + char *VendorString; +} servinfo_t; + +typedef struct event_callback_args_t { + client_handle_t client_handle; + void *info; + void *mtdrequest; + void *buffer; + void *misc; + void *client_data; +} event_callback_args_t; + +/* for GetConfigurationInfo */ +typedef struct config_info_t { + u_char Function; + u_int Attributes; + u_int Vcc, Vpp1, Vpp2; + u_int IntType; + u_int ConfigBase; + u_char Status, Pin, Copy, Option, ExtStatus; + u_int Present; + u_int CardValues; + u_int AssignedIRQ; + u_int IRQAttributes; + ioaddr_t BasePort1; + ioaddr_t NumPorts1; + u_int Attributes1; + ioaddr_t BasePort2; + ioaddr_t NumPorts2; + u_int Attributes2; + u_int IOAddrLines; +} config_info_t; + +/* For CardValues field */ +#define CV_OPTION_VALUE 0x01 +#define CV_STATUS_VALUE 0x02 +#define CV_PIN_REPLACEMENT 0x04 +#define CV_COPY_VALUE 0x08 +#define CV_EXT_STATUS 0x10 + +/* For GetFirst/NextClient */ +typedef struct client_req_t { + socket_t Socket; + u_int Attributes; +} client_req_t; + +#define CLIENT_THIS_SOCKET 0x01 + +/* For RegisterClient */ +typedef struct client_reg_t { + dev_info_t *dev_info; + u_int Attributes; + u_int EventMask; + int (*event_handler)(event_t event, int priority, + event_callback_args_t *); + event_callback_args_t event_callback_args; + u_int Version; +} client_reg_t; + +/* ModifyConfiguration */ +typedef struct modconf_t { + u_int Attributes; + u_int Vcc, Vpp1, Vpp2; +} modconf_t; + +/* Attributes for ModifyConfiguration */ +#define CONF_IRQ_CHANGE_VALID 0x100 +#define CONF_VCC_CHANGE_VALID 0x200 +#define CONF_VPP1_CHANGE_VALID 0x400 +#define CONF_VPP2_CHANGE_VALID 0x800 + +/* For RequestConfiguration */ +typedef struct config_req_t { + u_int Attributes; + u_int Vcc, Vpp1, Vpp2; + u_int IntType; + u_int ConfigBase; + u_char Status, Pin, Copy, ExtStatus; + u_char ConfigIndex; + u_int Present; +} config_req_t; + +/* Attributes for RequestConfiguration */ +#define CONF_ENABLE_IRQ 0x01 +#define CONF_ENABLE_DMA 0x02 +#define CONF_ENABLE_SPKR 0x04 +#define CONF_VALID_CLIENT 0x100 + +/* IntType field */ +#define INT_MEMORY 0x01 +#define INT_MEMORY_AND_IO 0x02 +#define INT_CARDBUS 0x04 + +/* For RequestIO and ReleaseIO */ +typedef struct io_req_t { + ioaddr_t BasePort1; + ioaddr_t NumPorts1; + u_int Attributes1; + ioaddr_t BasePort2; + ioaddr_t NumPorts2; + u_int Attributes2; + u_int IOAddrLines; +} io_req_t; + +/* Attributes for RequestIO and ReleaseIO */ +#define IO_SHARED 0x01 +#define IO_FIRST_SHARED 0x02 +#define IO_FORCE_ALIAS_ACCESS 0x04 +#define IO_DATA_PATH_WIDTH 0x18 +#define IO_DATA_PATH_WIDTH_8 0x00 +#define IO_DATA_PATH_WIDTH_16 0x08 +#define IO_DATA_PATH_WIDTH_AUTO 0x10 + +/* For RequestIRQ and ReleaseIRQ */ +typedef struct irq_req_t { + u_int Attributes; + u_int AssignedIRQ; + u_int IRQInfo1, IRQInfo2; + void *Handler; + void *Instance; +} irq_req_t; + +/* Attributes for RequestIRQ and ReleaseIRQ */ +#define IRQ_TYPE 0x03 +#define IRQ_TYPE_EXCLUSIVE 0x00 +#define IRQ_TYPE_TIME 0x01 +#define IRQ_TYPE_DYNAMIC_SHARING 0x02 +#define IRQ_FORCED_PULSE 0x04 +#define IRQ_FIRST_SHARED 0x08 +#define IRQ_HANDLE_PRESENT 0x10 +#define IRQ_PULSE_ALLOCATED 0x100 + +/* Bits in IRQInfo1 field */ +#define IRQ_MASK 0x0f +#define IRQ_NMI_ID 0x01 +#define IRQ_IOCK_ID 0x02 +#define IRQ_BERR_ID 0x04 +#define IRQ_VEND_ID 0x08 +#define IRQ_INFO2_VALID 0x10 +#define IRQ_LEVEL_ID 0x20 +#define IRQ_PULSE_ID 0x40 +#define IRQ_SHARE_ID 0x80 + +typedef struct eventmask_t { + u_int Attributes; + u_int EventMask; +} eventmask_t; + +#define CONF_EVENT_MASK_VALID 0x01 + +/* Configuration registers present */ +#define PRESENT_OPTION 0x001 +#define PRESENT_STATUS 0x002 +#define PRESENT_PIN_REPLACE 0x004 +#define PRESENT_COPY 0x008 +#define PRESENT_EXT_STATUS 0x010 +#define PRESENT_IOBASE_0 0x020 +#define PRESENT_IOBASE_1 0x040 +#define PRESENT_IOBASE_2 0x080 +#define PRESENT_IOBASE_3 0x100 +#define PRESENT_IOSIZE 0x200 + +/* Attributes for Request/GetConfiguration */ +#define CONF_ENABLE_IRQ 0x01 +#define EXCLUSIVE_USE 0x02 +#define VALID_CLIENT 0x04 + +/* For MapMemPage */ +typedef struct memreq_t { + u_int CardOffset; + page_t Page; +} memreq_t; + +/* For ModifyWindow */ +typedef struct modwin_t { + u_int Attributes; + u_int AccessSpeed; +} modwin_t; + +/* For RequestWindow */ +typedef struct win_req_t { + u_int Attributes; + u_long Base; + u_int Size; + u_int AccessSpeed; +} win_req_t; + +/* Attributes for RequestWindow */ +#define WIN_ADDR_SPACE 0x0001 +#define WIN_ADDR_SPACE_MEM 0x0000 +#define WIN_ADDR_SPACE_IO 0x0001 +#define WIN_MEMORY_TYPE 0x0002 +#define WIN_MEMORY_TYPE_CM 0x0000 +#define WIN_MEMORY_TYPE_AM 0x0002 +#define WIN_ENABLE 0x0004 +#define WIN_DATA_WIDTH 0x0018 +#define WIN_DATA_WIDTH_8 0x0000 +#define WIN_DATA_WIDTH_16 0x0008 +#define WIN_DATA_WIDTH_32 0x0010 +#define WIN_PAGED 0x0020 +#define WIN_SHARED 0x0040 +#define WIN_FIRST_SHARED 0x0080 +#define WIN_USE_WAIT 0x0100 +#define WIN_MAP_BELOW_1MB 0x0400 +#define WIN_PREFETCH 0x0800 +#define WIN_CACHEABLE 0x1000 +#define WIN_BAR_MASK 0xe000 +#define WIN_BAR_SHIFT 13 + +/* Attributes for RegisterClient */ +#define INFO_MASTER_CLIENT 0x01 +#define INFO_IO_CLIENT 0x02 +#define INFO_MTD_CLIENT 0x04 +#define INFO_MEM_CLIENT 0x08 +#define MAX_NUM_CLIENTS 3 + +#define INFO_CARD_SHARE 0x10 +#define INFO_CARD_EXCL 0x20 + +typedef struct cs_status_t { + u_char Function; + event_t CardState; + event_t SocketState; +} cs_status_t; + +typedef struct error_info_t { + int func; + int retcode; +} error_info_t; + +/* Special stuff for binding drivers to sockets */ +typedef struct bind_req_t { + socket_t Socket; + u_char Function; + dev_info_t *dev_info; +} bind_req_t; + +/* Flag to bind to all functions */ +#define BIND_FN_ALL 0xff + +typedef struct mtd_bind_t { + socket_t Socket; + u_int Attributes; + u_int CardOffset; + dev_info_t *dev_info; +} mtd_bind_t; + +/* Events */ +#define CS_EVENT_PRI_LOW 0 +#define CS_EVENT_PRI_HIGH 1 + +#define CS_EVENT_WRITE_PROTECT 0x000001 +#define CS_EVENT_CARD_LOCK 0x000002 +#define CS_EVENT_CARD_INSERTION 0x000004 +#define CS_EVENT_CARD_REMOVAL 0x000008 +#define CS_EVENT_BATTERY_DEAD 0x000010 +#define CS_EVENT_BATTERY_LOW 0x000020 +#define CS_EVENT_READY_CHANGE 0x000040 +#define CS_EVENT_CARD_DETECT 0x000080 +#define CS_EVENT_RESET_REQUEST 0x000100 +#define CS_EVENT_RESET_PHYSICAL 0x000200 +#define CS_EVENT_CARD_RESET 0x000400 +#define CS_EVENT_REGISTRATION_COMPLETE 0x000800 +#define CS_EVENT_RESET_COMPLETE 0x001000 +#define CS_EVENT_PM_SUSPEND 0x002000 +#define CS_EVENT_PM_RESUME 0x004000 +#define CS_EVENT_INSERTION_REQUEST 0x008000 +#define CS_EVENT_EJECTION_REQUEST 0x010000 +#define CS_EVENT_MTD_REQUEST 0x020000 +#define CS_EVENT_ERASE_COMPLETE 0x040000 +#define CS_EVENT_REQUEST_ATTENTION 0x080000 +#define CS_EVENT_CB_DETECT 0x100000 +#define CS_EVENT_3VCARD 0x200000 +#define CS_EVENT_XVCARD 0x400000 + +/* Return codes */ +#define CS_SUCCESS 0x00 +#define CS_BAD_ADAPTER 0x01 +#define CS_BAD_ATTRIBUTE 0x02 +#define CS_BAD_BASE 0x03 +#define CS_BAD_EDC 0x04 +#define CS_BAD_IRQ 0x06 +#define CS_BAD_OFFSET 0x07 +#define CS_BAD_PAGE 0x08 +#define CS_READ_FAILURE 0x09 +#define CS_BAD_SIZE 0x0a +#define CS_BAD_SOCKET 0x0b +#define CS_BAD_TYPE 0x0d +#define CS_BAD_VCC 0x0e +#define CS_BAD_VPP 0x0f +#define CS_BAD_WINDOW 0x11 +#define CS_WRITE_FAILURE 0x12 +#define CS_NO_CARD 0x14 +#define CS_UNSUPPORTED_FUNCTION 0x15 +#define CS_UNSUPPORTED_MODE 0x16 +#define CS_BAD_SPEED 0x17 +#define CS_BUSY 0x18 +#define CS_GENERAL_FAILURE 0x19 +#define CS_WRITE_PROTECTED 0x1a +#define CS_BAD_ARG_LENGTH 0x1b +#define CS_BAD_ARGS 0x1c +#define CS_CONFIGURATION_LOCKED 0x1d +#define CS_IN_USE 0x1e +#define CS_NO_MORE_ITEMS 0x1f +#define CS_OUT_OF_RESOURCE 0x20 +#define CS_BAD_HANDLE 0x21 + +#define CS_BAD_TUPLE 0x40 + +#ifdef __KERNEL__ + +/* + * Calls to set up low-level "Socket Services" drivers + */ + +typedef int (*ss_entry_t)(u_int sock, u_int cmd, void *arg); +extern int register_ss_entry(int nsock, ss_entry_t entry); +extern void unregister_ss_entry(ss_entry_t entry); + +/* + * The main Card Services entry point + */ + +enum service { + AccessConfigurationRegister, AddSocketServices, + AdjustResourceInfo, CheckEraseQueue, CloseMemory, CopyMemory, + DeregisterClient, DeregisterEraseQueue, GetCardServicesInfo, + GetClientInfo, GetConfigurationInfo, GetEventMask, + GetFirstClient, GetFirstPartion, GetFirstRegion, GetFirstTuple, + GetNextClient, GetNextPartition, GetNextRegion, GetNextTuple, + GetStatus, GetTupleData, MapLogSocket, MapLogWindow, MapMemPage, + MapPhySocket, MapPhyWindow, ModifyConfiguration, ModifyWindow, + OpenMemory, ParseTuple, ReadMemory, RegisterClient, + RegisterEraseQueue, RegisterMTD, RegisterTimer, + ReleaseConfiguration, ReleaseExclusive, ReleaseIO, ReleaseIRQ, + ReleaseSocketMask, ReleaseWindow, ReplaceSocketServices, + RequestConfiguration, RequestExclusive, RequestIO, RequestIRQ, + RequestSocketMask, RequestWindow, ResetCard, ReturnSSEntry, + SetEventMask, SetRegion, ValidateCIS, VendorSpecific, + WriteMemory, BindDevice, BindMTD, ReportError, + SuspendCard, ResumeCard, EjectCard, InsertCard, ReplaceCIS +}; + +#ifdef IN_CARD_SERVICES +extern int CardServices(int func, void *a1, void *a2, void *a3); +#else +extern int CardServices(int func, ...); +#endif + +#ifdef __BEOS__ +#define SS_MODULE_NAME(s) ("busses/pcmcia/" s "/v1") +#define MTD_MODULE_NAME(s) ("busses/pcmcia/" s "/v1") +#define CS_CLIENT_MODULE_NAME "bus_managers/pcmcia_cs/client/v1" +typedef struct cs_client_module_info { + bus_manager_info binfo; + int (*_CardServices)(int, ...); + int (*_MTDHelperEntry)(int, ...); + void (*_add_timer)(struct timer_list *); + void (*_del_timer)(struct timer_list *); +} cs_client_module_info; +#define CS_SOCKET_MODULE_NAME "bus_managers/pcmcia_cs/socket/v1" +typedef struct cs_socket_module_info { + bus_manager_info binfo; + int (*_register_ss_entry)(int, ss_entry_t); + void (*_unregister_ss_entry)(ss_entry_t); + void (*_add_timer)(struct timer_list *); + void (*_del_timer)(struct timer_list *); + int (*register_resource)(int, u_long, u_long); + int (*release_resource)(int, u_long, u_long); + int (*check_resource)(int, u_long, u_long); +} cs_socket_module_info; +#endif + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_CS_H */ diff --git a/klaptopdaemon/linux/cs_types.h b/klaptopdaemon/linux/cs_types.h new file mode 100644 index 0000000..8f9df45 --- /dev/null +++ b/klaptopdaemon/linux/cs_types.h @@ -0,0 +1,50 @@ +/* + * cs_types.h 1.13 1998/07/14 00:52:20 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_CS_TYPES_H +#define _LINUX_CS_TYPES_H + +#ifdef __linux__ +#include +#endif + +typedef u_short socket_t; +typedef u_short ioaddr_t; +typedef u_int event_t; +typedef u_char cisdata_t; +typedef u_short page_t; + +struct client_t; +typedef struct client_t *client_handle_t; + +struct window_t; +typedef struct window_t *window_handle_t; + +struct region_t; +typedef struct region_t *memory_handle_t; + +struct eraseq_t; +typedef struct eraseq_t *eraseq_handle_t; + +#ifndef DEV_NAME_LEN +#define DEV_NAME_LEN 32 +#endif + +typedef char dev_info_t[DEV_NAME_LEN]; + +#endif /* _LINUX_CS_TYPES_H */ diff --git a/klaptopdaemon/linux/driver_ops.h b/klaptopdaemon/linux/driver_ops.h new file mode 100644 index 0000000..a6a71ee --- /dev/null +++ b/klaptopdaemon/linux/driver_ops.h @@ -0,0 +1,71 @@ +/* + * driver_ops.h 1.11 1998/11/18 07:01:50 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_DRIVER_OPS_H +#define _LINUX_DRIVER_OPS_H + +#ifndef DEV_NAME_LEN +#define DEV_NAME_LEN 32 +#endif + +#ifdef __KERNEL__ + +typedef struct dev_node_t { + char dev_name[DEV_NAME_LEN]; + u_short major, minor; + struct dev_node_t *next; +} dev_node_t; + +typedef struct dev_locator_t { + enum { LOC_ISA, LOC_PCI } bus; + union { + struct { + u_short io_base_1, io_base_2; + u_long mem_base; + u_char irq, dma; + } isa; + struct { + u_char bus; + u_char devfn; + } pci; + } b; +} dev_locator_t; + +typedef struct driver_operations { + char *name; + dev_node_t *(*attach) (dev_locator_t *loc); + void (*suspend) (dev_node_t *dev); + void (*resume) (dev_node_t *dev); + void (*detach) (dev_node_t *dev); +} driver_operations; + +int register_driver(struct driver_operations *ops); +void unregister_driver(struct driver_operations *ops); + +#ifdef __BEOS__ +#define CB_ENABLER_MODULE_NAME "bus_managers/cb_enabler/v1" +typedef struct cb_enabler_module_info { + bus_manager_info binfo; + int (*register_driver)(struct driver_operations *ops); + void (*unregister_driver)(struct driver_operations *ops); +} cb_enabler_module_info; +#endif /* __BEOS__ */ + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_DRIVER_OPS_H */ diff --git a/klaptopdaemon/linux/ds.h b/klaptopdaemon/linux/ds.h new file mode 100644 index 0000000..11e0740 --- /dev/null +++ b/klaptopdaemon/linux/ds.h @@ -0,0 +1,142 @@ +/* + * ds.h 1.49 1998/08/03 19:12:23 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_DS_H +#define _LINUX_DS_H + +#include "driver_ops.h" +#include "bulkmem.h" + +typedef struct tuple_parse_t { + tuple_t tuple; + cisdata_t data[255]; + cisparse_t parse; +} tuple_parse_t; + +typedef struct bind_info_t { + dev_info_t dev_info; + u_char function; + struct dev_link_t *instance; + char name[DEV_NAME_LEN]; + u_short major, minor; + void *next; +} bind_info_t; + +typedef struct mtd_info_t { + dev_info_t dev_info; + u_int Attributes; + u_int CardOffset; +} mtd_info_t; + +typedef union ds_ioctl_arg_t { + servinfo_t servinfo; + adjust_t adjust; + config_info_t config; + tuple_t tuple; + tuple_parse_t tuple_parse; + client_req_t client_req; + cs_status_t status; + conf_reg_t conf_reg; + cisinfo_t cisinfo; + region_info_t region; + bind_info_t bind_info; + mtd_info_t mtd_info; + cisdump_t cisdump; +} ds_ioctl_arg_t; + +#define DS_GET_CARD_SERVICES_INFO _IOR ('d', 1, servinfo_t) +#define DS_ADJUST_RESOURCE_INFO _IOWR('d', 2, adjust_t) +#define DS_GET_CONFIGURATION_INFO _IOWR('d', 3, config_info_t) +#define DS_GET_FIRST_TUPLE _IOWR('d', 4, tuple_t) +#define DS_GET_NEXT_TUPLE _IOWR('d', 5, tuple_t) +#define DS_GET_TUPLE_DATA _IOWR('d', 6, tuple_parse_t) +#define DS_PARSE_TUPLE _IOWR('d', 7, tuple_parse_t) +#define DS_RESET_CARD _IO ('d', 8) +#define DS_GET_STATUS _IOWR('d', 9, cs_status_t) +#define DS_ACCESS_CONFIGURATION_REGISTER _IOWR('d', 10, conf_reg_t) +#define DS_VALIDATE_CIS _IOR ('d', 11, cisinfo_t) +#define DS_SUSPEND_CARD _IO ('d', 12) +#define DS_RESUME_CARD _IO ('d', 13) +#define DS_EJECT_CARD _IO ('d', 14) +#define DS_INSERT_CARD _IO ('d', 15) +#define DS_GET_FIRST_REGION _IOWR('d', 16, region_info_t) +#define DS_GET_NEXT_REGION _IOWR('d', 17, region_info_t) +#define DS_REPLACE_CIS _IOWR('d', 18, cisdump_t) + +#define DS_BIND_REQUEST _IOWR('d', 60, bind_info_t) +#define DS_GET_DEVICE_INFO _IOWR('d', 61, bind_info_t) +#define DS_GET_NEXT_DEVICE _IOWR('d', 62, bind_info_t) +#define DS_UNBIND_REQUEST _IOW ('d', 63, bind_info_t) +#define DS_BIND_MTD _IOWR('d', 64, mtd_info_t) + +#ifdef __KERNEL__ + +typedef struct dev_link_t { + dev_node_t *dev; + u_int state, open; + struct wait_queue *pending; + struct timer_list release; + client_handle_t handle; + io_req_t io; + irq_req_t irq; + config_req_t conf; + window_handle_t win; + void *priv; + struct dev_link_t *next; +} dev_link_t; + +/* Flags for device state */ +#define DEV_PRESENT 0x01 +#define DEV_CONFIG 0x02 +#define DEV_STALE_CONFIG 0x04 /* release on close */ +#define DEV_STALE_LINK 0x08 /* detach on release */ +#define DEV_CONFIG_PENDING 0x10 +#define DEV_RELEASE_PENDING 0x20 +#define DEV_SUSPEND 0x40 +#define DEV_BUSY 0x80 + +#define DEV_OK(l) \ + ((l) && ((l->state & ~DEV_BUSY) == (DEV_CONFIG|DEV_PRESENT))) + +int register_pccard_driver(dev_info_t *dev_info, + dev_link_t *(*attach)(void), + void (*detach)(dev_link_t *)); + +int unregister_pccard_driver(dev_info_t *dev_info); + +#define register_pcmcia_driver register_pccard_driver +#define unregister_pcmcia_driver unregister_pccard_driver + +#ifdef __BEOS__ +#define DS_MODULE_NAME "bus_managers/pcmcia_ds/v1" +typedef struct ds_module_info { + bus_manager_info binfo; + int (*_register_pccard_driver)(dev_info_t *, + dev_link_t *(*)(void), + void (*)(dev_link_t *)); + int (*_unregister_pccard_driver)(dev_info_t *); + struct driver_info_t **root_driver; + int *sockets; + struct socket_info_t **socket_table; + sem_id *list_sem; +} ds_module_info; +#endif /* __BEOS__ */ + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_DS_H */ diff --git a/klaptopdaemon/linux/ftl.h b/klaptopdaemon/linux/ftl.h new file mode 100644 index 0000000..9357d17 --- /dev/null +++ b/klaptopdaemon/linux/ftl.h @@ -0,0 +1,62 @@ +/* + * ftl.h 1.4 1998/05/10 12:10:34 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_FTL_H +#define _LINUX_FTL_H + +typedef struct erase_unit_header_t { + u_char LinkTargetTuple[5]; + u_char DataOrgTuple[10]; + u_char NumTransferUnits; + u_int EraseCount; + u_short LogicalEUN; + u_char BlockSize; + u_char EraseUnitSize; + u_short FirstPhysicalEUN; + u_short NumEraseUnits; + u_int FormattedSize; + u_int FirstVMAddress; + u_short NumVMPages; + u_char Flags; + u_char Code; + u_int SerialNumber; + u_int AltEUHOffset; + u_int BAMOffset; + u_char Reserved[12]; + u_char EndTuple[2]; +} erase_unit_header_t; + +/* Flags in erase_unit_header_t */ +#define HIDDEN_AREA 0x01 +#define REVERSE_POLARITY 0x02 +#define DOUBLE_BAI 0x04 + +/* Definitions for block allocation information */ + +#define BLOCK_FREE(b) ((b) == 0xffffffff) +#define BLOCK_DELETED(b) (((b) == 0) || ((b) == 0xfffffffe)) + +#define BLOCK_TYPE(b) ((b) & 0x7f) +#define BLOCK_ADDRESS(b) ((b) & ~0x7f) +#define BLOCK_NUMBER(b) ((b) >> 9) +#define BLOCK_CONTROL 0x30 +#define BLOCK_DATA 0x40 +#define BLOCK_REPLACEMENT 0x60 +#define BLOCK_BAD 0x70 + +#endif /* _LINUX_FTL_H */ diff --git a/klaptopdaemon/linux/k_compat.h b/klaptopdaemon/linux/k_compat.h new file mode 100644 index 0000000..2b14312 --- /dev/null +++ b/klaptopdaemon/linux/k_compat.h @@ -0,0 +1,246 @@ +/* + * k_compat.h 1.74 1999/01/07 03:46:29 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_K_COMPAT_H +#define _LINUX_K_COMPAT_H + +#define __LINUX__ +#define VERSION(v,p,s) (((v)<<16)+(p<<8)+s) + +#define RUN_AT(x) (jiffies+(x)) +#define CONST const +#define ALLOC_SKB(len) dev_alloc_skb(len+2) +#define DEVICE(req) ((req)->rq_dev) +#define GET_PACKET(dev, skb, count) \ + skb_reserve((skb), 2); \ + BLOCK_INPUT(skb_put((skb), (count)), (count)); \ + (skb)->protocol = eth_type_trans((skb), (dev)) + +#define BLK_DEV_HDR "linux/blk.h" +#define NEW_MULTICAST + +#define FREE_IRQ(i,d) free_irq(i, d) +#define REQUEST_IRQ(i,h,f,n,d) request_irq(i,h,f,n,d) +#define IRQ(a,b,c) (a,b,c) +#define DEV_ID dev_id + +#if (LINUX_VERSION_CODE < VERSION(2,0,16)) +#define init_waitqueue(p) (*(p) = NULL) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,4)) && !defined(__alpha__) +#define FS_SIZE_T int +#define U_FS_SIZE_T int +#else +#if (LINUX_VERSION_CODE < VERSION(2,1,60)) +#define FS_SIZE_T long +#define U_FS_SIZE_T unsigned long +#else +#define FS_SIZE_T ssize_t +#define U_FS_SIZE_T size_t +#endif +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,25)) +#define net_device_stats enet_statistics +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,31)) +#define FS_RELEASE_T void +#else +#define FS_RELEASE_T int +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,38)) +#define test_and_set_bit set_bit +#endif + +#if (LINUX_VERSION_CODE > VERSION(2,1,16)) +#define AUTOCONF_INCLUDED +#define EXPORT_SYMTAB +#endif +#ifdef CONFIG_MODVERSIONS +#define MODVERSIONS 1 +#include +#endif +#include + +#if (LINUX_VERSION_CODE < VERSION(2,1,18)) +#define MODULE_PARM(a,b) extern int __bogus_decl +#undef GET_USE_COUNT +#define GET_USE_COUNT(m) mod_use_count_ +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,0)) +#define copy_from_user memcpy_fromfs +#define copy_to_user memcpy_tofs + +#if (!defined(__alpha__) || (LINUX_VERSION_CODE < VERSION(2,0,34))) +#define ioremap(a,b) \ + (((a) < 0x100000) ? (void *)((u_long)(a)) : vremap(a,b)) +#define iounmap(v) \ + do { if ((u_long)(v) > 0x100000) vfree(v); } while (0) +#endif +/* This is evil... throw away the built-in get_user in 2.0 */ +#include +#undef get_user + +#ifdef __alpha__ +#define get_user(x, ptr) ((x) = __get_user((ptr), sizeof(*(ptr)))) +#undef get_fs_long +#undef put_fs_long +#define get_fs_long(ptr) __get_user((ptr), sizeof(int)) +#define put_fs_long(x, ptr) __put_user((x), (ptr), sizeof(int)) +#else +#define get_user(x, ptr) \ + ((sizeof(*ptr) == 4) ? (x = get_fs_long(ptr)) : \ + (sizeof(*ptr) == 2) ? (x = get_fs_word(ptr)) : \ + (x = get_fs_byte(ptr))) +#endif + +#else /* 2.1.X */ +#include +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,45)) +#define F_INODE(file) ((file)->f_inode) +#else +#define F_INODE(file) ((file)->f_dentry->d_inode) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,51)) +#define INVALIDATE_INODES(r) invalidate_inodes(r) +#else +#define INVALIDATE_INODES(r) \ + do { struct super_block *sb = get_super(r); \ + if (sb) invalidate_inodes(sb); } while (0) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,60)) +#define IRQ_MAP(irq, dev) irq2dev_map[irq] = dev +#define FOPS(i,f,b,c,p) (i,f,b,c) +#define FPOS (file->f_pos) +#else +#define IRQ_MAP(irq, dev) while (0) +#define FOPS(i,f,b,c,p) (f,b,c,p) +#define FPOS (*ppos) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,68)) +#define signal_pending(cur) ((cur)->signal & ~(cur)->blocked) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,86)) +#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE) +#else +#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,89)) +#define POLL_WAIT(f, q, w) poll_wait(q, w) +#else +#define POLL_WAIT(f, q, w) poll_wait(f, q, w) +#endif + +#include +#ifndef le16_to_cpu +#define le16_to_cpu(x) (x) +#define le32_to_cpu(x) (x) +#define cpu_to_le16(x) (x) +#define cpu_to_le32(x) (x) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,90)) +#define spin_lock(l) do { } while (0) +#define spin_unlock(l) do { } while (0) +#define spin_lock_irqsave(l,f) do { save_flags(f); cli(); } while (0) +#define spin_unlock_irqrestore(l,f) do { restore_flags(f); } while (0) +#else +#include +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,104)) +#define mdelay(x) { int i; for (i=0;itimeout=jiffies+(t));wsleep(w);current->timeout;}) +#define schedule_timeout(t) \ + do { current->timeout = jiffies+(t); schedule(); } while (0) +#endif + +#include +#ifndef readw_ns +#ifdef __powerpc__ +#define readw_ns(p) ld_be16((volatile unsigned short *)(p)) +#define readl_ns(p) ld_be32((volatile unsigned *)(p)) +#define writew_ns(v,p) st_le16((volatile unsigned short *)(p),(v)) +#define writel_ns(v,p) st_le32((volatile unsigned *)(p),(v)) +#define inw_ns(p) in_be16((unsigned short *)((p)+_IO_BASE)) +#define inl_ns(p) in_be32((unsigned *)((p)+_IO_BASE)) +#define outw_ns(v,p) out_be16((unsigned short *)((p)+_IO_BASE),(v)) +#define outl_ns(v,p) out_be32((unsigned *)((p)+_IO_BASE),(v)) +#else +#define readw_ns(p) readw(p) +#define readl_ns(p) readl(p) +#define writew_ns(v,p) writew(v,p) +#define writel_ns(v,p) writel(v,p) +#define inw_ns(p) inw(p) +#define inl_ns(p) inl(p) +#define outw_ns(v,p) outw(v,p) +#define outl_ns(v,p) outl(v,p) +#endif +#endif +#ifndef insw_ns +#define insw_ns(p,b,l) insw(p,b,l) +#define insl_ns(p,b,l) insl(p,b,l) +#define outsw_ns(p,b,l) outsw(p,b,l) +#define outsl_ns(p,b,l) outsl(p,b,l) +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,93)) +#include +#endif +#include +#ifndef PCI_FUNC +#define PCI_FUNC(devfn) ((devfn)&7) +#define PCI_SLOT(devfn) ((devfn)>>3) +#define PCI_DEVFN(dev,fn) (((dev)<<3)|((fn)&7)) +#endif + +#if (LINUX_VERSION_CODE > VERSION(2,1,117)) +#define NULL_FLUSH NULL, +#else +#define NULL_FLUSH +#endif + +#if (LINUX_VERSION_CODE < VERSION(2,1,126)) +#define SCSI_DISK0_MAJOR SCSI_DISK_MAJOR +#endif + +typedef unsigned long k_time_t; +#define ACQUIRE_RESOURCE_LOCK do {} while (0) +#define RELEASE_RESOURCE_LOCK do {} while (0) + +#endif /* _LINUX_K_COMPAT_H */ diff --git a/klaptopdaemon/linux/mem_op.h b/klaptopdaemon/linux/mem_op.h new file mode 100644 index 0000000..85f1ba2 --- /dev/null +++ b/klaptopdaemon/linux/mem_op.h @@ -0,0 +1,120 @@ +/* + * mem_op.h 1.8 1998/07/17 10:12:23 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_MEM_OP_H +#define _LINUX_MEM_OP_H + +/* + If UNSAFE_MEMCPY is defined, we use the (optimized) system routines + to copy between a card and kernel memory. These routines do 32-bit + operations which may not work with all PCMCIA controllers. The + safe versions defined here will do only 8-bit and 16-bit accesses. +*/ + +#ifdef UNSAFE_MEMCPY + +#define copy_from_pc memcpy_fromio +#define copy_to_pc memcpy_toio + +static inline void copy_pc_to_user(void *to, const void *from, size_t n) +{ + size_t odd = (n & 3); + n -= odd; + while (n) { + put_user(readl_ns(from), (int *)to); + (char *)from += 4; (char *)to += 4; n -= 4; + } + while (odd--) + put_user(readb((char *)from++), (char *)to++); +} + +static inline void copy_user_to_pc(void *to, const void *from, size_t n) +{ + int l; + char c; + size_t odd = (n & 3); + n -= odd; + while (n) { + get_user(l, (int *)from); + writel_ns(l, to); + (char *)to += 4; (char *)from += 4; n -= 4; + } + while (odd--) { + get_user(c, (char *)from++); + writeb(c, (char *)to++); + } +} + +#else /* UNSAFE_MEMCPY */ + +static inline void copy_from_pc(void *to, const void *from, size_t n) +{ + size_t odd = (n & 1); + n -= odd; + while (n) { + *(u_short *)to = readw_ns(from); + (char *)to += 2; (char *)from += 2; n -= 2; + } + if (odd) + *(u_char *)to = readb(from); +} + +static inline void copy_to_pc(void *to, const void *from, size_t n) +{ + size_t odd = (n & 1); + n -= odd; + while (n) { + writew_ns(*(u_short *)from, to); + (char *)to += 2; (char *)from += 2; n -= 2; + } + if (odd) + writeb(*(u_char *)from, to); +} + +static inline void copy_pc_to_user(void *to, const void *from, size_t n) +{ + size_t odd = (n & 1); + n -= odd; + while (n) { + put_user(readw_ns(from), (short *)to); + (char *)to += 2; (char *)from += 2; n -= 2; + } + if (odd) + put_user(readb(from), (char *)to); +} + +static inline void copy_user_to_pc(void *to, const void *from, size_t n) +{ + short s; + char c; + size_t odd = (n & 1); + n -= odd; + while (n) { + get_user(s, (short *)from); + writew_ns(s, to); + (char *)to += 2; (char *)from += 2; n -= 2; + } + if (odd) { + get_user(c, (char *)from); + writeb(c, to); + } +} + +#endif /* UNSAFE_MEMCPY */ + +#endif /* _LINUX_MEM_OP_H */ diff --git a/klaptopdaemon/linux/memory.h b/klaptopdaemon/linux/memory.h new file mode 100644 index 0000000..d7aa9de --- /dev/null +++ b/klaptopdaemon/linux/memory.h @@ -0,0 +1,30 @@ +/* + * memory.h 1.3 1998/05/10 12:10:34 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_MEMORY_H +#define _LINUX_MEMORY_H + +typedef struct erase_info_t { + u_long Offset; + u_long Size; +} erase_info_t; + +#define MEMGETINFO _IOR('M', 1, region_info_t) +#define MEMERASE _IOW('M', 2, erase_info_t) + +#endif /* _LINUX_MEMORY_H */ diff --git a/klaptopdaemon/linux/ss.h b/klaptopdaemon/linux/ss.h new file mode 100644 index 0000000..57ad769 --- /dev/null +++ b/klaptopdaemon/linux/ss.h @@ -0,0 +1,113 @@ +/* + * ss.h 1.18 1998/10/01 20:54:49 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1998 David A. Hinds. All Rights Reserved. + */ + +#ifndef _LINUX_SS_H +#define _LINUX_SS_H + +/* For RegisterCallback */ +typedef struct ss_callback_t { + void (*handler)(void *info, u_int events); + void *info; +} ss_callback_t; + +/* Definitions for card status flags for GetStatus */ +#define SS_WRPROT 0x0001 +#define SS_CARDLOCK 0x0002 +#define SS_EJECTION 0x0004 +#define SS_INSERTION 0x0008 +#define SS_BATDEAD 0x0010 +#define SS_BATWARN 0x0020 +#define SS_READY 0x0040 +#define SS_DETECT 0x0080 +#define SS_POWERON 0x0100 +#define SS_GPI 0x0200 +#define SS_STSCHG 0x0400 +#define SS_CARDBUS 0x0800 +#define SS_3VCARD 0x1000 +#define SS_XVCARD 0x2000 + +/* for InquireSocket */ +typedef struct socket_cap_t { + u_int features; + u_int irq_mask; + u_int map_size; + u_char pci_irq; + u_char cardbus; +} socket_cap_t; + +/* InquireSocket features */ +#define SS_HAS_PAGE_REGS 0x0001 + +/* for GetSocket, SetSocket */ +typedef struct socket_state_t { + u_int flags; + u_int csc_mask; + u_char Vcc, Vpp; + u_char io_irq; +} socket_state_t; + +/* Various card configuration flags */ +#define SS_PWR_AUTO 0x0010 +#define SS_IOCARD 0x0020 +#define SS_RESET 0x0040 +#define SS_DMA_MODE 0x0080 +#define SS_SPKR_ENA 0x0100 +#define SS_OUTPUT_ENA 0x0200 + +/* Flags for I/O port and memory windows */ +#define MAP_ACTIVE 0x01 +#define MAP_16BIT 0x02 +#define MAP_AUTOSZ 0x04 +#define MAP_0WS 0x08 +#define MAP_WRPROT 0x10 +#define MAP_ATTRIB 0x20 +#define MAP_USE_WAIT 0x40 +#define MAP_PREFETCH 0x80 + +/* Use this just for bridge windows */ +#define MAP_IOSPACE 0x20 + +typedef struct pccard_io_map { + u_char map; + u_char flags; + u_short speed; + u_short start, stop; +} pccard_io_map; + +typedef struct pccard_mem_map { + u_char map; + u_char flags; + u_short speed; + u_long sys_start, sys_stop; + u_int card_start; +} pccard_mem_map; + +typedef struct cb_bridge_map { + u_char map; + u_char flags; + u_int start, stop; +} cb_bridge_map; + +enum ss_service { + SS_RegisterCallback, SS_InquireSocket, + SS_GetStatus, SS_GetSocket, SS_SetSocket, + SS_GetIOMap, SS_SetIOMap, SS_GetMemMap, SS_SetMemMap, + SS_GetBridge, SS_SetBridge, SS_ProcSetup +}; + +#endif /* _LINUX_SS_H */ diff --git a/klaptopdaemon/linux/version.h b/klaptopdaemon/linux/version.h new file mode 100644 index 0000000..86f556e --- /dev/null +++ b/klaptopdaemon/linux/version.h @@ -0,0 +1,4 @@ +/* version.h 1.55 1998/02/25 22:21:07 (David Hinds) */ + +#define CS_RELEASE "3.0.9" +#define CS_RELEASE_CODE 0x3009 diff --git a/klaptopdaemon/main.cpp b/klaptopdaemon/main.cpp new file mode 100644 index 0000000..9dc0419 --- /dev/null +++ b/klaptopdaemon/main.cpp @@ -0,0 +1,305 @@ +/* + * main.cpp + * + * Copyright (c) 1999 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "main.h" +#include "version.h" +#include "warning.h" +#include "power.h" +#include "battery.h" +#include "buttons.h" +#include "pcmcia.h" +#include "acpi.h" +#include "apm.h" +#include "sony.h" +#include "profile.h" +#include "portable.h" +extern void wake_laptop_daemon(); + + +extern "C" +{ + + KDE_EXPORT KCModule *create_pcmcia(QWidget *parent, const char *) + { + return new PcmciaConfig(parent, "kcmlaptop"); + } + + KDE_EXPORT KCModule *create_bwarning(QWidget *parent, const char *) + { + return new WarningConfig(0, parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_cwarning(QWidget *parent, const char *) + { + return new WarningConfig(1, parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_battery(QWidget *parent, const char *) + { + return new BatteryConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_power(QWidget *parent, const char *) + { + return new PowerConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_acpi(QWidget *parent, const char *) + { + return new AcpiConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_apm(QWidget *parent, const char *) + { + return new ApmConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_Profile(QWidget *parent, const char *) + { + return new ProfileConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_sony(QWidget *parent, const char *) + { + return new SonyConfig(parent, "kcmlaptop"); + } + KDE_EXPORT KCModule *create_buttons(QWidget *parent, const char *) + { + return new ButtonsConfig(parent, "kcmlaptop"); + } + + KDE_EXPORT void init_battery() + { + KConfig config("kcmlaptoprc", true /*readonly*/, false /*no globals*/); + config.setGroup("BatteryDefault"); + bool enable = false; + if (!config.hasKey("Enable")) { // if they have APM or PCMCIA, Enable=true + struct power_result pr = laptop_portable::poll_battery_state(); + if ((laptop_portable::has_power_management() && + !(pr.powered && + (pr.percentage < 0 || pr.percentage == 0xff)))|| + 0 == access("/var/run/stab", R_OK|F_OK) || + 0 == access("/var/lib/pcmcia/stab", R_OK|F_OK)) + enable = true; + } else { + enable = config.readBoolEntry("Enable", false); + } + if (!enable) + return; + wake_laptop_daemon(); + } + + KDE_EXPORT KCModule *create_laptop(QWidget *parent, const char *) + { + return new LaptopModule(parent, "kcmlaptop"); + } + + KDE_EXPORT void init_laptop() + { + init_battery(); + } +} + + + +LaptopModule::LaptopModule(QWidget *parent, const char *) + : KCModule(parent, "kcmlaptop") +{ + { // export ACPI options + KConfig config("kcmlaptoprc", true /*readonly*/, false /*no globals*/); + config.setGroup("AcpiDefault"); + + bool enablestandby = config.readBoolEntry("EnableStandby", false); + bool enablesuspend = config.readBoolEntry("EnableSuspend", false); + bool enablehibernate = config.readBoolEntry("EnableHibernate", false); + bool enableperformance = config.readBoolEntry("EnablePerformance", false); + bool enablethrottle = config.readBoolEntry("EnableThrottle", false); + laptop_portable::acpi_set_mask(enablestandby, enablesuspend, enablehibernate, enableperformance, enablethrottle); + + config.setGroup("ApmDefault"); + + enablestandby = config.readBoolEntry("EnableStandby", false); + enablesuspend = config.readBoolEntry("EnableSuspend", false); + laptop_portable::apm_set_mask(enablestandby, enablesuspend); + config.setGroup("SoftwareSuspendDefault"); + enablehibernate = config.readBoolEntry("EnableHibernate", false); + laptop_portable::software_suspend_set_mask(enablehibernate); + } + QVBoxLayout *layout = new QVBoxLayout(this); + tab = new QTabWidget(this); + layout->addWidget(tab); + + battery = new BatteryConfig(parent, "kcmlaptop"); + tab->addTab(battery, i18n("&Battery")); + connect(battery, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + + power = new PowerConfig(parent, "kcmlaptop"); + tab->addTab(power, i18n("&Power Control")); + connect(power, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + + warning = new WarningConfig(0, parent, "kcmlaptop"); + tab->addTab(warning, i18n("Low Battery &Warning")); + connect(warning, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + + critical = new WarningConfig(1, parent, "kcmlaptop"); + tab->addTab(critical, i18n("Low Battery &Critical")); + connect(critical, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + + QStringList profile_list; + int current_profile; + bool *active_list; + bool has_profile = laptop_portable::get_system_performance(0, current_profile, profile_list, active_list); + QStringList throttle_list; + int current_throttle; + bool has_throttling = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + if (laptop_portable::has_brightness() || has_profile || has_throttling) { + profile = new ProfileConfig(parent, "kcmlaptop"); + tab->addTab(profile, i18n("Default Power Profiles")); + connect(profile, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + } else { + profile = 0; + } + if (laptop_portable::has_button(laptop_portable::LidButton) || laptop_portable::has_button(laptop_portable::PowerButton)) { + buttons = new ButtonsConfig(parent, "kcmlaptop"); + tab->addTab(buttons, i18n("Button Actions")); + connect(buttons, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + } else { + buttons = 0; + } + if (laptop_portable::has_acpi()) { + acpi = new AcpiConfig(parent, "kcmlaptop"); + tab->addTab(acpi, i18n("&ACPI Config")); + connect(acpi, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + } else { + acpi = 0; + } + if (laptop_portable::has_apm()) { + apm = new ApmConfig(parent, "kcmlaptop"); + tab->addTab(apm, i18n("&APM Config")); + connect(apm, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + } else { + apm = 0; + } + if (::access("/dev/sonypi", F_OK) == 0) { + bool do_sony = 1; + if (::access("/dev/sonypi", R_OK) == 0) { + int fd = ::open("/dev/sonypi", O_RDONLY); // make sure the driver's there as well as the /dev inode + if (fd >= 0) { + ::close(fd); + } else { + do_sony = 0; + } + } + if (do_sony) { + sony = new SonyConfig(parent, "kcmlaptop"); + tab->addTab(sony, i18n("&Sony Laptop Config")); + connect(sony, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); + } else { + sony = 0; + } + } else { + sony = 0; + } + + KAboutData* about = + new KAboutData("kcmlaptop", I18N_NOOP("Laptop Battery Configuration"), LAPTOP_VERSION, + I18N_NOOP("Battery Control Panel Module"), + KAboutData::License_GPL, + I18N_NOOP("(c) 1999 Paul Campbell"), 0, 0); + //about->addAuthor("NAME", 0, "e-mail addy"); + setAboutData( about ); +} + +void LaptopModule::load() +{ + battery->load(); + warning->load(); + critical->load(); + power->load(); + if (apm) + apm->load(); + if (acpi) + acpi->load(); + if (profile) + profile->load(); + if (sony) + sony->load(); + if (buttons) + buttons->load(); +} + +void LaptopModule::save() +{ + battery->save(); + warning->save(); + critical->save(); + power->save(); + if (profile) + profile->save(); + if (acpi) + acpi->save(); + if (apm) + apm->save(); + if (sony) + sony->save(); + if (buttons) + buttons->save(); +} + + +void LaptopModule::defaults() +{ + battery->defaults(); + warning->defaults(); + critical->defaults(); + power->defaults(); + if (acpi) + acpi->defaults(); + if (apm) + apm->defaults(); + if (profile) + profile->defaults(); + if (sony) + sony->defaults(); + if (buttons) + buttons->defaults(); +} + +QString LaptopModule::quickHelp() const +{ + return i18n("

Laptop Battery

This module allows you to monitor " + "your batteries. To make use of this module, you must have power management software " + "installed. (And, of course, you should have batteries in your " + "machine.)"); +} + + +void LaptopModule::moduleChanged(bool state) +{ + emit changed(state); +} + + +#include "main.moc" diff --git a/klaptopdaemon/main.h b/klaptopdaemon/main.h new file mode 100644 index 0000000..81d6e41 --- /dev/null +++ b/klaptopdaemon/main.h @@ -0,0 +1,82 @@ +/* + * main.h + * + * Copyright (c) 2002 Paul Campbell paul@taniwha.com + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __MAIN_H__ +#define __MAIN_H__ + + +#include + + +#include + + +class WarningConfig; +class BatteryConfig; +class PowerConfig; +class AcpiConfig; +class ApmConfig; +class SonyConfig; +class ProfileConfig; +class ButtonsConfig; + +class LaptopModule : public KCModule +{ + Q_OBJECT + +public: + + LaptopModule(QWidget *parent, const char *name); + + void load(); + void save(); + void defaults(); + QString quickHelp() const; + + + +protected slots: + + void moduleChanged(bool state); + + +private: + + QTabWidget *tab; + + WarningConfig *warning; + WarningConfig *critical; + BatteryConfig *battery; + PowerConfig *power; + AcpiConfig *acpi; + ApmConfig *apm; + ProfileConfig *profile; + SonyConfig *sony; + ButtonsConfig *buttons; +}; + + +#endif + + diff --git a/klaptopdaemon/makecrc.cpp b/klaptopdaemon/makecrc.cpp new file mode 100644 index 0000000..ce3d415 --- /dev/null +++ b/klaptopdaemon/makecrc.cpp @@ -0,0 +1,38 @@ +/* + * makecrc.cpp + * + * Copyright (c) 2003 Paul Campbell + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + + + +#include "checkcrc.h" + +int main(int, char**) +{ + unsigned long len, crc; + checkcrc("./klaptop_acpi_helper", len, crc); + printf("#ifndef _CRCRESULT_H_\n"); + printf("#define _CRCRESULT_H_\n"); + printf("static unsigned long file_len = 0x%lx;\n", len); + printf("static unsigned long file_crc = 0x%lx;\n", crc); + printf("#endif\n"); + return(0); +} diff --git a/klaptopdaemon/pcmcia.cpp b/klaptopdaemon/pcmcia.cpp new file mode 100644 index 0000000..ed17789 --- /dev/null +++ b/klaptopdaemon/pcmcia.cpp @@ -0,0 +1,122 @@ +/* + * pcmcia.cpp + * + * Copyright (c) 1999 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "pcmcia.h" +#include "portable.h" +#include "version.h" + +PcmciaConfig::PcmciaConfig (QWidget * parent, const char *name) + : KCModule(parent, name) +{ + KAboutData *about = + new KAboutData(I18N_NOOP("kcmlaptop"), + I18N_NOOP("KDE Panel System Information Control Module"), + 0, 0, KAboutData::License_GPL, + I18N_NOOP("(c) 1999 - 2002 Paul Campbell")); + about->addAuthor("Paul Campbell", 0, "paul@taniwha.com"); + setAboutData( about ); + + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + label0 = laptop_portable::pcmcia_info(0, this); + label0_text = laptop_portable::pcmcia_info(1, this); + label1 = laptop_portable::pcmcia_info(2, this); + label1_text = laptop_portable::pcmcia_info(3, this); + + + QVBoxLayout *top_layout = new QVBoxLayout(this, 15, 5); + QGridLayout *top_grid = new QGridLayout(2, 2); + top_layout->addLayout(top_grid); + + top_grid->setColStretch(0, 0); + top_grid->setColStretch(1, 1); + top_grid->addRowSpacing(0, 40); + top_grid->addRowSpacing(1, 40); + + label0->setFixedSize(80, 24); + top_grid->addWidget(label0, 0, 0); + label0_text->adjustSize(); + top_grid->addWidget(label0_text, 0, 1); + + label1->setFixedSize(80, 24); + top_grid->addWidget(label1, 1, 0); + label1_text->adjustSize(); + top_grid->addWidget(label1_text, 1, 1); + + + top_layout->addStretch(1); + + QHBoxLayout *v1 = new QHBoxLayout; + top_layout->addLayout(v1, 0); + v1->addStretch(1); + QString s1 = LAPTOP_VERSION; + QString s2 = i18n("Version: ")+s1; + QLabel* vers = new QLabel(s2, this); + vers->setMinimumSize(vers->sizeHint()); + v1->addWidget(vers, 0); + + top_layout->activate(); + + load(); + setButtons(Help); +} + + +void PcmciaConfig::save() +{ +} + +void PcmciaConfig::load() +{ +} + +void PcmciaConfig::defaults() +{ +} + + +void PcmciaConfig::changed() +{ + emit KCModule::changed(true); +} + + +QString PcmciaConfig::quickHelp() const +{ + return i18n("

PCMCIA Config

This module shows information about " + "the PCMCIA cards in your system, if there are PCMCIA cards."); +} + +#include "pcmcia.moc" diff --git a/klaptopdaemon/pcmcia.h b/klaptopdaemon/pcmcia.h new file mode 100644 index 0000000..e163742 --- /dev/null +++ b/klaptopdaemon/pcmcia.h @@ -0,0 +1,70 @@ +/* + * pcmcia.h + * + * Copyright (c) 1999 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __PCMCIACONFIG_H__ +#define __PCMCIACONFIG_H__ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +class PcmciaConfig : public KCModule +{ + Q_OBJECT +public: + PcmciaConfig( QWidget *parent=0, const char* name=0); + + void save( void ); + void load(); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void changed(); + + +private: + void GetSettings( void ); + + QLabel *label0; + QLabel *label1; + QLabel *label0_text; + QLabel *label1_text; + + +}; + +#endif + diff --git a/klaptopdaemon/pics/Makefile.am b/klaptopdaemon/pics/Makefile.am new file mode 100644 index 0000000..2828fc2 --- /dev/null +++ b/klaptopdaemon/pics/Makefile.am @@ -0,0 +1,6 @@ +# $Id$ +# kdebase/kcontrol/input/pics +SUBDIRS = actions + +KDE_ICON = laptop_battery laptop laptop_pcmcia klaptopdaemon + diff --git a/klaptopdaemon/pics/README b/klaptopdaemon/pics/README new file mode 100644 index 0000000..29a1b13 --- /dev/null +++ b/klaptopdaemon/pics/README @@ -0,0 +1,36 @@ +Notes about laptop daemon's icons: + + lo16-app-klaptopdaemon.png - is only used for the context menu + only the 16x16 is actually needed + + in fact with recent changes to the iconloader icons other than + the 16x16 (really 20x20) are BAD - please don't create them + + the 3 icons in the action directory: + laptop_charge/laptop_concharge/laptop_nobattery + + are 'special' - they are read by the application and + modified on-the-fly to create a bar-graph of how full + the battery is - you can't just edit them the way you would + a normal icon - basically any white pixels will be replaced + with a proportional number of blue ones from the bottom of + the icon to the top (so pure white pixels are 'magic' and + should be treated as the portion of the icon that is the graph) + you can use slightly off-white or a not-quite-saturated + white if you want 'white' + + I'd love some cool new battery icons but please contact me + if you need some testing before committing + + + + Paul Campbell - laptop support author + paul@taniwha.com + +We also have some contributed icons: + +the 2 'alt_' ones came from Percy Leonhardt +the 3 'alt2_' ones came from Keunwoo Lee +the 2 'alt3_' ones came from Jason Dixon + +thanks guys! diff --git a/klaptopdaemon/pics/actions/Makefile.am b/klaptopdaemon/pics/actions/Makefile.am new file mode 100644 index 0000000..4f9cf71 --- /dev/null +++ b/klaptopdaemon/pics/actions/Makefile.am @@ -0,0 +1,3 @@ +klaptopdaemoniconsdir = $(kde_datadir)/klaptopdaemon/icons +klaptopdaemonicons_ICON = AUTO + diff --git a/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nobattery.png b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nobattery.png new file mode 100644 index 0000000..3018b38 Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nobattery.png differ diff --git a/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nocharge.png b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nocharge.png new file mode 100644 index 0000000..6c4951b Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_nocharge.png differ diff --git a/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_power.png b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_power.png new file mode 100644 index 0000000..743d809 Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-alt2_laptop_power.png differ diff --git a/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_nocharge.png b/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_nocharge.png new file mode 100644 index 0000000..fd3e6ff Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_nocharge.png differ diff --git a/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_power.png b/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_power.png new file mode 100644 index 0000000..87962a6 Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-alt3_laptop_power.png differ diff --git a/klaptopdaemon/pics/actions/cr16-action-alt_laptop_nocharge.png b/klaptopdaemon/pics/actions/cr16-action-alt_laptop_nocharge.png new file mode 100644 index 0000000..8a257fd Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-alt_laptop_nocharge.png differ diff --git a/klaptopdaemon/pics/actions/cr16-action-alt_laptop_power.png b/klaptopdaemon/pics/actions/cr16-action-alt_laptop_power.png new file mode 100644 index 0000000..211b5f6 Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-alt_laptop_power.png differ diff --git a/klaptopdaemon/pics/actions/cr16-action-laptop_charge.png b/klaptopdaemon/pics/actions/cr16-action-laptop_charge.png new file mode 100644 index 0000000..717d37f Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-laptop_charge.png differ diff --git a/klaptopdaemon/pics/actions/cr16-action-laptop_nobattery.png b/klaptopdaemon/pics/actions/cr16-action-laptop_nobattery.png new file mode 100644 index 0000000..7c6b8bc Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-laptop_nobattery.png differ diff --git a/klaptopdaemon/pics/actions/cr16-action-laptop_nocharge.png b/klaptopdaemon/pics/actions/cr16-action-laptop_nocharge.png new file mode 100644 index 0000000..e5e8418 Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-laptop_nocharge.png differ diff --git a/klaptopdaemon/pics/actions/cr16-action-power.png b/klaptopdaemon/pics/actions/cr16-action-power.png new file mode 100644 index 0000000..ac7deec Binary files /dev/null and b/klaptopdaemon/pics/actions/cr16-action-power.png differ diff --git a/klaptopdaemon/pics/actions/cr22-action-laptop_charge.png b/klaptopdaemon/pics/actions/cr22-action-laptop_charge.png new file mode 100644 index 0000000..4a9fad1 Binary files /dev/null and b/klaptopdaemon/pics/actions/cr22-action-laptop_charge.png differ diff --git a/klaptopdaemon/pics/actions/cr22-action-laptop_nobattery.png b/klaptopdaemon/pics/actions/cr22-action-laptop_nobattery.png new file mode 100644 index 0000000..07e9f0d Binary files /dev/null and b/klaptopdaemon/pics/actions/cr22-action-laptop_nobattery.png differ diff --git a/klaptopdaemon/pics/actions/cr22-action-laptop_nocharge.png b/klaptopdaemon/pics/actions/cr22-action-laptop_nocharge.png new file mode 100644 index 0000000..1eda606 Binary files /dev/null and b/klaptopdaemon/pics/actions/cr22-action-laptop_nocharge.png differ diff --git a/klaptopdaemon/pics/actions/cr22-action-laptop_power.png b/klaptopdaemon/pics/actions/cr22-action-laptop_power.png new file mode 100644 index 0000000..92b6328 Binary files /dev/null and b/klaptopdaemon/pics/actions/cr22-action-laptop_power.png differ diff --git a/klaptopdaemon/pics/actions/cr32-action-power.png b/klaptopdaemon/pics/actions/cr32-action-power.png new file mode 100644 index 0000000..e785191 Binary files /dev/null and b/klaptopdaemon/pics/actions/cr32-action-power.png differ diff --git a/klaptopdaemon/pics/cr128-app-laptop_battery.png b/klaptopdaemon/pics/cr128-app-laptop_battery.png new file mode 100644 index 0000000..48561f6 Binary files /dev/null and b/klaptopdaemon/pics/cr128-app-laptop_battery.png differ diff --git a/klaptopdaemon/pics/cr16-app-laptop_battery.png b/klaptopdaemon/pics/cr16-app-laptop_battery.png new file mode 100644 index 0000000..7deaf05 Binary files /dev/null and b/klaptopdaemon/pics/cr16-app-laptop_battery.png differ diff --git a/klaptopdaemon/pics/cr16-app-laptop_pcmcia.png b/klaptopdaemon/pics/cr16-app-laptop_pcmcia.png new file mode 100644 index 0000000..e8eda78 Binary files /dev/null and b/klaptopdaemon/pics/cr16-app-laptop_pcmcia.png differ diff --git a/klaptopdaemon/pics/cr32-app-laptop_battery.png b/klaptopdaemon/pics/cr32-app-laptop_battery.png new file mode 100644 index 0000000..5358826 Binary files /dev/null and b/klaptopdaemon/pics/cr32-app-laptop_battery.png differ diff --git a/klaptopdaemon/pics/cr32-app-laptop_pcmcia.png b/klaptopdaemon/pics/cr32-app-laptop_pcmcia.png new file mode 100644 index 0000000..534e548 Binary files /dev/null and b/klaptopdaemon/pics/cr32-app-laptop_pcmcia.png differ diff --git a/klaptopdaemon/pics/cr48-app-laptop_battery.png b/klaptopdaemon/pics/cr48-app-laptop_battery.png new file mode 100644 index 0000000..4038d44 Binary files /dev/null and b/klaptopdaemon/pics/cr48-app-laptop_battery.png differ diff --git a/klaptopdaemon/pics/cr48-app-laptop_pcmcia.png b/klaptopdaemon/pics/cr48-app-laptop_pcmcia.png new file mode 100644 index 0000000..faad8ff Binary files /dev/null and b/klaptopdaemon/pics/cr48-app-laptop_pcmcia.png differ diff --git a/klaptopdaemon/pics/cr64-app-laptop_battery.png b/klaptopdaemon/pics/cr64-app-laptop_battery.png new file mode 100644 index 0000000..8a6a92d Binary files /dev/null and b/klaptopdaemon/pics/cr64-app-laptop_battery.png differ diff --git a/klaptopdaemon/pics/crsc-app-laptop_battery.svgz b/klaptopdaemon/pics/crsc-app-laptop_battery.svgz new file mode 100644 index 0000000..07ae4e5 Binary files /dev/null and b/klaptopdaemon/pics/crsc-app-laptop_battery.svgz differ diff --git a/klaptopdaemon/portable.cpp b/klaptopdaemon/portable.cpp new file mode 100644 index 0000000..f56dc1e --- /dev/null +++ b/klaptopdaemon/portable.cpp @@ -0,0 +1,3087 @@ +/* + * portable.cpp + * + * $Id$ + * + * Copyright (c) 1999 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// +// this file contains the machine specific laptop power management stuff +// to add support for your own OS this is should be the only place you need +// to change - to add your own stuff insert above the line marked +// 'INSERT HERE' : +// +// #ifdef MY_OS" +// .. copy of linux code or whatever you want to use as a base +// # else +// +// then tag an extra '#endif' at the end +// +// There is support for the following OSsen right now: +// +// Linux (#if __linux__) +// FreeBSD (#elif __FreeBSD__) +// NetBSD (#elif __NetBSD_APM__) +// generic nothing (#else) +// +// +// The code here is written in a C rather than C++ like to encourage +// people more used to kernel types to do stuff here +// +// If you have any problems, questions, whatever please get in touch +// +// Paul Campbell +// paul@taniwha.com +// +// +// Thanks to Cajus Pollmeier +// and Robert Ellis Parrott +// who both provided ACPI support +// and Volker Krause who provided ACPI bug fixes +// + +#include +#include +#include +#include +#include "portable.h" + +#ifdef __linux__ + +/* +** This is the Linux-specific laptop code. +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// ibm specific stuff +extern "C"{ +#include "thinkpad_common.h" +#include "smapi.h" +#include "smapidev.h" +} + +// +// here's the Linux specific laptop control panel stuff +// + +typedef struct apm_info { + unsigned int apm_flags; + unsigned int ac_line_status; + int battery_percentage; + int battery_time; +} apm_info; + +static int +apm_read(apm_info *ap) +{ + FILE *f = 0; + char tmp2[10]; + int tmp, s; + unsigned int utmp; + char version[256]; + + f = fopen("/proc/apm", "r"); + if (f == NULL) + return(1); + s = fscanf(f, "%255s %d.%d %x %x %x %x %d%% %d %s\n", + version, + &tmp, + &tmp, + &ap->apm_flags, + &ap->ac_line_status, + &utmp, + &utmp, + &ap->battery_percentage, + &ap->battery_time, + tmp2); + fclose(f); + if (s < 9) + return(1); + if (version[0] == 'B') + return(2); + if (ap->battery_percentage > 100) + ap->battery_percentage = -1; + if (strcmp(tmp2, "sec") == 0) + ap->battery_time /= 60; + return(0); +} + + +// 0 => unknown +// 1 => have it +// -1 => don't have it +static int pmustate = 0; + +static bool +have_pmu(void) +{ + if (pmustate != 0) + return (pmustate == 1); + if (!access("/proc/pmu", R_OK|X_OK)) { + kdDebug() << "Found powermac PMU. Using that." << endl; + pmustate = 1; + return true; + } + pmustate = -1; + return false; +} + +/* Only supports 1 battery right now - all batteries are merged into one stat */ +static int +pmu_read(apm_info *ap) +{ + int bcnt = 0; + memset(ap, 0, sizeof(apm_info)); + QFile f("/proc/pmu/info"); + if (!f.open(IO_ReadOnly)) + return 1; + + while (!f.atEnd()) { + QString l; + f.readLine(l, 500); + QStringList ll = QStringList::split(':', l, false); + if (ll[0].stripWhiteSpace() == "AC Power") { + ap->ac_line_status = ll[1].stripWhiteSpace().toInt(); + //kdDebug() << "line status " << ap->ac_line_status << endl; + } else if (ll[0].stripWhiteSpace() == "Battery count") { + bcnt = ll[1].stripWhiteSpace().toInt(); + //kdDebug() << "batteries: " << bcnt << endl; + } + } + + f.close(); + + int charge = 0; + int timerem = 0; + int maxcharge = 0; + for (int i = 0; i < bcnt; i++) { + QFile bf(QString("/proc/pmu/battery_%1").arg(i)); + if (!bf.open(IO_ReadOnly)) + continue; + + while(!bf.atEnd()) { + QString l; + bf.readLine(l, 500); + QStringList ll = QStringList::split(':', l, false); + if (ll[0].stripWhiteSpace() == "charge") { + charge += ll[1].stripWhiteSpace().toInt(); + //kdDebug() << "charge: " << charge << endl; + } else if (ll[0].stripWhiteSpace() == "max_charge") { + maxcharge += ll[1].stripWhiteSpace().toInt(); + //kdDebug() << "max charge: " << maxcharge << endl; + } else if (ll[0].stripWhiteSpace() == "time rem.") { + timerem += ll[1].stripWhiteSpace().toInt(); + //kdDebug() << "time: " << timerem << endl; + } + } + bf.close(); + } + ap->battery_percentage = int(rint(100.0*float(float(charge)/float(maxcharge)))); + ap->battery_time = timerem; + + if (ap->ac_line_status > 0 || timerem == 0 || + (ap->ac_line_status == 0 && charge > 100 && timerem == 0)) + ap->battery_time = -1; + + return 0; +} + + +struct acpi_battery_info { + int percentage; + bool present; + int cap; + int cap_low; + int remaining; + int rate; + QString name; + QString state_file; + QString info_file; +}; + +static QValueVector acpi_batteries; +static int acpi_last_known=0; +static int last_seed=1; // increment this to force revaluation + +static unsigned char acpi_ac_ok; + +// +// linux APCI doesn't return useful stuff like how much TIME is left yet +// the 'rate' is not smoothed over time so it's faked out here +// it's not pretty and it's a quick estimate +// +// for the moment we prefer APM +// + +static int +acpi_ac_status() +{ + DIR *dfd; + struct dirent *dp; + FILE *f = NULL; + static char buff[NAME_MAX+50]; + static bool inited=0; + static bool bad=0; + + if (inited) { + if (bad) + return(-1); + f = fopen(buff, "r"); + goto readit; + } + inited = 1; + + dfd = opendir("/proc/acpi/ac_adapter/"); + if (dfd) { + for (;;) { + dp = readdir(dfd); + if (dp == 0) + break; + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + strcpy(buff, "/proc/acpi/ac_adapter/"); + strcat(buff, dp->d_name); + strcat(buff, "/status"); + f = fopen(buff, "r"); + if (!f) { + strcpy(buff, "/proc/acpi/ac_adapter/"); + strcat(buff, dp->d_name); + strcat(buff, "/state"); + f = fopen(buff, "r"); + } + if (f) + break; + } + closedir(dfd); +readit: + if (f) { + for (;;) { + char buff2[1024]; + if (fgets(buff2, sizeof(buff), f) == NULL) + break; + if (strstr(buff2, "Status:") != NULL || + strstr(buff2, "state:") != NULL) { + if (strstr(buff2, "on-line") != NULL) { + fclose(f); + return(1); + } + } + } + fclose(f); + return(0); + } + } + bad=1; + return(-1); +} + +static void acpi_read_batteries() { + QString buff; + QFile *f; + static int test_count = 0; + bool skip = false; + + for(unsigned int i = 0; i < acpi_batteries.count(); ++i) { + acpi_battery_info& bat = acpi_batteries[i]; + bool present = false; + if ((test_count==0 || acpi_last_known != last_seed) && !bat.info_file.isNull()) { + f = new QFile(bat.info_file); + if (f && f->open(IO_ReadOnly)) { + while(f->readLine(buff,1024) > 0) { + if (buff.contains("design capacity low:", false)) { + QRegExp rx("(\\d*)\\D*$"); + rx.search(buff); + bat.cap_low = rx.cap(1).toInt(); + if (bat.cap_low < 0) + bat.cap_low = 0; + continue; + } + if (buff.contains("last full capacity:", false)) { + QRegExp rx("(\\d*)\\D*$"); + rx.search(buff); + bat.cap = rx.cap(1).toInt(); + continue; + } + } + f->close(); + bat.cap -= bat.cap_low; + } + delete f; + } + if (bat.cap <= 0) { + KConfig* config = new KConfig("kcmlaptoprc", true /*readonly*/, false /*useKDEGlobals*/); + config->setGroup("AcpiBattery"); + bat.cap = config->readNumEntry(bat.name,0); + delete config; + } + if (!bat.state_file.isNull()) { + f = new QFile(bat.state_file); + if (f && f->open(IO_ReadOnly)) { + while(f->readLine(buff,1024) > 0) { + if (buff.contains("present rate:", false)) { + QRegExp rx("(\\d*)\\D*$"); + rx.search(buff); + bat.rate = rx.cap(1).toInt(); + if (bat.rate < 0) + bat.rate = 0; + present = true; + continue; + } + if (buff.contains("remaining capacity:", false)) { + QRegExp rx("(\\d*)\\D*$"); + rx.search(buff); + bat.remaining = rx.cap(1).toInt(); + bat.remaining -= bat.cap_low; + if (bat.remaining < 0) + bat.remaining = 0; + present = true; + continue; + } + } + f->close(); + } + delete f; + } + if(present && !bat.present) // recheck capacity if a battery was put in + skip = true; + bat.present = present; + if (bat.present) { + if (bat.remaining > bat.cap) { // happens e.g. if the system doesn't provide a capacity value + bat.cap = bat.remaining; + KConfig* config = new KConfig("kcmlaptoprc", false /*readonly*/, false /*useKDEGlobals*/); + config->setGroup("AcpiBattery"); + config->writeEntry(bat.name, bat.cap); + config->sync(); + delete config; + skip = true; + } + if (bat.cap == 0) + bat.percentage = 0; + else + bat.percentage = bat.remaining*100/bat.cap; + } + else + bat.percentage = 0; + } + + if (!skip) { + acpi_last_known = last_seed; + test_count++; + } + else + test_count = 0; + if (test_count > 1000) // every 1000 or so times recheck the battery capacity + test_count = 0; + +} + +static int +acpi_read(apm_info *ap) +{ + int rate, part, total; + int ret = 1; + bool present = 0; + + part = 0; + total = 0; + rate = 0; + + acpi_read_batteries(); + + for(unsigned int i = 0; i < acpi_batteries.count(); ++i) { + acpi_battery_info& bat = acpi_batteries[i]; + present |= bat.present; + if(bat.present) { + total += bat.cap; + part += bat.remaining; + rate += bat.rate; + } + ret = 0; + } + + // some broken ACPI implementations don't return a rate + // compute a 'fake' rate by diffing remaining values + if (rate == 0) + { + static int last_remaining = 0; + static time_t last_time = 0; + if (last_remaining != 0 + && last_time != 0) + { + int diff_time = time(0) - last_time; + if (diff_time > 0) + rate = (last_remaining - part) * 3600 / diff_time; + } + last_remaining = part; + last_time = time(0); + if (rate < 0) + rate = 0; + } + + static int nrates = 0; + static int saved_rate[8]; + static unsigned char ignore_next = 2; // ignore the first couple + + ap->ac_line_status = 0; + // + // ACPI (unlike nice systems like some APM implementations) doesn't + // tell us how much battery TIME we have left - here we + // do a weighted average of the discharge rate (in mW) and + // figure out how long we have left by dividing it into the + // remaining capacity + // + // because some ACPI implementations return bogus + // rates when charging we can't estimate the battery life + // so we only collect discharge rate data when we're actually + // discharging + // + if (acpi_ac_status() == 1) { + ap->ac_line_status |= 1; + ignore_next = 2; + } else { + // after switching from power to unpowered we often get + // a bad reading from ACPI resulting in bizarre + // readings + if (ignore_next == 0) { + if (nrates < 8) // smooth the power flow + nrates++; // simple box filter + for (int i = 8-1; i > 0; i--) + saved_rate[i] = saved_rate[i-1]; + saved_rate[0] = rate; + } else { + ignore_next--; + } + } + // + // if we haven't got any discharge rate data yet don't return a + // battery time - probably happens when you start up with the + // ac adaptor plugged in + // + if (nrates == 0) { + ap->battery_time = -1; + } else { + rate = 0; + for (int i = 0; i < nrates; i++) + rate += saved_rate[i]; + rate = (rate+2*saved_rate[0])/(nrates+2); // weight it slighly + ap->battery_time = (rate==0 ? -1 : 60*part/rate); + } + ap->battery_percentage = (total==0?0:100*part/total); + if (!present) { + ap->battery_percentage = -1; + ap->battery_time = -1; + } + ap->apm_flags = 0; + return(ret); +} + +static int apm_no_time; +static apm_info apmx = {0,0,0,0}; +static int +has_apm() +{ + static int init = 0; + static int val; + if (init) + return(val); + init = 1; + val = 1; + apm_no_time=0; + if (apm_read(&apmx) || (apmx.apm_flags&0x20)) { + val = 0; + apm_no_time = 1; + } else { + apm_no_time = apmx.battery_time < 0; + } + + if (val == 0) { + val = have_pmu(); + if (val && pmu_read(&apmx)) { + val = 0; + } + } + return(val); +} + +// Power to the powermacs!! +static int +has_pmu() +{ + static int init = 0; + static int val; + if (init) + return val; + init = 1; + val = 1; + if (!QDir("/proc/pmu").exists()) { + val = 0; + } + return val; +} + +static bool software_suspend_is_preferred = false; // user prefers to use SS for hibernate +static bool acpi_helper_ok(bool type); +static bool +has_software_suspend(int type) +{ + static int known=0; + static bool present=0; // functionality seems to be here + static bool available=0; // helper can work + if (known != last_seed) { + known = last_seed; + available = 0; + present = (((::access("/proc/sys/kernel/swsusp", F_OK) == 0) || + (::access("/proc/software_suspend", F_OK) == 0) || + (::access("/proc/suspend2", F_OK) == 0)) && + ::access("/usr/sbin/hibernate", F_OK) == 0); + if (present) { + if (::getuid() == 0) { // running as root + available = ::access("/usr/sbin/hibernate", X_OK) == 0 && acpi_helper_ok(1); + } else { + available = acpi_helper_ok(0); + } + } + } + switch (type) { + case 0: return(present); + case 1: return(present&available&software_suspend_is_preferred); + case 2: return(present&available); + default:return(0); + } +} + +bool +laptop_portable::has_software_suspend(int type) +{ + return(::has_software_suspend(type)); +} + +void +laptop_portable::software_suspend_set_mask(bool hibernate) +{ + software_suspend_is_preferred = hibernate; +} + + +static int x_acpi_init = 0; +static bool +has_acpi() +{ + static bool val; + static bool checked = 0; + + if (!checked) { + val = ::access("/proc/acpi", F_OK) == 0; + checked = 1; + } + return(val); +} + +static int +has_acpi_power() +{ + static int val; + + if (x_acpi_init) + return(val); + x_acpi_init = 1; + val = 0; + + acpi_batteries.clear(); + + if (acpi_ac_status() >= 0) + acpi_ac_ok = 1; + + QDir battdir("/proc/acpi/battery"); + battdir.setFilter(QDir::Dirs); + if(!battdir.isReadable()) + return(val = 0); + for(uint i = 0; !battdir[i].isNull(); ++i) { + if(battdir[i] == "." || battdir[i] == "..") + continue; + bool ok = 0; + acpi_battery_info bat = {0,0,0,0,0,0,0,0,0}; + QString base = battdir.path() + "/" + battdir[i] + "/"; + QString name(base + "state"); + QFileInfo f(name); + if(f.isReadable()) { + bat.state_file = name; + ok = true; + } else { + name = base + "status"; + f.setFile(name); + if(f.isReadable()) { + bat.state_file = name; + ok = true; + } + } + name = base + "info"; + f.setFile(name); + if(f.isReadable()) { + bat.info_file = name; + ok = true; + } + if (ok) { + bat.name = battdir[i]; + acpi_batteries.append(bat); + val = 1; + } + } + if (!acpi_ac_ok) + val = 0; + return(val); +} + +static unsigned long acpi_sleep_enabled = 0x00; // acpi sleep functions enabled mask + + +static bool +has_acpi_sleep(int state) +{ + static int known=0; + static unsigned long mask=0; + if (known != last_seed) { + known = last_seed; + mask = 0; + + QFile p("/sys/power/state"); + QFile f("/proc/acpi/sleep"); + + if (p.open(IO_ReadOnly)) { + QString l; + QTextStream t(&p); + l = t.readLine(); + QStringList ll = QStringList::split(' ',l,false); + for (QValueListIterator i = ll.begin(); i!=ll.end(); i++) { + QString s = *i; + + if (s.compare("standby")==0) + mask |= (1<<1); + else if (s.compare("mem")==0) + mask |= (1<<3); + else if (s.compare("disk")==0) + mask |= (1<<4); + } + p.close(); + } + else if (f.open(IO_ReadOnly)) { + QString l; + QTextStream t(&f); + l = t.readLine(); + QStringList ll = QStringList::split(' ',l,false); + for (QValueListIterator i = ll.begin(); i!=ll.end(); i++) { + QString s = *i; + if (s[0] == 'S') { + int c = s[1].digitValue(); + if (c >= 0 && c <= 9) + mask |= 1<= 0) { + result = 1; + return(1); + } + ibm_device = "/dev/thinkpad/thinkpad"; + if ((ibm_fd = open(ibm_device, O_RDWR)) < 0) { + ibm_device = "/dev/thinkpad"; + if ((ibm_fd = open(ibm_device, O_RDWR)) < 0) + return(0); + } + result = 1; + return(1); +} +// +// returns 1 if we support power management +// +int laptop_portable::has_power_management() +{ + if (::has_apm()) + return 1; + if (::has_pmu()) + return 1; + if (::has_acpi_power()) + return 1; + if (::has_ibm()) + return 1; + // INSERT HERE + return 0; +} +// +// returns 1 if the BIOS returns the time left in the battery rather than a % of full +// +int laptop_portable::has_battery_time() +{ + if (::has_acpi_power()) + return 1; + if (::apm_has_time()) + return 1; + // INSERT HERE + return 0; +} +// +// returns 1 if we can perform a change-to-suspend-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_suspend() +{ + if (::has_acpi()) + return ::acpi_sleep_access_ok() && ::has_acpi_sleep(3); + if (::has_pmu()) + return 1; + if (::has_ibm()) + return 1; + if (::has_apm()) + return ::apm_sleep_access_ok() && ::has_apm_sleep(3); + // INSERT HERE + return 0; +} +// +// returns 1 if we can perform a change-to-standby-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_standby() +{ + if (::has_pmu()) + return 0; + if (::has_acpi()) + return ::acpi_sleep_access_ok() && (::has_acpi_sleep(1)||::has_acpi_sleep(2)); + if (::has_ibm()) + return 1; + if (::has_apm()) + return ::apm_sleep_access_ok() && ::has_apm_sleep(2); + // INSERT HERE + return 0; +} +// +// returns 1 if we can perform a change-to-hibernate-mode for a user +// (has_power_management() has already returned 1) [hibernate is the save-to-disk mode +// not supported by linux APM] +// +int laptop_portable::has_hibernation() +{ + if (::has_pmu()) + return 0; + if (::has_software_suspend(1)) // must be before acpi + return 1; + if (::has_acpi()) + return ::acpi_sleep_access_ok() && ::has_acpi_sleep(4); + if (::has_ibm()) + return 1; + // INSERT HERE + return 0; +} + +// +// explain to the user what they need to do if has_power_management() returned 0 +// to get any software they lack +// + +KActiveLabel *laptop_portable::no_power_management_explanation(QWidget *parent) +{ + if (access("/proc/acpi", F_OK) == 0) { // probably has default kernel ACPI installed + KActiveLabel* explain = new KActiveLabel(i18n("Your computer seems to have a partial ACPI installation. ACPI was probably enabled, but some of the sub-options were not - you need to enable at least 'AC Adaptor' and 'Control Method Battery' and then rebuild your kernel."), parent); + return(explain); + } + + KActiveLabel* explain = new KActiveLabel(i18n("Your computer doesn't have the Linux APM (Advanced Power Management) or ACPI software installed, or doesn't have the APM kernel drivers installed - check out the Linux Laptop-HOWTO document for information on how to install APM."), parent); + + return(explain); +} + +// +// explain to the user what they need to do to get suspend/resume to work from user mode +// +QLabel *laptop_portable::how_to_do_suspend_resume(QWidget *parent) +{ + if (::has_apm()) { + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + QLabel* note = new KRichTextLabel(i18n("\nIf you make /usr/bin/apm setuid then you will also " + "be able to choose 'suspend' and 'standby' in the above " + "dialog - check out the help button below to find out " + "how to do this").replace("\n", QString::null), parent); + return(note); + } + if (::has_acpi()) { + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + QLabel* note = new KRichTextLabel(i18n("\nYou may need to enable ACPI suspend/resume in the ACPI panel").replace("\n", QString::null), parent); + return(note); + } + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + QLabel* note = new KRichTextLabel(i18n("\nYour system does not support suspend/standby").replace("\n", QString::null), parent); + return(note); +} + +static char tmp0[256], tmp1[256]; +static int present=0; +static +void get_pcmcia_info() +{ + FILE *f = fopen("/var/lib/pcmcia/stab", "r"); + if (!f) f = fopen("/var/run/stab", "r"); + if (f) { + int c; + char *cp; + + present = 1; + cp = tmp0; + for (;;) { + c = fgetc(f); + if (c == EOF || c == '\n') + break; + if (c == ':') { + while ((c = fgetc(f)) == ' ') + ; + if (c == EOF) + break; + for (;;) { + *cp++ = c; + c = fgetc(f); + if (c == EOF || c == '\n') + break; + } + break; + } + } + *cp = 0; + + if (c != EOF) { + cp = tmp1; + for (;;) { + c = fgetc(f); + if (c == EOF) + break; + if (c == ':') { + while ((c = fgetc(f)) == ' ') + ; + if (c == EOF) + break; + for (;;) { + *cp++ = c; + c = fgetc(f); + if (c == EOF || c == '\n') + break; + } + break; + } + } + *cp = 0; + } + + fclose(f); + } else { + present = 0; + } +} + +// +// pcmcia support - this will be replaced by better - pcmcia support being worked on by +// others +// +QLabel *laptop_portable::pcmcia_info(int x, QWidget *parent) +{ + if (x == 0) + get_pcmcia_info(); + if (!present) { + if (x == 1) + return(new QLabel(i18n("No PCMCIA controller detected"), parent)); + return(new QLabel(i18n(""), parent)); + } else { + switch (x) { + case 0: return(new QLabel(i18n("Card 0:"), parent)); + case 1: return(new QLabel(tmp0, parent)); + case 2: return(new QLabel(i18n("Card 1:"), parent)); + default:return(new QLabel(tmp1, parent)); + } + } +} + +// +// puts us into standby mode +// +void laptop_portable::invoke_standby() +{ + last_seed++; // make it look for battery removal/return + if (::has_acpi()) { + if (::has_acpi_sleep(1)) { // people seem to argue as to which is 'standby' the S1 people are winning + ::invoke_acpi_helper("--standby", 0, 0); + } else { + ::invoke_acpi_helper("--standby2", 0, 0); + } + return; + } + if (::has_ibm()) { + smapi_ioparm_t ioparmMy; + sync(); + ioparmMy.in.bFunc = (byte) 0x70; + ioparmMy.in.bSubFunc = (byte) 0; + ioparmMy.in.wParm1 = (word) 0; + ioparmMy.in.wParm2 = (word) 0; + ioparmMy.in.wParm3 = (word) 0; + ioparmMy.in.dwParm4 = (dword) 0; + ioparmMy.in.dwParm5 = (dword) 0; + (void)ioctl_smapi( ibm_fd, &ioparmMy ); + return; + } + // add other machine specific standbys here + KProcess proc; + proc << "/usr/bin/apm"; + proc << "--standby"; + proc.start(KProcess::Block); // helper runs fast and we want to see the result +} + +// +// puts us into suspend mode +// +void laptop_portable::invoke_suspend() +{ + last_seed++; // make it look for battery removal/return + + if (::has_pmu()) { + KProcess proc; + proc << "/usr/bin/apm"; + proc << "-f"; + proc.start(KProcess::Block); // helper runs fast and we want to see the result + return; + } + + if (::has_acpi()) { + ::invoke_acpi_helper("--suspend", 0, 0); + return; + } + if (::has_ibm()) { + smapi_ioparm_t ioparmMy; + sync(); + ioparmMy.in.bFunc = (byte) 0x70; + ioparmMy.in.bSubFunc = (byte) 1; + ioparmMy.in.wParm1 = (word) 0; + ioparmMy.in.wParm2 = (word) 0; + ioparmMy.in.wParm3 = (word) 0; + ioparmMy.in.dwParm4 = (dword) 0; + ioparmMy.in.dwParm5 = (dword) 0; + (void)ioctl_smapi( ibm_fd, &ioparmMy ); + return; + } + // add other machine specific suspends here + KProcess proc; + proc << "/usr/bin/apm"; + proc << "--suspend"; + proc.start(KProcess::Block); // helper runs fast and we want to see the result +} + +// +// puts us into hibernate mode +// +void laptop_portable::invoke_hibernation() +{ + last_seed++; // make it look for battery removal/return + if (::has_software_suspend(1)) { // must be before acpi + ::invoke_acpi_helper("--software-suspend", 0, 0); + return; + } + if (::has_acpi()) { + ::invoke_acpi_helper("--hibernate", 0, 0); + return; + } + if (::has_ibm()) { + smapi_ioparm_t ioparmMy; + sync(); + ioparmMy.in.bFunc = (byte) 0x70; + ioparmMy.in.bSubFunc = (byte) 2; + ioparmMy.in.wParm1 = (word) 0; + ioparmMy.in.wParm2 = (word) 0; + ioparmMy.in.wParm3 = (word) 0; + ioparmMy.in.dwParm4 = (dword) 0; + ioparmMy.in.dwParm5 = (dword) 0; + (void)ioctl_smapi( ibm_fd, &ioparmMy ); + return; + } + // add other machine specific hibernates here +} + +void +laptop_portable::extra_config(QWidget *wp, KConfig *, QVBoxLayout *top_layout) +{ + if (laptop_portable::has_apm(1) || laptop_portable::has_acpi(1)) + return; + if (laptop_portable::has_apm(0)) { + QLabel* explain = new KRichTextLabel( i18n("Your system has APM installed but may not be able to use all " + "of its features without further setup - look in the 'APM Config' " + "tab for information about setting up APM for suspend and resume"), wp); + top_layout->addWidget(explain, 0); + } + if (laptop_portable::has_acpi(0)) { + QLabel* explain = new KRichTextLabel( i18n("Your system has ACPI installed but may not be able to use all " + "of its features without further setup - look in the 'ACPI Config' " + "tab for information about setting up ACPI for suspend and resume"), wp); + top_layout->addWidget(explain, 0); + } +} + +// +// return current battery state +// +struct power_result laptop_portable::poll_battery_state() +{ + struct power_result p; + + apm_info x = {0,0,0,-1}; + if (have_pmu()) { + pmu_read(&x); + } else + if ((::has_acpi_power() ? ::acpi_read(&x) : ::apm_read(&x)) || (x.apm_flags&0x20)) { + // INSERT HERE + p.powered = 0; + p.percentage=0; + p.time = -1; + return p; + } + p.powered = x.ac_line_status&1; + p.percentage = x.battery_percentage; + p.time = x.battery_time; + return(p); +} + +void +laptop_portable::get_battery_status(int &num_batteries, QStringList &names, QStringList &state, QStringList &values) +{ + struct power_result r; + + if (!has_power_management()) { + num_batteries = 0; + names.clear(); + state.clear(); + values.clear(); + return; + } + + if (::has_acpi_power()) { + names.clear(); + state.clear(); + values.clear(); + acpi_read_batteries(); + num_batteries = acpi_batteries.count(); + for(unsigned int i = 0; i < acpi_batteries.count(); ++i) { + acpi_battery_info& bat = acpi_batteries[i]; + names.append(bat.name); + values.append(QString("%1").arg(bat.percentage)); + state.append(bat.present ? "yes" : "no"); + } + return; + } + + // INSERT HERE + + num_batteries = 1; + r = poll_battery_state(); + names.append("BAT1"); + state.append("yes"); + QString s; + s.setNum(r.percentage); + values.append(s); +} + + +// +// returns the current system load average, -1 if none +// +static QFile lav_file; +static bool lav_inited=0; +static bool lav_openok=0; + +static bool has_lav() +{ + if (!lav_inited) { + lav_inited =1; + lav_file.setName("/proc/loadavg"); + lav_openok = lav_file.open( IO_ReadOnly ); + if (lav_openok) + lav_file.close(); + } + return(lav_openok); +} + +bool laptop_portable::has_lav() +{ + return ::has_lav(); +} + +float laptop_portable::get_load_average() +{ + if (!::has_lav()) + return(-1); + lav_file.open( IO_ReadOnly ); + QString l; + lav_file.readLine(l, 500); + lav_file.close(); + QStringList ll = QStringList::split(' ', l, false); + l = ll[0]; + bool ok; + float f = l.toFloat(&ok); + if (!ok) + f = -1; + return(f); +} + + +int laptop_portable::has_cpufreq() { + struct stat sb; + int rc; + rc = stat("/proc/cpufreq", &sb); + if (rc == 0) { + rc = stat("/proc/cpuinfo", &sb); + if (rc == 0) + return 1; + } + // INSERT HERE + return 0; +} + + +QString laptop_portable::cpu_frequency() { + QString rc; + QFile cf("/proc/cpufreq"); + bool haveProfile = false; + + if (cf.open(IO_ReadOnly)) { + while (!cf.atEnd()) { + QString l; + cf.readLine(l, 500); + if (l.left(3) == "CPU") { + QStringList ll = QStringList::split(' ', l, false); + rc = ll.last(); + haveProfile = true; + break; + } + } + + } + if (haveProfile) { + QFile ci("/proc/cpuinfo"); + if (ci.open(IO_ReadOnly)) { + while (!ci.atEnd()) { + QString l; + ci.readLine(l, 500); + QStringList ll = + QStringList::split(':',l,false); + if (ll.count() != 2) + continue; + if (ll.first().stripWhiteSpace() + == "cpu MHz") { + rc = i18n("%1 MHz (%2)").arg(ll.last().stripWhiteSpace()).arg(rc); + break; + } else if (ll.first().stripWhiteSpace() + == "clock") { + rc = QString("%1 (%2)").arg(ll.last().stripWhiteSpace()).arg(rc); + break; + } + } + } + } + + return rc; +} + +static int sonyFd = -1; +static int has_toshiba_brightness = 0; + +static bool +acpi_helper_ok(bool type) +{ + static int known[2]={0,0}; + static bool known_res[2]; + + if (known[type] == last_seed) + return(known_res[type]); + known[type] = last_seed; + known_res[type] = 0; + struct stat sb; + QString str = KStandardDirs::findExe("klaptop_acpi_helper"); + if (str.isNull() || str.isEmpty()) + return(0); + + if (stat(str.latin1(), &sb) < 0) + return(0); + if (!S_ISREG(sb.st_mode)) + return(0); + if (!type && getuid() != 0 && (sb.st_uid != 0 || !(sb.st_mode&S_ISUID))) + return(0); + if (!(sb.st_mode&0x111)) + return(0); + known_res[type] = 1; + return(1); +} + +static bool +acpi_sleep_access_ok() +{ + static int known=0; + static int known_res=1; + + if (known != last_seed) { + known = last_seed; + known_res = (::access("/proc/acpi/sleep", R_OK|W_OK)==0 && ::acpi_helper_ok(1)) || + (::access("/proc/acpi/sleep", R_OK)==0 && ::acpi_helper_ok(0)) || + (::access("/sys/power/state", R_OK|W_OK)==0 && ::acpi_helper_ok(1)) || + (::access("/sys/power/state", R_OK)==0 && ::acpi_helper_ok(0)); + } + return(known_res); +} + +static bool +apm_helper_ok(bool type) +{ + static int known[2]={0,0}; + static bool known_res[2]; + + if (known[type] == last_seed) + return(known_res[type]); + known[type] = last_seed; + known_res[type] = 0; + struct stat sb; + QString str = "/usr/bin/apm"; + if (str.isNull() || str.isEmpty()) + return(0); + if (stat(str.latin1(), &sb) < 0) + return(0); + if (!S_ISREG(sb.st_mode)) + return(0); + if (!type && getuid() != 0 && (sb.st_uid != 0 || !(sb.st_mode&S_ISUID))) + return(0); + if (!(sb.st_mode&0x111)) + return(0); + known_res[type] = 1; + return(1); +} + +static bool +apm_sleep_access_ok() +{ + static int known=0; + static int known_res=1; + + if (known != last_seed) { + known = last_seed; + known_res = (::access("/proc/apm", R_OK|W_OK)==0 && ::apm_helper_ok(1)) || + (::access("/proc/apm", R_OK)==0 && ::apm_helper_ok(0)); + } + return(known_res); +} + +int +laptop_portable::has_brightness() +{ + static int known=0; + static int known_res=1; + + if (known == last_seed) + return(known_res); + known = last_seed; + if (sonyFd == -1 && ::access("/dev/sonypi", R_OK) == 0) + sonyFd = ::open("/dev/sonypi", O_RDONLY|O_NONBLOCK); + if (sonyFd >= 0) + return(1); + if (::has_acpi() && + (((::access("/proc/acpi/TOSHIBA1/lcd", R_OK|W_OK)==0 || ::access("/proc/acpi/toshiba/lcd", R_OK|W_OK)==0) && ::acpi_helper_ok(1)) || + ((::access("/proc/acpi/TOSHIBA1/lcd", R_OK)==0 || ::access("/proc/acpi/toshiba/lcd", R_OK)==0) && ::acpi_helper_ok(0)))) { + has_toshiba_brightness = 1; + return(1); + } + // check for new devices here + // INSERT HERE + known_res = 0; + return 0; +} + +#define SONYPI_IOCSBRT _IOW('v', 0, unsigned char) + +// +// There are two sorts of brightness calls - ones where we expect the user to raise the brightness themselves +// by doing something (for these we don't allow the panel to go completely dark), and those where the +// laptop software is going to remember the brightness and set it back later (like closing the lid +// where we can go all the way black) +// +// NOTE: some panel interfaces (sony) can't actually go all the way blank anyway so we ignore the blank tag +// +void +laptop_portable::set_brightness(bool blank, int val) // val = 0-255 255 brightest, 0 means dimmest (if !blank it must be still visible), +{ + if (sonyFd >= 0) { + unsigned char v; + if (val < 0) + val = 0; + if (val > 255) + val = 255; + v = val; + (void)::ioctl(sonyFd, SONYPI_IOCSBRT, &v); + return; + } + if (has_toshiba_brightness) { + char tmp[20]; + + if (val < 0) + val = 0; + if (val > 255) + val = 255; + val >>= 5; + if (val == 0 && !blank) + val = 1; + snprintf(tmp, sizeof(tmp), "%d", val&7); + ::invoke_acpi_helper("--toshibalcd", tmp, 0); + return; + } + // INSERT HERE +} + +int +laptop_portable::get_brightness() // return a val 0-255, or -1 if you can't +{ + if (sonyFd >= 0) + return(-1); // sonypi doesn't seem to return this reliably + + // INSERT HERE + return(-1); // means can't extract it +} + +#define MAP_SIZE 20 +static int acpi_performance_map[MAP_SIZE]; // hidden acpi state map +static bool acpi_performance_enable[MAP_SIZE]; +static QStringList performance_list; +static QString acpi_performance_cpu; +static int acpi_throttle_map[MAP_SIZE]; +static bool acpi_throttle_enable[MAP_SIZE]; +static QStringList throttle_list; +static QString acpi_throttle_cpu; + +static bool +get_acpi_list(char p, int *map, const char *dev, QStringList &list, int &index, QString &cpu, bool get_enable, bool *enable_list) +{ + DIR *dfd; + struct dirent *dp; + unsigned int i = 0; + bool result = 0; + + index = 0; + list.clear(); + dfd = opendir("/proc/acpi/processor/"); + if (dfd) { + for (dp = readdir(dfd);dp ;dp = readdir(dfd)) { + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + QString name("/proc/acpi/processor/"); + name += dp->d_name; + name += dev; + if (!(::access(name.latin1(), R_OK|W_OK)==0 && ::acpi_helper_ok(1)) && + !(::access(name.latin1(), R_OK)==0 && ::acpi_helper_ok(0))) + continue; + QFile f(name); + if (f.open(IO_ReadOnly)) { + while (!f.atEnd() && i < MAP_SIZE) { + QString l; + f.readLine(l, 500); + QStringList ll = QStringList::split(':',l,false); + QString tag = ll[0].stripWhiteSpace(); + bool is_this = tag[0] == '*'; + if (is_this) { + if (tag[1] != p) + continue; + tag.remove(0, 2); + } else { + if (tag[0] != p) + continue; + tag.remove(0, 1); + } + bool ok; + int val = tag.toInt(&ok); + if (ok) { + if (!result) + cpu = dp->d_name; + if (is_this) + index = i; + map[i] = val; + list.append(ll[1].stripWhiteSpace()); + result = 1; + enable_list[i] = 1; + i++; + } + } + f.close(); + + // + // get the limit info if asked for + // + if (get_enable) { + name = QString("/proc/acpi/processor/")+dp->d_name+"/limit"; + f.setName(name); + if (f.open(IO_ReadOnly)) { + while (!f.atEnd() && i < MAP_SIZE) { + QString l; + f.readLine(l, 500); + if (l.contains("active limit", false)) { + QRegExp rx(QString("%1(\\d+)").arg(p)); + if (rx.search(l) >= 0) { + bool ok; + int min = rx.cap(1).toInt(&ok); + if (ok) { + for (int j = 0; j < min; j++) + enable_list[j] = 0; + + } + } + break; + } + } + f.close(); + } + } + break; + } + } + closedir(dfd); + } + return(result); +} + +#define CPUFREQ_NONE 0 +#define CPUFREQ_24 1 +#define CPUFREQ_25 2 +#define CPUFREQ_SYSFS 3 + +static QString cpufreq_cpu = ""; +static QString cpufreq_minmax_frequency[2]; + +// get CPUFreq scaling policies via the sysfs interface +static int get_cpufreq_sysfs_state(QStringList &states, int ¤t, const QString cpu) { + QString cur, buffer; + + // read current scaling policy + QFile f("/sys/devices/system/cpu/" + cpu + "/cpufreq/scaling_governor"); + if(!f.open(IO_ReadOnly) || f.atEnd()) + return CPUFREQ_NONE; + f.readLine(buffer, 256); + cur = buffer.stripWhiteSpace(); + f.close(); + + // read available scaling policies + states.clear(); + f.setName("/sys/devices/system/cpu/" + cpu + "/cpufreq/scaling_available_governors"); + if(!f.open(IO_ReadOnly)) + return CPUFREQ_NONE; + int count = 0; + if(!f.atEnd()) { + f.readLine(buffer, 1024); + QStringList l = QStringList::split(' ', buffer.stripWhiteSpace(), false); + for(unsigned int i = 0; i < l.size(); ++i, ++count) { + states.append(l[i].stripWhiteSpace()); + if(states[i] == cur) + current = count; + } + } + f.close(); + + return CPUFREQ_SYSFS; +} + +// get CPUFreq scaling policies via the 2.5 /proc interface +// sample output of cat /proc/cpufreq: +// minimum CPU frequency - maximum CPU frequency - policy +// CPU 0 700000 kHz ( 70 %) - 1000000 kHz (100 %) - powersave +static int get_cpufreq_25_state(QStringList &states, int ¤t) { + current = -1; + states.clear(); + + QFile f("/proc/cpufreq"); + if (f.open(IO_ReadOnly)) { + while (!f.atEnd()) { + QString l; + f.readLine(l, 1024); + QRegExp rx("CPU.*\\d+.*(\\d+).*-.*(\\d+).*-\\W*(\\w*)"); + if (rx.search(l) >= 0) { + cpufreq_minmax_frequency[0] = rx.cap(1); + cpufreq_minmax_frequency[1] = rx.cap(2); + if(rx.cap(3) == "performance") + current = 0; + else + current = 1; + break; + } + } + } + f.close(); + + if(current < 0) + return CPUFREQ_NONE; + + // we don't know all available scaling governors, so use only a minimal set + states.append("performance"); + states.append("powersave"); + return CPUFREQ_25; +} + +// get CPUFreq scaling policies via the 2.4 /proc interface +// The old interface doesn't support policies yet, we only get the min and max frequency, +// so we use these as performance states. +static int get_cpufreq_24_state(QStringList &states, int ¤t, const QString cpu) { + QString buffer, cur; + states.clear(); + + // current frequency + QFile f("/proc/sys/cpu/" + cpu + "/speed"); + if(!f.open(IO_ReadOnly) || f.atEnd()) + return CPUFREQ_NONE; + f.readLine(buffer, 16); + f.close(); + cur = buffer.stripWhiteSpace(); + + // read maximal and minimal frequency + const char* files[] = { "max", "min" }; + for(int i = 0; i <= 1; ++i) { + f.setName("/proc/sys/cpu/" + cpu + "/speed-" + files[i]); + if(!f.open(IO_ReadOnly) || f.atEnd()) + return CPUFREQ_NONE; + f.readLine(buffer, 16); + f.close(); + cpufreq_minmax_frequency[i] = buffer; + unsigned int val = buffer.toUInt() / 1000; + states.append(i18n("%1 MHz").arg(val)); + if(buffer.stripWhiteSpace() == cur) + current = i; + } + return CPUFREQ_24; +} + +// check for CPUFreq support and get a list of all available scaling policies +// this method doesn't support multiple CPU's (neither does get_acpi_list() above), +// but this shouldn't be a problem on notebooks... +static int get_cpufreq_state(bool force, QStringList &states, int ¤t) { + static int known = -1; + + // check wether we already know which interface to use + if(!force && known >= 0) { + switch(known) { + case CPUFREQ_SYSFS: + return get_cpufreq_sysfs_state(states, current, cpufreq_cpu); + break; + case CPUFREQ_25: + return get_cpufreq_25_state(states, current); + break; + case CPUFREQ_24: + return get_cpufreq_24_state(states, current, cpufreq_cpu); + break; + default: + return CPUFREQ_NONE; + } + } + + // look for the CPUFreq sysfs interface first + QDir dir("/sys/devices/system/cpu"); + dir.setFilter(QDir::Dirs); + if(dir.isReadable()) { + for(unsigned int i = 0; !dir[i].isNull(); ++i) { + if(dir[i] == "." || dir[i] == "..") + continue; + cpufreq_cpu = dir[i]; + if(get_cpufreq_sysfs_state(states, current, cpufreq_cpu)) + return (known = CPUFREQ_SYSFS); + } + } + + // try the /proc interface from the 2.5 kernel series next + if(get_cpufreq_25_state(states, current)) + return (known = CPUFREQ_25); + + // last chance: the /proc interface from the 2.4 kernel series + dir.setPath("/proc/sys/cpu"); + dir.setFilter(QDir::Dirs); + if(dir.isReadable()) { + for(unsigned int i = 0; !dir[i].isNull(); ++i) { + if(dir[i] == "." || dir[i] == "..") + continue; + cpufreq_cpu = dir[i]; + if(get_cpufreq_24_state(states, current, cpufreq_cpu)) + return (known = CPUFREQ_24); + } + } + + // no CPUFreq support found + return (known = CPUFREQ_NONE); +} + +bool +laptop_portable::get_system_performance(bool force, int ¤t, QStringList &s, bool *&active) // do something to help get system profiles from places like ACPI +{ + if(!acpi_performance_enabled) + return false; + static int known=0; + static int index=0; + static bool result = 0; + if (known != last_seed || force) { + known = last_seed; + performance_list.clear(); + result = 0; + current = 0; + if (::has_acpi()) { + active = acpi_performance_enable; + result = get_acpi_list('P', acpi_performance_map, "/performance", performance_list, index, acpi_performance_cpu, force, acpi_performance_enable); + } + // CPUFreq support + if (!result && get_cpufreq_state(force, performance_list, index)) { + for(unsigned int i = 0; i < performance_list.size(); ++i) + acpi_performance_enable[i] = true; + active = acpi_performance_enable; + result = true; + } + if (!result) { + // INSERT HERE + } + } + current = index; + s = performance_list; + return(result); +} + +bool +laptop_portable::get_system_throttling(bool force, int ¤t, QStringList &s, bool *&active) // do something to help get system throttling data from places like ACPI +{ + static int known=0; + static int index=0; + static bool result = 0; + if (known != last_seed || force) { + known = last_seed; + throttle_list.clear(); + result = 0; + current = 0; + if (::has_acpi() && acpi_throttle_enabled) { + active = acpi_throttle_enable; + result = get_acpi_list('T', acpi_throttle_map, "/throttling", throttle_list, index, acpi_throttle_cpu, force, acpi_throttle_enable); + } + if (!result) { + // INSERT HERE + } + } + current = index; + s = throttle_list; + return(result); +} + +void +laptop_portable::set_system_performance(QString val) // val = string given by get_system_performance above +{ + if(!acpi_performance_enabled) + return; + int current, result; + if((result = get_acpi_list('P', acpi_performance_map, "/performance", performance_list, current, acpi_performance_cpu, false, acpi_performance_enable))) { + char tmp[20]; + int ind = performance_list.findIndex(val); + if (ind < 0 || ind >= MAP_SIZE || current == ind) + return; + snprintf(tmp, sizeof(tmp), "%d", acpi_performance_map[ind]); + tmp[sizeof(tmp)-1]=0; + ::invoke_acpi_helper("--performance", acpi_performance_cpu.latin1(), tmp); + return; + } + // CPUFreq support + if((result = get_cpufreq_state(false, performance_list, current))) { + if(performance_list[current] == val) + return; + QString tmp; + switch(result) { + case CPUFREQ_SYSFS: + invoke_acpi_helper("--cpufreq-sysfs", cpufreq_cpu.latin1(), val.latin1()); + return; + case CPUFREQ_25: + tmp = cpufreq_minmax_frequency[0] + ":" + cpufreq_minmax_frequency[1] + ":" + val; + invoke_acpi_helper("--cpufreq-25", tmp.latin1(), 0); + return; + case CPUFREQ_24: + int target = performance_list.findIndex(val); + invoke_acpi_helper("--cpufreq-24", cpufreq_cpu.latin1(), cpufreq_minmax_frequency[target].latin1()); + return; + } + } + // INSERT HERE + return; +} + +void +laptop_portable::set_system_throttling(QString val) // val = string given by get_system_throttle above +{ + if (::has_acpi()) { + char tmp[20]; + int ind = throttle_list.findIndex(val); + if (ind < 0 || ind >= MAP_SIZE) + return; + snprintf(tmp, sizeof(tmp), "%d", acpi_throttle_map[ind]); + tmp[sizeof(tmp)-1]=0; + ::invoke_acpi_helper("--throttling", acpi_throttle_cpu.latin1(), tmp); + return; + } + // INSERT HERE + return; +} + +static QString acpi_power_name, acpi_lid_name; // names of paths to ACPI lid states + +static bool +acpi_check_button(const char *prefix, QString &result) +{ + DIR *dfd; + struct dirent *dp; + bool v=0; + + dfd = opendir(prefix); + if (dfd) { + for (dp = readdir(dfd);dp ;dp = readdir(dfd)) { + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + QString name(prefix); + name += "/"; + name += dp->d_name; + name += "/state"; + if (::access(name.latin1(), R_OK)!=0) + continue; + QFile f(name); + if (f.open(IO_ReadOnly)) { + while (!f.atEnd()) { + QString l; + f.readLine(l, 500); + if (l.contains("state:")) { + result = name; + v = 1; + break; + } + } + f.close(); + if (v) + break; + } + } + closedir(dfd); + } + return(v); +} + +bool +laptop_portable::has_button(LaptopButton l) // true if we have support for a particular button +{ + static int known[2]={0,0}; + static bool result[2] = {0,0}; + int type = (l==LidButton?0:1); + if (known[type] != last_seed) { + result[type] = 0; + known[type] = last_seed; + if (::has_acpi()) { + switch (l) { + case LidButton: + result[type] = ::acpi_check_button("/proc/acpi/button/lid", acpi_lid_name); + break; + case PowerButton: + result[type] = ::acpi_check_button("/proc/acpi/button/power", acpi_power_name); + break; + default: + break; + } + } + if (!result[type] && ::has_ibm() && l == LidButton) + result[type] = 1; + if (!result[type]) { + // INSERT HERE + } + } + return(result[type]); +} + +bool +laptop_portable::get_button(LaptopButton l) // true if a button is pressed +{ + if (::has_acpi()) { + QString name; + switch (l) { + case LidButton: + name = acpi_lid_name; + break; + case PowerButton: + name = acpi_power_name; + break; + default: + break; + } + if (!name.isEmpty()) { + QFile f(name); + if (f.open(IO_ReadOnly)) { + while (!f.atEnd()) { + QString l; + f.readLine(l, 500); + QStringList ll = QStringList::split(':',l,false); + if (ll[0].stripWhiteSpace() == "state") { + if (ll[1].stripWhiteSpace() == "open") { + f.close(); + return(0); + } + if (ll[1].stripWhiteSpace() == "closed") { + f.close(); + return(1); + } + break; + } + } + f.close(); + } + + } + } + if (::has_ibm() && l == LidButton) { + smapidev_sensorinfo_t t; + if (smapidev_GetSensorInfo(ibm_fd, &t) == 0) + return(t.fLidClosed != 0); + } + // INSERT HERE + return(0); +} + +#elif defined(__FreeBSD__) && HAVE_MACHINE_APM_BIOS_H + +/* +** This is the FreeBSD-specific code. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define APMDEV "/dev/apm" + +// FreeBSD support by yours truly. Yay. +// Actually this code was "adapted" from apm(8) from +// FreeBSD's collection of tools. The original apm program +// was pieced together by Tatsumi Hosokawa in 1994 + +// +// returns 1 if we support power management +// + +#include +using namespace std; + +// +// something changed maybe we need to check out environment again +// +void +laptop_portable::power_management_restart() +{ + // INSERT HERE +} + +int +laptop_portable::has_power_management() +{ + int ret, fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) { + return 0; + } + + struct apm_info info; + ret=ioctl(fd, APMIO_GETINFO, &info); + ::close(fd); + + if (ret == -1) { + return 0; + } + + return info.ai_status; +} +// +// returns 1 if the BIOS returns the time left in the battery rather than a % of full +// +int laptop_portable::has_battery_time() +{ + int ret, fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + return 0; + + struct apm_info info; + ret=ioctl(fd, APMIO_GETINFO, &info); + ::close(fd); + + if (ret == -1) + return 0; + + return (info.ai_batt_time != 0xffff); +} + +// +// returns 1 if we can perform a change-to-suspend-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_suspend() +{ + int ret, fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + return 0; + + struct apm_info info; + ret=ioctl(fd, APMIO_GETINFO, &info); + ::close(fd); + + if (ret == -1) + return 0; + + return (info.ai_capabilities & 0x02); +} +// +// returns 1 if we can perform a change-to-standby-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_standby() +{ + int ret, fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + return 0; + + struct apm_info info; + ret=ioctl(fd, APMIO_GETINFO, &info); + ::close(fd); + + if (ret == -1) + return 0; + + return (info.ai_capabilities & 0x01); +} +// +// returns 1 if we can perform a change-to-hibernate-mode for a user +// (has_power_management() has already returned 1) [hibernate is the save-to-disk mode +// not supported by linux - different laptops have their own - the first here is for +// a ThinkPad] +// +int laptop_portable::has_hibernation() +{ + if (::access(PATH_TPCTL, X_OK)==0) + return(1); + return(0); +} + +// +// explain to the user what they need to do if has_power_management() returned 0 +// to get any software they lack +// +KActiveLabel *laptop_portable::no_power_management_explanation(QWidget *parent) +{ + int fd; + KActiveLabel *explain; + + fd = ::open(APMDEV, O_RDWR); + if (fd == -1) { + switch (errno) { + case ENOENT: + explain = new KActiveLabel(i18n("There is no /dev/apm file on this system. Please review the FreeBSD handbook on how to create a device node for the APM device driver (man 4 apm)."), parent); + break; + case EACCES: + explain = new KActiveLabel(i18n("Your system has the proper device node for APM support, however you cannot access it. If you are logged in as root right now, you have a problem, otherwise contact your local sysadmin and ask for read/write access to /dev/apm."), parent); + break; + case ENXIO: + explain = new KActiveLabel(i18n("Your kernel lacks support for Advanced Power Management."), parent); + break; + break; + default: + explain = new KActiveLabel(i18n("There was a generic error while opening /dev/apm."), parent); + break; + } + } else { + close(fd); + explain = new KActiveLabel(i18n("APM has most likely been disabled."), parent); + } + + return(explain); +} + +// +// explain to the user what they need to do to get suspend/resume to work from user mode +// +QLabel *laptop_portable::how_to_do_suspend_resume(QWidget *parent) +{ + QLabel* note = new QLabel(" ", parent); + return(note); +} + + +// +// pcmcia support - this will be replaced by better - pcmcia support being worked on by +// others +// +QLabel *laptop_portable::pcmcia_info(int x, QWidget *parent) +{ + if (x == 0) + return(new QLabel(i18n("No PCMCIA controller detected"), parent)); + return(new QLabel(i18n(""), parent)); +} +// +// puts us into standby mode +// +void laptop_portable::invoke_standby() +{ + int fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + return; + + ioctl(fd, APMIO_STANDBY, NULL); + ::close(fd); + + return; +} + +// +// puts us into suspend mode +// +void laptop_portable::invoke_suspend() +{ + int fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + return; + + ioctl(fd, APMIO_SUSPEND, NULL); + ::close(fd); + + return; +} +// +// puts us into hibernate mode +// +void laptop_portable::invoke_hibernation() +{ + KProcess thisProc; + + if (::access(PATH_TPCTL, X_OK)==0) { + thisProc << PATH_TPCTL; + thisProc << "---hibernate"; + thisProc.start(KProcess::Block); + return; + } +} + +// +//ACPI specific - chances are you don't need to implement this one +// +void +laptop_portable::acpi_set_mask(bool, bool, bool, bool, bool ) +{ + // INSERT HERE +} + +int laptop_portable::has_acpi(int) +{ + // INSERT HERE + return (0); +} + +int laptop_portable::has_apm(int type) +{ + if (type == 1) // implement me .... this is the hook that pops up the panel for making /usr/sbin/apm setuid + return(0); // or in this case you could make an acpi_helper type app freebsd + return (1); +} + +void +laptop_portable::apm_set_mask(bool , bool ) +{ +} + + +// +// adds extra widgets to the battery panel +// +void +laptop_portable::extra_config(QWidget * /*parent*/, KConfig * /*config*/, QVBoxLayout * /*layout*/) +{ + // INSERT HERE +} + + + +// +// return current battery state +// +struct power_result laptop_portable::poll_battery_state() +{ + struct power_result p; + int ret; + + int fd = ::open(APMDEV, O_RDWR); + + if (fd == -1) + goto bad; + + struct apm_info info; + ret=ioctl(fd, APMIO_GETINFO, &info); + ::close(fd); + + if (ret == -1) + goto bad; + + p.powered = info.ai_acline; + p.percentage = (info.ai_batt_life==255 ? 100 : info.ai_batt_life); + p.time = (info.ai_batt_time != 0xffff ? info.ai_batt_time/60 : -1); + return(p); + +bad: + p.powered = 1; + p.percentage = 100; + p.time = 0; + return(p); +} + +// +// return the system load +// + +bool laptop_portable::has_lav() { return 0; } + +float laptop_portable::get_load_average() +{ + // INSERT HERE + return(-1); +} + +int laptop_portable::has_cpufreq() { + // INSERT HERE + return 0; +} + +QString laptop_portable::cpu_frequency() { + // INSERT HERE + return ""; +} + +int +laptop_portable::has_brightness() +{ + // INSERT HERE + return 0; +} + +void +laptop_portable::set_brightness(bool /*blank*/, int /*val*/) // val = 0-255 255 brightest, 0 means dimmest (if !blank it must be still visible), +{ + // INSERT HERE +} + +int +laptop_portable::get_brightness() +{ + // INSERT HERE + return(-1); // means can't extract it +} + +bool +laptop_portable::get_system_performance(bool, int ¤t, QStringList &s, bool *&) // do something to help get system profiles from places like ACPI +{ + // INSERT HERE + current = 0; + s.clear(); + return(0); // if no profiles are available +} + +bool +laptop_portable::get_system_throttling(bool, int ¤t, QStringList &s, bool *&) // do something to help get system throttling data from places like ACPI +{ + // INSERT HERE + current = 0; + s.clear(); + return(0); +} + +void +laptop_portable::set_system_performance(QString) +{ + // INSERT HERE +} + +void +laptop_portable::set_system_throttling(QString) +{ + // INSERT HERE +} + +bool +laptop_portable::has_button(LaptopButton) // true if we have support for a particular button +{ + // INSERT HERE + return(0); +} + +bool +laptop_portable::get_button(LaptopButton) // true if a button is pressed +{ + // INSERT HERE + return(0); +} + +void +laptop_portable::get_battery_status(int &num_batteries, QStringList &names, QStringList &state, QStringList &values) // get multiple battery status +{ + struct power_result r; + + if (!has_power_management()) { + num_batteries = 0; + names.clear(); + state.clear(); + values.clear(); + return; + } + + // INSERT HERE + + num_batteries = 1; + r = poll_battery_state(); + names.append("BAT1"); + state.append("yes"); + QString s; + s.setNum(r.percentage); + values.append(s); +} + +bool +laptop_portable::has_software_suspend(int /*type*/) +{ + return false; // (::has_software_suspend(type)); +} + +void +laptop_portable::software_suspend_set_mask(bool /*hibernate*/) +{ + // software_suspend_is_preferred = hibernate; +} + + +#elif defined(__NetBSD_APM__) + +#include +#include +#include +#include +#include +#include +#include +#include + +// +// klaptopdeamon interface to NetBSD 1.5 apm. +// Scott Presnell, srp@zgi.com, srp@tworoads.net +// Fri Jun 29 17:21:25 PDT 2001 +// Tested on Dell I4K running NetBSD 1.5R +// +#define APMDEV "/dev/apm" + +// +// Check for apm in kernel by talking to /dev/apm +// (opening read only is allowed by any process). +// returns 1 if we support power management +// +int +laptop_portable::has_power_management() +{ + int ret, fd = ::open(APMDEV, O_RDONLY); + + if (fd == -1) { + return 0; + } + + struct apm_power_info info; + ret=ioctl(fd, APM_IOC_GETPOWER, &info); + ::close(fd); + + if (ret == -1) { + return 0; + } + + return 1; +} + +void +laptop_portable::power_management_restart() +{ + // INSERT HERE +} + +// +// returns 1 if the BIOS returns the time left in the battery rather than a % of full +// +int laptop_portable::has_battery_time() +{ + int ret, fd = ::open(APMDEV, O_RDONLY); + + if (fd == -1) + return 0; + + struct apm_power_info info; + ret=ioctl(fd, APM_IOC_GETPOWER, &info); + ::close(fd); + + if (ret == -1) + return 0; + + return (info.minutes_left != 0xffff); +} + +// +// returns 1 if we can perform a change-to-suspend-mode operation for the user +// (ust check to see if we have the binary) +// (has_power_management() has already returned 1) +// +int laptop_portable::has_suspend() +{ + + struct stat s; + if (stat("/usr/sbin/apm", &s)) + return(0); + return(1); +} + +// +// returns 1 if we can perform a change-to-standby-mode operation for the user +// (just check to see if we have the binary) +// (has_power_management() has already returned 1) +// +int laptop_portable::has_standby() +{ + + struct stat s; + if (stat("/usr/sbin/apm", &s)) + return(0); + return(1); +} + +// +// returns 1 if we can perform a change-to-hibernate-mode for a user +// (has_power_management() has already returned 1) [hibernate is the save-to-disk mode +// not supported by linux - different laptops have their own - the first here is for +// a ThinkPad] +// No support in NetBSD at this time. +// +int laptop_portable::has_hibernation() +{ + // INSERT HERE + return(0); +} + +// +// explain to the user what they need to do if has_power_management() returned 0 +// to get any software they lack +// +KActiveLabel *laptop_portable::no_power_management_explanation(QWidget *parent) +{ + int fd; + KActiveLabel *explain; + + fd = ::open(APMDEV, O_RDONLY); + if (fd == -1) { + switch (errno) { + case ENOENT: + explain = new KActiveLabel(i18n("There is no /dev/apm file on this system. Please review the NetBSD documentation on how to create a device node for the APM device driver (man 4 apm)."), parent); + break; + case EACCES: + explain = new KActiveLabel(i18n("Your system has the proper device node for APM support, however you cannot access it. If you have APM compiled into the kernel this should not happen."), parent); + break; + case ENXIO: + explain = new KActiveLabel(i18n("Your kernel lacks support for Advanced Power Management."), parent); + break; + break; + default: + explain = new KActiveLabel(i18n("There was a generic error while opening /dev/apm."), parent); + break; + } + } else { + close(fd); + explain = new KActiveLabel(i18n("APM has most likely been disabled."), parent); + } + + return(explain); +} + +// +// explain to the user what they need to do to get suspend/resume to work from user mode +// +QLabel *laptop_portable::how_to_do_suspend_resume(QWidget *parent) +{ + // INSERT HERE + QLabel* note = new QLabel(" ", parent); + return(note); +} + +// +// pcmcia support - this will be replaced by better - pcmcia support being worked on by +// others +// +QLabel *laptop_portable::pcmcia_info(int x, QWidget *parent) +{ + // INSERT HERE + if (x == 0) + return(new QLabel(i18n("No PCMCIA controller detected"), parent)); + return(new QLabel(i18n(""), parent)); +} + +// +// puts us into standby mode +// Use apm rather than ioctls in case they are running apmd +// (as they should be). +// +void laptop_portable::invoke_standby() +{ + KProcess proc; + proc << "/usr/sbin/apm"; + proc << "-S"; + proc.start(KProcess::Block); // helper runs fast and we want to see the result +} + +// +// puts us into suspend mode +// Use apm rather than ioctls in case they are running apmd +// (as they should be). +// +void laptop_portable::invoke_suspend() +{ + KProcess proc; + proc << "/usr/sbin/apm"; + proc << "-z"; + proc.start(KProcess::Block); // helper runs fast and we want to see the result +} + +// +// puts us into hibernate mode +// No hibernate mode for NetBSD. +// +void laptop_portable::invoke_hibernation() +{ + // INSERT HERE + return; +} + +// +//ACPI specific - chances are you don't need to implement this one +// +void +laptop_portable::acpi_set_mask(bool, bool, bool, bool, bool ) +{ + // INSERT HERE +} + +int laptop_portable::has_acpi(int) +{ + // INSERT HERE + return (0); +} + +int laptop_portable::has_apm(int type) +{ + if (type == 1) // implement me .... this is the hook that pops up the panel for making /usr/sbin/apm setuid + return(0); + return (1); +} + +void +laptop_portable::apm_set_mask(bool , bool ) +{ +} + + +// +// return current battery state +// +struct power_result laptop_portable::poll_battery_state() +{ + struct power_result p; + int ret; + + int fd = ::open(APMDEV, O_RDONLY); + + if (fd == -1) + goto bad; + + struct apm_power_info info; + ret=ioctl(fd, APM_IOC_GETPOWER, &info); + ::close(fd); + + if (ret == -1) + goto bad; + + p.powered = (info.ac_state == APM_AC_ON); + p.percentage = (info.battery_life==255 ? 100 : info.battery_life); + p.time = (info.minutes_left != 0xffff ? info.minutes_left : -1); + return(p); + +bad: + p.powered = 1; + p.percentage = 100; + p.time = 0; + return(p); +} + +// +// return the system load +// + +bool laptop_portable::has_lav() { return 0; } + +float laptop_portable::get_load_average() +{ + // INSERT HERE + return(-1); +} + + +int laptop_portable::has_cpufreq() { + // INSERT HERE + return 0; +} + +QString laptop_portable::cpu_frequency() { + // INSERT HERE + return ""; +} + +int +laptop_portable::has_brightness() +{ + // INSERT HERE + return 0; +} + +void +laptop_portable::set_brightness(bool blank, int val) // val = 0-255 255 brightest, 0 means dimmest (if !blank it must be still visible), +{ + // INSERT HERE +} + +int +laptop_portable::get_brightness() +{ + // INSERT HERE + return(-1); // means can't extract it +} + +bool +laptop_portable::get_system_throttling(bool, int ¤t, QStringList &s) // do something to help get system throttling data from places like ACPI +{ + // INSERT HERE + current = 0; + s.clear(); + return(0); +} + +void +laptop_portable::set_system_performance(QString) +{ + // INSERT HERE +} + +void +laptop_portable::set_system_throttling(QString) +{ + // INSERT HERE +} + +bool +laptop_portable::has_button(LaptopButton) // true if we have support for a particular button +{ + // INSERT HERE + return(0); +} + +bool +laptop_portable::get_button(LaptopButton) // true if a button is pressed +{ + // INSERT HERE + return(0); +} + +void +laptop_portable::get_battery_status(int &num_batteries, QStringList &names, QStringList &state, QStringList &values) // get multiple battery status +{ + struct power_result r; + + if (!has_power_management()) { + num_batteries = 0; + names.clear(); + state.clear(); + values.clear(); + return; + } + + // INSERT HERE + + num_batteries = 1; + r = poll_battery_state(); + names.append("BAT1"); + state.append("yes"); + QString s; + s.setNum(r.percentage); + values.append(s); +} + +#else + +/* +** This is utterly generic code. +*/ + +// +// something changed maybe we need to check out environment again +// +void +laptop_portable::power_management_restart() +{ + // INSERT HERE +} + +// +// returns 1 if we support power management +// +int +laptop_portable::has_power_management() +{ + // INSERT HERE + return(0); +} + +// +// returns 1 if the BIOS returns the time left in the battery rather than a % of full +// +int laptop_portable::has_battery_time() +{ + // INSERT HERE + return (0); +} + +// +// returns 1 if we can perform a change-to-suspend-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_suspend() +{ + // INSERT HERE + return(0); +} +// +// returns 1 if we can perform a change-to-standby-mode operation for the user +// (has_power_management() has already returned 1) +// +int laptop_portable::has_standby() +{ + // INSERT HERE + return(0); +} +// +// returns 1 if we can perform a change-to-hibernate-mode for a user +// (has_power_management() has already returned 1) [hibernate is the save-to-disk mode +// not supported by linux] +// +int laptop_portable::has_hibernation() +{ + // INSERT HERE + return(0); +} + +// +// explain to the user what they need to do if has_power_management() returned 0 +// to get any software they lack +// +KActiveLabel *laptop_portable::no_power_management_explanation(QWidget *parent) +{ + KActiveLabel* explain = new KActiveLabel(i18n("Your computer or operating system is not supported by the current version of the\nKDE laptop control panels. If you want help porting these panels to work with it\nplease contact paul@taniwha.com."), parent); + // INSERT HERE + return(explain); +} + +// +// explain to the user what they need to do to get suspend/resume to work from user mode +// +QLabel *laptop_portable::how_to_do_suspend_resume(QWidget *parent) +{ + QLabel* note = new QLabel(" ", parent); + // INSERT HERE + return(note); +} + + +// +// pcmcia support - this will be replaced by better - pcmcia support being worked on by +// others +// +QLabel *laptop_portable::pcmcia_info(int x, QWidget *parent) +{ + // INSERT HERE + if (x == 0) + return(new QLabel(i18n("No PCMCIA controller detected"), parent)); + return(new QLabel(i18n(""), parent)); +} +// +// puts us into standby mode +// +void laptop_portable::invoke_standby() +{ + // INSERT HERE +} + +// +// puts us into suspend mode +// +void laptop_portable::invoke_suspend() +{ + // INSERT HERE +} +// +// puts us into hibernate mode +// +void laptop_portable::invoke_hibernation() +{ + // INSERT HERE +} + +// +//ACPI specific - chances are you don't need to implement this one +// +void +laptop_portable::acpi_set_mask(bool, bool, bool, bool, bool ) +{ + // INSERT HERE +} + +int laptop_portable::has_acpi(int) +{ + // INSERT HERE + return (0); +} + +void +laptop_portable::apm_set_mask(bool, bool) +{ + // INSERT HERE +} + +int laptop_portable::has_apm(int) +{ + // INSERT HERE + return (0); +} + + +// +// adds extra widgets to the battery panel +// +void +laptop_portable::extra_config(QWidget *parent, KConfig *config, QVBoxLayout *layout) +{ + // INSERT HERE +} + +// +// return current battery state +// +struct power_result laptop_portable::poll_battery_state() +{ + struct power_result p; + // INSERT HERE + p.powered = 0; + p.percentage = 0; + p.time = 0; + return(p); +} + +// +// return the system load +// + +bool laptop_portable::has_lav() { return 0; } + +float laptop_portable::get_load_average() +{ + // INSERT HERE + return(-1); +} + +int laptop_portable::has_cpufreq() { + // INSERT HERE + return 0; +} + +QString laptop_portable::cpu_frequency() { + // INSERT HERE + return ""; +} + +int +laptop_portable::has_brightness() +{ + // INSERT HERE + return 0; +} + +void +laptop_portable::set_brightness(bool blank, int val) // val = 0-255 255 brightest, 0 means dimmest (if !blank it must be still visible), +{ + // INSERT HERE +} + +int +laptop_portable::get_brightness() +{ + // INSERT HERE + return(-1); // means can't extract it +} + +bool +laptop_portable::get_system_performance(bool, int ¤t, QStringList &s, bool *&) // do something to help get system profiles from places like ACPI +{ + // INSERT HERE + current = 0; + s.clear(); + return(0); // if no profiles are available +} + +bool +laptop_portable::get_system_throttling(bool, int ¤t, QStringList &s, bool *&) // do something to help get system throttling data from places like ACPI +{ + // INSERT HERE + current = 0; + s.clear(); + return(0); +} + +void +laptop_portable::set_system_performance(QString) +{ + // INSERT HERE +} + +void +laptop_portable::set_system_throttling(QString) +{ + // INSERT HERE +} + +bool +laptop_portable::has_button(LaptopButton) // true if we have support for a particular button +{ + // INSERT HERE + return(0); +} + +bool +laptop_portable::get_button(LaptopButton) // true if a button is pressed +{ + // INSERT HERE + return(0); +} + +void +laptop_portable::get_battery_status(int &num_batteries, QStringList &names, QStringList &state, QStringList &values) // get multiple battery status +{ + struct power_result r; + + if (!has_power_management()) { + num_batteries = 0; + names.clear(); + state.clear(); + values.clear(); + return; + } + + // INSERT HERE + + num_batteries = 1; + r = poll_battery_state(); + names.append("BAT1"); + state.append("yes"); + QString s; + s.setNum(r.percentage); + values.append(s); +} + +bool +laptop_portable::has_software_suspend(int type) +{ + return false; // (::has_software_suspend(type)); +} + +void +laptop_portable::software_suspend_set_mask(bool hibernate) +{ + // software_suspend_is_preferred = hibernate; +} +#endif diff --git a/klaptopdaemon/portable.h b/klaptopdaemon/portable.h new file mode 100644 index 0000000..62d325c --- /dev/null +++ b/klaptopdaemon/portable.h @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include + +#ifndef PORTABLE_H +#define PORTABLE_H +/* + * Copyright (c) 2002 Paul Campbell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +struct power_result { + int powered ; // true if we're plugged into the wall + int percentage; // value 0-100 percentage of battery left + int time; // time in minutes left - -1 if this is not supported by the BIOS +}; + + +// ATTENTION: if you change something in here, please update ALL of the +// ported sections in the implementation file! + +class KDE_EXPORT laptop_portable { +public: + static void power_management_restart(); // reset internal state + static int has_power_management(); // returns 1 if this computer has power management + static int has_battery_time(); // returns 1 if this give BIOS battery time info + + /** + * Returns 1 if this computer can perform a suspend, i.e. supports some kind + * of suspend-to-ram energy saving mode (average wakeup time and energy + * saving). + */ + static int has_suspend(); + + /** + * Returns 1 if this computer can perform a standby, i.e. supports an energy + * saving mode with a very fast wakeup time (neither suspend-to-disk nor + * suspend-to-ram). + */ + static int has_standby(); + + /** + * Returns 1 if this computer can perform hibernatation, i.e. supports some + * kind of suspend-to-disk energy saving mode (highest energy saving, + * slowest wakeup time). + */ + static int has_hibernation(); + + static int has_apm(int); // returns 1 if this computer has linux-style apm of some particular type + static int has_apm() { return has_apm(0); } // returns 1 if this computer has linux-style apm + static int has_acpi(int); // returns 1 if this computer has linux-style acpi of some particular type + static int has_acpi() { return has_acpi(0); } // returns 1 if this computer has linux-style acpi + static bool has_software_suspend(int type); // // returns 1 if the system has software suspend available + static bool has_software_suspend() { return has_software_suspend(0); } + static int has_cpufreq(); // returns 1 if this computer can scale the cpu frequency + static int has_brightness(); // returns 1 if this computer can set tyhe back panel brightness + static void set_brightness(bool blank, int val); // val = 0-255 255 brightest, 0 means dimmest (if !blank it must be still visible), + static int get_brightness(); // returns 0-255 brightness, -1 if you can't + static QString cpu_frequency(); // Returns the cpu freq. + static KActiveLabel *no_power_management_explanation(QWidget *parent); + static QLabel *how_to_do_suspend_resume(QWidget *parent); + static QLabel *pcmcia_info(int x, QWidget *parent); + + /** + * Put this computer into standby mode. + * @see has_standby() + */ + static void invoke_standby(); + + /** + * Put this computer into suspend mode. + * @see has_suspend() + */ + static void invoke_suspend(); + + /** + * Put this computer into hibernatation mode. + * @see has_hibernation() + */ + static void invoke_hibernation(); + + static struct power_result poll_battery_state(); + static void get_battery_status(int &num_batteries, QStringList &names, QStringList &state, QStringList &values); // get multiple battery status + static bool has_lav(); // true if the following returns a valid value + static float get_load_average(); // current short term load average + static void extra_config(QWidget *parent, KConfig *config, QVBoxLayout *layout); + static void acpi_set_mask(bool standby, bool suspend, bool hibernate, bool perf, bool throttle); + static void apm_set_mask(bool standby, bool suspend); + static void software_suspend_set_mask(bool hibernate); + + /** + * Get a list of available performance profiles. + * @param force - Force re-evaluation or use cached values. + * @param current - Index of the currently active profile. + * @param s - A list of available profiles. + * @param active - Marks profiles as enabled or disabled (used e.g. for ACPI + * limits). + * @return True if this system provides performance profiles. + */ + static bool get_system_performance(bool force, int ¤t, QStringList &s, bool *&active); + + /** + * Set performance profile. + * @param val - Name of the performance profile as provided by + * get_system_performance(). + */ + static void set_system_performance(QString val); + + /** + * Get a list of available throttling levels. + * @param force - Force re-evaluation or use cached values. + * @param current - Index of the currently active throttling level. + * @param s - A list of available throttling levels. + * @param active - Marks throttling labels as enabled or disabled (used e.g. + * for ACPI limits). + * @return True if this system provides throttling levels. + */ + static bool get_system_throttling(bool force, int ¤t, QStringList &s, bool *&active); + + /** + * Set throttling level. + * @param val - Name of the throttling level as provided by + * get_system_throttling(). + */ + static void set_system_throttling(QString val); + + enum LaptopButton {LidButton=0, PowerButton}; + static bool has_button(LaptopButton p); // true if we have support for a particular button + static bool get_button(LaptopButton p); // true if a button is pressed +}; + +#endif diff --git a/klaptopdaemon/power.cpp b/klaptopdaemon/power.cpp new file mode 100644 index 0000000..2477cee --- /dev/null +++ b/klaptopdaemon/power.cpp @@ -0,0 +1,587 @@ +/* + * power.cpp + * + * Copyright (c) 1999 Paul Campbell + * Copyright (c) 2002 Marc Mutz + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "power.h" +#include "portable.h" +#include "version.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +extern void wake_laptop_daemon(); + +PowerConfig::PowerConfig (QWidget * parent, const char *name) + : KCModule(parent, name), + nopowerBox(0), + nopowerStandby(0), + nopowerSuspend(0), + nopowerOff(0), + nopowerHibernate(0), + nopowerBrightness(0), + nopowerValBrightness(0), + nopowerThrottle(0), + nopowerValThrottle(0), + nopowerPerformance(0), + nopowerValPerformance(0), + + powerBox(0), + powerStandby(0), + powerSuspend(0), + powerOff(0), + powerHibernate(0), + powerBrightness(0), + powerValBrightness(0), + powerThrottle(0), + powerValThrottle(0), + powerPerformance(0), + powerValPerformance(0), + + + noeditwait(0), + editwait(0), + enablelav(0), + noenablelav(0), + noeditlav(0), + editlav(0) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + apm = laptop_portable::has_power_management(); + config = new KConfig("kcmlaptoprc"); + int can_brightness = laptop_portable::has_brightness(); + QStringList throttle_list; + int current_throttle; + bool *active_list; + bool has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + QStringList performance_list; + int current_performance; + bool has_performance = laptop_portable::get_system_performance(0, current_performance, performance_list, active_list); + + if (!apm && !can_brightness && !has_throttle && !has_performance) { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + + KActiveLabel* explain = laptop_portable::no_power_management_explanation(this); + top_layout->addWidget(explain); + + top_layout->addStretch(1); + } else { + int can_standby = laptop_portable::has_standby(); + int can_suspend = laptop_portable::has_suspend(); + int can_hibernate = laptop_portable::has_hibernation(); + + if (!can_standby && !can_suspend && !can_hibernate && !can_brightness && !has_throttle && !has_performance) + apm = 0; + if (!apm) { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + + QLabel* explain = laptop_portable::how_to_do_suspend_resume(this); + top_layout->addWidget(explain); + + top_layout->addStretch(1); + } else { + QVBoxLayout *top_layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint()); + QHBoxLayout *hlay = new QHBoxLayout( top_layout ); + + nopowerBox = new QVButtonGroup(i18n("Not Powered"), this); + QToolTip::add( nopowerBox, i18n( "Options in this box apply when the laptop is unplugged from the wall and has been idle for a while" ) ); + nopowerBox->layout()->setSpacing( KDialog::spacingHint() ); + hlay->addWidget( nopowerBox ); + + if (can_standby) { + nopowerStandby = new QRadioButton(i18n("Standb&y"), nopowerBox); + QToolTip::add( nopowerStandby, i18n( "Causes the laptop to change to a standby temporary-low power state" ) ); + } + if (can_suspend) { + nopowerSuspend = new QRadioButton(i18n("&Suspend"), nopowerBox); + QToolTip::add( nopowerSuspend, i18n( "Causes the laptop to change to a suspend 'save-to-ram' state" ) ); + } + if (can_hibernate) { + nopowerHibernate = new QRadioButton(i18n("H&ibernate"), nopowerBox); + QToolTip::add( nopowerHibernate, i18n( "Causes the laptop to change to a hibernate 'save-to-disk' state" ) ); + } + if (can_suspend||can_standby||can_hibernate) + nopowerOff = new QRadioButton(i18n("None"), nopowerBox); + if (can_brightness) { + nopowerBrightness = new QCheckBox(i18n("Brightness"), nopowerBox); + QToolTip::add( nopowerBrightness, i18n( "Enables changing the laptop's back panel brightness" ) ); + QWidget *wp = new QWidget(nopowerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + xl->addWidget(new QLabel("-", wp)); + nopowerValBrightness = new QSlider(0, 255, 16, 255, Qt::Horizontal, wp); + QToolTip::add( nopowerValBrightness, i18n( "How bright to change the back panel" ) ); + nopowerValBrightness->setEnabled(0); + connect(nopowerValBrightness, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(nopowerBrightness, SIGNAL(toggled(bool)), nopowerValBrightness, SLOT(setEnabled(bool))); + xl->addWidget(nopowerValBrightness); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } + if (has_performance) { + nopowerPerformance = new QCheckBox(i18n("System performance"), nopowerBox); + QToolTip::add( nopowerPerformance, i18n( "Enables changing the laptop's performance profile" ) ); + + QWidget *wp = new QWidget(nopowerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + nopowerValPerformance = new KComboBox(0, wp); + QToolTip::add( nopowerValPerformance, i18n( "Which profile to change it to" ) ); + nopowerValPerformance->insertStringList(performance_list); + nopowerValPerformance->setEnabled(0); + connect(nopowerValPerformance, SIGNAL(activated(int)), this, SLOT(changed())); + connect(nopowerPerformance, SIGNAL(toggled(bool)), nopowerValPerformance, SLOT(setEnabled(bool))); + xl->addWidget(nopowerValPerformance); + xl->addStretch(1); + } + if (has_throttle) { + nopowerThrottle = new QCheckBox(i18n("CPU throttle"), nopowerBox); + QToolTip::add( nopowerThrottle, i18n( "Enables throttling the laptop's CPU" ) ); + + QWidget *wp = new QWidget(nopowerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + nopowerValThrottle = new KComboBox(0, wp); + QToolTip::add( nopowerValThrottle, i18n( "How much to throttle the laptop's CPU" ) ); + nopowerValThrottle->insertStringList(throttle_list); + nopowerValThrottle->setEnabled(0); + connect(nopowerValThrottle, SIGNAL(activated(int)), this, SLOT(changed())); + connect(nopowerThrottle, SIGNAL(toggled(bool)), nopowerValThrottle, SLOT(setEnabled(bool))); + xl->addWidget(nopowerValThrottle); + xl->addStretch(1); + } + + + connect(nopowerBox, SIGNAL(clicked(int)), this, SLOT(changed())); + + bool can_lav = laptop_portable::has_lav(); + QHBox *hbox; + if (can_lav) { + hbox = new QHBox( nopowerBox ); + noenablelav = new QCheckBox(i18n("Don't act if LAV is >"), hbox); + connect(noenablelav, SIGNAL(clicked()), this, SLOT(changed())); + noeditlav = new KDoubleSpinBox(0.0, 10.0, 0.0, 0.1, 1, hbox); + QToolTip::add( noeditlav, i18n( "If enabled and the system load average is greater than this value none of the above options will be applied" ) ); + connect(noeditlav, SIGNAL(valueChanged(double)), this, SLOT(changed())); + connect(noenablelav, SIGNAL(toggled(bool)), noeditlav, SLOT(setEnabled(bool))); + } + + hbox = new QHBox( nopowerBox ); + QLabel* noedlabel = new QLabel(i18n("&Wait for:"), hbox); + noeditwait = new QSpinBox( 1, 60*24 /*1 day*/, 1, hbox ); + QToolTip::add( noeditwait, i18n( "How long the computer has to be idle before these values take effect" ) ); + noeditwait->setSuffix( i18n("keep short, unit in spinbox", "min") ); + noedlabel->setBuddy( noeditwait ); + hbox->setStretchFactor( noeditwait, 1 ); + connect( noeditwait, SIGNAL(valueChanged(int)), this, SLOT(changed())); + + + /////////////////////////////////////////////////////////////// + + + powerBox = new QVButtonGroup(i18n("Powered"), this); + powerBox->layout()->setSpacing( KDialog::spacingHint() ); + QToolTip::add( powerBox, i18n( "Options in this box apply when the laptop is plugged into the wall and has been idle for a while" ) ); + hlay->addWidget( powerBox ); + + if (can_standby) { + powerStandby = new QRadioButton(i18n("Sta&ndby"), powerBox); + QToolTip::add( powerStandby, i18n( "Causes the laptop to change to a standby temporary-low power state" ) ); + } + if (can_suspend) { + powerSuspend = new QRadioButton(i18n("S&uspend"), powerBox); + QToolTip::add( powerSuspend, i18n( "Causes the laptop to change to a suspend 'save-to-ram' state" ) ); + } + if (can_hibernate) { + powerHibernate = new QRadioButton(i18n("Hi&bernate"), powerBox); + QToolTip::add( powerHibernate, i18n( "Causes the laptop to change to a hibernate 'save-to-disk' state" ) ); + } + if (can_suspend||can_standby||can_hibernate) + powerOff = new QRadioButton(i18n("None"), powerBox); + if (can_brightness) { + powerBrightness = new QCheckBox(i18n("Brightness"), powerBox); + QToolTip::add( powerBrightness, i18n( "Enables changing the laptop's back panel brightness" ) ); + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + xl->addWidget(new QLabel("-", wp)); + powerValBrightness = new QSlider(0, 255, 16, 255, Qt::Horizontal, wp); + QToolTip::add( powerValBrightness, i18n( "How bright to change the back panel" ) ); + powerValBrightness->setEnabled(0); + connect(powerValBrightness, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(powerBrightness, SIGNAL(toggled(bool)), powerValBrightness, SLOT(setEnabled(bool))); + xl->addWidget(powerValBrightness); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } + if (has_performance) { + powerPerformance = new QCheckBox(i18n("System performance"), powerBox); + QToolTip::add( powerPerformance, i18n( "Enables changing the laptop's performance profile" ) ); + + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + powerValPerformance = new KComboBox(0, wp); + QToolTip::add( powerValPerformance, i18n( "Which profile to change it to" ) ); + powerValPerformance->insertStringList(performance_list); + powerValPerformance->setEnabled(0); + connect(powerValPerformance, SIGNAL(activated(int)), this, SLOT(changed())); + connect(powerPerformance, SIGNAL(toggled(bool)), powerValPerformance, SLOT(setEnabled(bool))); + xl->addWidget(powerValPerformance); + xl->addStretch(1); + } + if (has_throttle) { + powerThrottle = new QCheckBox(i18n("CPU throttle"), powerBox); + QToolTip::add( powerThrottle, i18n( "Enables throttling the laptop's CPU" ) ); + + QWidget *wp = new QWidget(powerBox); + QHBoxLayout *xl = new QHBoxLayout( wp); + powerValThrottle = new KComboBox(0, wp); + QToolTip::add( powerValThrottle, i18n( "How much to throttle the laptop's CPU" ) ); + powerValThrottle->insertStringList(throttle_list); + powerValThrottle->setEnabled(0); + connect(powerValThrottle, SIGNAL(activated(int)), this, SLOT(changed())); + connect(powerThrottle, SIGNAL(toggled(bool)), powerValThrottle, SLOT(setEnabled(bool))); + xl->addWidget(powerValThrottle); + xl->addStretch(1); + } + + connect(powerBox, SIGNAL(clicked(int)), this, SLOT(changed())); + + if (can_lav) { + hbox = new QHBox( powerBox ); + enablelav = new QCheckBox(i18n("Don't act if LAV is >"), hbox); + connect( enablelav, SIGNAL(clicked()), this, SLOT(changed())); + editlav = new KDoubleSpinBox(0.0, 10.0, 0.0, 0.1, 1, hbox); + QToolTip::add( editlav, i18n( "If enabled and the system load average is greater than this value none of the above options will be applied" ) ); + connect( editlav, SIGNAL(valueChanged(double)), this, SLOT(changed())); + connect( enablelav, SIGNAL(toggled(bool)), editlav, SLOT(setEnabled(bool)) ); + } + + hbox = new QHBox( powerBox ); + QLabel* edlabel = new QLabel(i18n("Wai&t for:"), hbox); + editwait = new QSpinBox( 1, 60*24 /*1 day*/, 1, hbox ); + QToolTip::add( editwait, i18n( "How long the computer has to be idle before these values take effect" ) ); + editwait->setSuffix( i18n("keep short, unit in spinbox", "min") ); + edlabel->setBuddy( editwait ); + hbox->setStretchFactor( editwait, 1 ); + connect( editwait, SIGNAL(valueChanged(int)), this, SLOT(changed())); + + hlay->addStretch(1); + + QLabel* explain = new QLabel(i18n("This panel configures the behavior of the automatic power-down feature - " + "it works as a sort of extreme screen saver. You can configure different " + "timeouts and types of behavior depending on whether or not your laptop is " + "plugged in to the mains supply."), this ); + explain->setAlignment( Qt::WordBreak ); + top_layout->addWidget(explain); + + if (can_standby) { + QLabel* explain3 = new QLabel(i18n("Different laptops may respond to 'standby' in different ways - in many " + "it is only a temporary state and may not be useful for you."), this); + explain3->setAlignment( Qt::WordBreak ); + top_layout->addWidget(explain3, 0, Qt::AlignLeft); + } + + top_layout->addStretch(1); + + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this ), 0, Qt::AlignRight ); + } + } + + load(); +} + +PowerConfig::~PowerConfig() +{ + delete config; +} + +void PowerConfig::save() +{ + if (editwait) { + power = getPower(); + nopower = getNoPower(); + edit_wait = editwait->value(); + noedit_wait = noeditwait->value(); + nopower_bright_enabled = (nopowerBrightness?nopowerBrightness->isChecked():0); + power_bright_enabled = (powerBrightness?powerBrightness->isChecked():0); + nopower_bright_val = (nopowerValBrightness?nopowerValBrightness->value():0); + power_bright_val = (powerValBrightness?powerValBrightness->value():255); + nopower_performance_enabled = (nopowerPerformance?nopowerPerformance->isChecked():0); + power_performance_enabled = (powerPerformance?powerPerformance->isChecked():0); + nopower_performance_val = (nopowerValPerformance?nopowerValPerformance->currentText():""); + power_performance_val = (powerValPerformance?powerValPerformance->currentText():""); + nopower_throttle_enabled = (nopowerThrottle?nopowerThrottle->isChecked():0); + power_throttle_enabled = (powerThrottle?powerThrottle->isChecked():0); + nopower_throttle_val = (nopowerValThrottle?nopowerValThrottle->currentText():""); + power_throttle_val = (powerValThrottle?powerValThrottle->currentText():""); + edit_lav = (editlav?editlav->value():-1); + noedit_lav = (noeditlav?noeditlav->value():-1); + lav_enabled = (enablelav?enablelav->isChecked():0); + nolav_enabled = (noenablelav?noenablelav->isChecked():0); + } + + config->setGroup("LaptopPower"); + config->writeEntry("NoPowerSuspend", nopower); + config->writeEntry("PowerSuspend", power); + config->writeEntry("PowerWait", edit_wait); + config->writeEntry("NoPowerWait", noedit_wait); + config->writeEntry("PowerLav", edit_lav); + config->writeEntry("NoPowerLav", noedit_lav); + config->writeEntry("LavEnabled", lav_enabled); + config->writeEntry("NoLavEnabled", nolav_enabled); + config->writeEntry("PowerBrightnessEnabled", power_bright_enabled); + config->writeEntry("NoPowerBrightnessEnabled", nopower_bright_enabled); + config->writeEntry("PowerBrightness", power_bright_val); + config->writeEntry("NoPowerBrightness", nopower_bright_val); + config->writeEntry("PowerPerformanceEnabled", power_performance_enabled); + config->writeEntry("NoPowerPerformanceEnabled", nopower_performance_enabled); + config->writeEntry("PowerPerformance", power_performance_val); + config->writeEntry("NoPowerPerformance", nopower_performance_val); + config->writeEntry("PowerThrottleEnabled", power_throttle_enabled); + config->writeEntry("NoPowerThrottleEnabled", nopower_throttle_enabled); + config->writeEntry("PowerThrottle", power_throttle_val); + config->writeEntry("NoPowerThrottle", nopower_throttle_val); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void PowerConfig::load() +{ + load( false ); +} + +void PowerConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + + config->setGroup("LaptopPower"); + nopower = config->readNumEntry("NoPowerSuspend", (nopowerStandby?1:nopowerSuspend?2:0)); + power = config->readNumEntry("PowerSuspend", 0); + edit_wait = config->readNumEntry("PowerWait", 20); + noedit_wait = config->readNumEntry("NoPowerWait", 5); + edit_lav = config->readDoubleNumEntry("PowerLav", -1); + noedit_lav = config->readDoubleNumEntry("NoPowerLav", -1); + lav_enabled = config->readBoolEntry("LavEnabled", 0); + nolav_enabled = config->readBoolEntry("NoLavEnabled", 0); + nopower_bright_enabled = config->readBoolEntry("NoPowerBrightnessEnabled", 0); + power_bright_enabled = config->readBoolEntry("PowerBrightnessEnabled", 0); + nopower_bright_val = config->readNumEntry("NoPowerBrightness", 0); + power_bright_val = config->readNumEntry("PowerBrightness", 255); + nopower_performance_enabled = config->readBoolEntry("NoPowerPerformanceEnabled", 0); + power_performance_enabled = config->readBoolEntry("PowerPerformanceEnabled", 0); + nopower_performance_val = config->readEntry("NoPowerPerformance", ""); + power_performance_val = config->readEntry("PowerPerformance", ""); + nopower_throttle_enabled = config->readBoolEntry("NoPowerThrottleEnabled", 0); + power_throttle_enabled = config->readBoolEntry("PowerThrottleEnabled", 0); + nopower_throttle_val = config->readEntry("NoPowerThrottle", ""); + power_throttle_val = config->readEntry("PowerThrottle", ""); + + // the GUI should reflect the real values + if (editwait) { + editwait->setValue(edit_wait); + noeditwait->setValue(noedit_wait); + if (editlav) { + editlav->setValue(edit_lav); + editlav->setEnabled(lav_enabled); + } + if (noeditlav) { + noeditlav->setValue(noedit_lav); + noeditlav->setEnabled(nolav_enabled); + } + if (enablelav) + enablelav->setChecked(lav_enabled); + if (noenablelav) + noenablelav->setChecked(nolav_enabled); + setPower(power, nopower); + if (nopowerBrightness) + nopowerBrightness->setChecked(nopower_bright_enabled); + if (powerBrightness) + powerBrightness->setChecked(power_bright_enabled); + if (nopowerValBrightness) { + nopowerValBrightness->setValue(nopower_bright_val); + nopowerValBrightness->setEnabled(nopower_bright_enabled); + } + if (powerValBrightness) { + powerValBrightness->setValue(power_bright_val); + powerValBrightness->setEnabled(power_bright_enabled); + } + if (nopowerPerformance) + nopowerPerformance->setChecked(nopower_performance_enabled); + if (powerPerformance) + powerPerformance->setChecked(power_performance_enabled); + if (nopowerValPerformance) { + int ind = 0; + for (int i = 0; i < nopowerValPerformance->count(); i++) + if (nopowerValPerformance->text(i) == nopower_performance_val) { + ind = i; + break; + } + nopowerValPerformance->setCurrentItem(ind); + nopowerValPerformance->setEnabled(nopower_performance_enabled); + } + if (powerValPerformance) { + int ind = 0; + for (int i = 0; i < powerValPerformance->count(); i++) + if (powerValPerformance->text(i) == power_performance_val) { + ind = i; + break; + } + powerValPerformance->setCurrentItem(ind); + powerValPerformance->setEnabled(power_performance_enabled); + } + if (nopowerThrottle) + nopowerThrottle->setChecked(nopower_throttle_enabled); + if (powerThrottle) + powerThrottle->setChecked(power_throttle_enabled); + if (nopowerValThrottle) { + int ind = 0; + for (int i = 0; i < nopowerValThrottle->count(); i++) + if (nopowerValThrottle->text(i) == nopower_throttle_val) { + ind = i; + break; + } + nopowerValThrottle->setCurrentItem(ind); + nopowerValThrottle->setEnabled(nopower_throttle_enabled); + } + if (powerValThrottle) { + int ind = 0; + for (int i = 0; i < powerValThrottle->count(); i++) + if (powerValThrottle->text(i) == power_throttle_val) { + ind = i; + break; + } + powerValThrottle->setCurrentItem(ind); + powerValThrottle->setEnabled(power_throttle_enabled); + } + } + emit changed( useDefaults ); +} + +void PowerConfig::defaults() +{ + load( true ); +} + +int PowerConfig::getNoPower() +{ + if (!apm) + return(nopower); + if (nopowerHibernate && nopowerHibernate->isChecked()) + return 3; + if (nopowerStandby && nopowerStandby->isChecked()) + return 1; + if (nopowerSuspend && nopowerSuspend->isChecked()) + return 2; + return(0); +} + +int PowerConfig::getPower() +{ + if (!apm || !powerOff) + return(power); + if (powerHibernate && powerHibernate->isChecked()) + return 3; + if (powerStandby && powerStandby->isChecked()) + return 1; + if (powerSuspend && powerSuspend->isChecked()) + return 2; + return(0); +} + +void PowerConfig::setPower(int p, int np) +{ + if (!apm || nopowerOff == 0) + return; + if (nopowerSuspend) { + nopowerSuspend->setChecked(FALSE); + } else { + if (np == 2) np = 0; + } + if (nopowerStandby) { + nopowerStandby->setChecked(FALSE); + } else { + if (np == 1) np = 0; + } + if (nopowerHibernate) { + nopowerHibernate->setChecked(FALSE); + } else { + if (np == 3) np = 0; + } + if (nopowerOff) + nopowerOff->setChecked(FALSE); + switch (np) { + case 0: nopowerOff->setChecked(TRUE);break; + case 1: nopowerStandby->setChecked(TRUE);break; + case 2: nopowerSuspend->setChecked(TRUE);break; + case 3: nopowerHibernate->setChecked(TRUE);break; + } + if (powerSuspend) { + powerSuspend->setChecked(FALSE); + } else { + if (p == 2) p = 0; + } + if (powerStandby) { + powerStandby->setChecked(FALSE); + } else { + if (p == 1) p = 0; + } + if (powerHibernate) { + powerHibernate->setChecked(FALSE); + } else { + if (p == 3) p = 0; + } + if (powerOff) + powerOff->setChecked(FALSE); + switch (p) { + case 0: powerOff->setChecked(TRUE);break; + case 1: powerStandby->setChecked(TRUE);break; + case 2: powerSuspend->setChecked(TRUE);break; + case 3: powerHibernate->setChecked(TRUE);break; + } +} + + +QString PowerConfig::quickHelp() const +{ + return i18n("

Laptop Power Control

This module allows you to " + "control the power settings of your laptop and set timouts that will trigger " + "state changes you can use to save power"); + +} + +#include "power.moc" diff --git a/klaptopdaemon/power.h b/klaptopdaemon/power.h new file mode 100644 index 0000000..0d9d624 --- /dev/null +++ b/klaptopdaemon/power.h @@ -0,0 +1,98 @@ +/* + * power.h + * + * Copyright (c) 1999 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __POWERCONFIG_H__ +#define __POWERCONFIG_H__ + +#include +#include + +class QWidget; +class QSlider; +class QButtonGroup; +class QRadioButton; +class QSpinBox; +class KConfig; +class QCheckBox; +class KComboBox; +class KDoubleSpinBox; + +class PowerConfig : public KCModule +{ + Q_OBJECT +public: + PowerConfig( QWidget *parent=0, const char* name=0); + ~PowerConfig(); + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + + +private: + + int getPower(); + int getNoPower(); + void setPower( int, int ); + + QButtonGroup *nopowerBox; + QRadioButton *nopowerStandby, *nopowerSuspend, *nopowerOff, *nopowerHibernate; + QCheckBox *nopowerBrightness; + QSlider *nopowerValBrightness; + QCheckBox *nopowerThrottle; + KComboBox *nopowerValThrottle; + QCheckBox *nopowerPerformance; + KComboBox *nopowerValPerformance; + QButtonGroup *powerBox; + QRadioButton *powerStandby, *powerSuspend, *powerOff, *powerHibernate; + QCheckBox *powerBrightness; + QSlider *powerValBrightness; + QCheckBox *powerThrottle; + KComboBox *powerValThrottle; + QCheckBox *powerPerformance; + KComboBox *powerValPerformance; + QSpinBox *noeditwait; + QSpinBox *editwait; + QCheckBox *enablelav; + QCheckBox *noenablelav; + KDoubleSpinBox *noeditlav; + KDoubleSpinBox *editlav; + int edit_wait, noedit_wait; + int power_bright_val, nopower_bright_val; + bool nopower_bright_enabled, power_bright_enabled; + bool nopower_throttle_enabled, power_throttle_enabled; + QString nopower_throttle_val, power_throttle_val; + bool nopower_performance_enabled, power_performance_enabled; + bool lav_enabled, nolav_enabled; + float edit_lav, noedit_lav; + QString nopower_performance_val, power_performance_val; + + KConfig *config; + int power, nopower, apm; +}; + +#endif + diff --git a/klaptopdaemon/profile.cpp b/klaptopdaemon/profile.cpp new file mode 100644 index 0000000..a6285cb --- /dev/null +++ b/klaptopdaemon/profile.cpp @@ -0,0 +1,424 @@ +/* + * brightness.cpp + * + * Copyright (c) 2003 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// my headers: +#include "profile.h" +#include "version.h" +#include "portable.h" + +#include +#include +#include + +// other KDE headers: +#include +#include +#include +#include +#include +#include +#include +#include + +// other Qt headers: +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void wake_laptop_daemon(); + +ProfileConfig::ProfileConfig(QWidget * parent, const char *name) + : KCModule(parent, name) +{ + QStringList performance_list; + int current_performance; + bool *active_list; + bool has_performance = laptop_portable::get_system_performance(0, current_performance, performance_list, active_list); + QStringList throttle_list; + int current_throttle; + bool has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + config = new KConfig("kcmlaptoprc"); + + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + QHBoxLayout *ll = new QHBoxLayout(); + + QVGroupBox *gb = new QVGroupBox(i18n("Not Powered"), this); + QToolTip::add( gb, i18n( "Items in this box take effect whenever the laptop is unplugged from the wall" ) ); + if (laptop_portable::has_brightness()) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + poff = new QCheckBox(i18n("Back panel brightness"), wp); + QToolTip::add( poff, i18n( "Enables the changing of the back panel brightness" ) ); + xl->addWidget(poff); + connect (poff, SIGNAL(toggled(bool)), this, SLOT(poff_changed(bool))); + + xl->addWidget(new QLabel("-", wp)); + soff = new QSlider(0, 255, 16, 160, Qt::Horizontal, wp); + soff->setEnabled(0); + QToolTip::add( soff, i18n( "How bright it should be when it is changed" ) ); + connect (soff, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + xl->addWidget(soff); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } else { + poff = 0; + soff = 0; + } + + if (has_performance) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + performance_off = new QCheckBox(i18n("System performance"), wp); + QToolTip::add( performance_off, i18n( "Enables the changing of the system performance profile" ) ); + xl->addWidget(performance_off); + connect (performance_off, SIGNAL(toggled(bool)), this, SLOT(performance_off_changed(bool))); + + performance_val_off = new KComboBox(0, wp); + QToolTip::add( performance_val_off, i18n( "The new system performance profile to change to" ) ); + performance_val_off->insertStringList(performance_list); + performance_val_off->setEnabled(0); + connect (performance_val_off, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(performance_val_off); + xl->addStretch(1); + } else { + performance_off = 0; + performance_val_off = 0; + } + if (has_throttle) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + throttle_off = new QCheckBox(i18n("CPU throttling"), wp); + QToolTip::add( throttle_off, i18n( "Enables the throttling of the CPU performance" ) ); + xl->addWidget(throttle_off); + connect (throttle_off, SIGNAL(toggled(bool)), this, SLOT(throttle_off_changed(bool))); + + throttle_val_off = new KComboBox(0, wp); + throttle_val_off->insertStringList(throttle_list); + throttle_val_off->setEnabled(0); + QToolTip::add( throttle_val_off, i18n( "How much to throttle the CPU by" ) ); + connect (throttle_val_off, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(throttle_val_off); + xl->addStretch(1); + } else { + throttle_off = 0; + throttle_val_off = 0; + } + + ll->addWidget(gb); + + gb = new QVGroupBox(i18n("Powered"), this); + QToolTip::add( gb, i18n( "Items in this box take effect whenever the laptop is plugged into the wall" ) ); + if (laptop_portable::has_brightness()) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + pon = new QCheckBox(i18n("Back panel brightness"), wp); + QToolTip::add( pon, i18n( "Enables the changing of the back panel brightness" ) ); + xl->addWidget(pon); + connect (pon, SIGNAL(toggled(bool)), this, SLOT(pon_changed(bool))); + + xl->addWidget(new QLabel("-", wp)); + son = new QSlider(0, 255, 16, 255, Qt::Horizontal, wp); + son->setEnabled(0); + QToolTip::add( son, i18n( "How bright it should be when it is changed" ) ); + connect (son, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + xl->addWidget(son); + xl->addWidget(new QLabel("+", wp)); + xl->addStretch(1); + } else { + pon = 0; + son = 0; + } + if (has_performance) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + performance_on = new QCheckBox(i18n("System performance"), wp); + QToolTip::add( performance_on, i18n( "Enables the changing of the system performance profile" ) ); + xl->addWidget(performance_on); + connect (performance_on, SIGNAL(toggled(bool)), this, SLOT(performance_on_changed(bool))); + + performance_val_on = new KComboBox(0, wp); + performance_val_on->insertStringList(performance_list); + performance_val_on->setEnabled(0); + QToolTip::add( performance_val_on, i18n( "The new system performance profile to change to" ) ); + connect (performance_val_on, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(performance_val_on); + xl->addStretch(1); + } else { + performance_on = 0; + performance_val_on = 0; + } + if (has_throttle) { + QWidget *wp = new QWidget(gb); + QHBoxLayout *xl = new QHBoxLayout( wp); + throttle_on = new QCheckBox(i18n("CPU throttle"), wp); + QToolTip::add( throttle_on, i18n( "Enables the throttling of the CPU performance" ) ); + xl->addWidget(throttle_on); + connect (throttle_on, SIGNAL(toggled(bool)), this, SLOT(throttle_on_changed(bool))); + + throttle_val_on = new KComboBox(0, wp); + throttle_val_on->insertStringList(throttle_list); + throttle_val_on->setEnabled(0); + QToolTip::add( throttle_val_on, i18n( "How much to throttle the CPU by" ) ); + connect (throttle_val_on, SIGNAL(activated(int)), this, SLOT(configChanged())); + xl->addWidget(throttle_val_on); + xl->addStretch(1); + } else { + throttle_on = 0; + throttle_val_on = 0; + } + ll->addWidget(gb); + + ll->addStretch(1); + + top_layout->addLayout(ll); + QLabel *tmp_label = new QLabel(i18n("This panel allows you to set default values for system attributes " + "so that they change when the laptop is plugged in to the wall or " + "running on batteries."), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + + tmp_label = new QLabel(i18n("You can also set options for these values that will be set by low battery " + "conditions, or system inactivity in the other panels"), this ); + tmp_label->setAlignment( Qt::WordBreak ); + top_layout->addWidget( tmp_label ); + top_layout->addStretch(1); + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this), 0, Qt::AlignRight ); + + + load(); +} + +ProfileConfig::~ProfileConfig() +{ + delete config; +} + +void ProfileConfig::pon_changed(bool v) +{ + if (son) + son->setEnabled(v); + configChanged(); +} + +void ProfileConfig::poff_changed(bool v) +{ + if (soff) + soff->setEnabled(v); + configChanged(); +} + +void ProfileConfig::performance_on_changed(bool v) +{ + if (performance_val_on) + performance_val_on->setEnabled(v); + configChanged(); +} + +void ProfileConfig::performance_off_changed(bool v) +{ + if (performance_val_off) + performance_val_off->setEnabled(v); + configChanged(); +} + +void ProfileConfig::throttle_on_changed(bool v) +{ + if (throttle_val_on) + throttle_val_on->setEnabled(v); + configChanged(); +} + +void ProfileConfig::throttle_off_changed(bool v) +{ + if (throttle_val_off) + throttle_val_off->setEnabled(v); + configChanged(); +} + + +void ProfileConfig::save() +{ + config->setGroup("ProfileDefault"); + + config->writeEntry("EnableBrightnessOn", (pon?pon->isChecked():0)); + config->writeEntry("BrightnessOnLevel", (son?son->value():255)); + config->writeEntry("EnableBrightnessOff", (poff?poff->isChecked():0)); + config->writeEntry("BrightnessOffLevel", (soff?soff->value():160)); + config->writeEntry("EnablePerformanceOn", (performance_on?performance_on->isChecked():0)); + config->writeEntry("PerformanceOnLevel", (performance_val_on?performance_val_on->currentText():"")); + config->writeEntry("EnablePerformanceOff", (performance_off?performance_off->isChecked():0)); + config->writeEntry("PerformanceOffLevel", (performance_val_off?performance_val_off->currentText():"")); + config->writeEntry("EnableThrottleOn", (throttle_on?throttle_on->isChecked():0)); + config->writeEntry("ThrottleOnLevel", (throttle_val_on?throttle_val_on->currentText():"")); + config->writeEntry("EnableThrottleOff", (throttle_off?throttle_off->isChecked():0)); + config->writeEntry("ThrottleOffLevel", (throttle_val_off?throttle_val_off->currentText():"")); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void ProfileConfig::load() +{ + load( false ); +} + +void ProfileConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + + config->setGroup("ProfileDefault"); + + bool v; + if (pon) { + v = config->readBoolEntry("EnableBrightnessOn", false); + pon->setChecked(v); + } else { + v = 0; + } + int x; + if (son) { + x = config->readNumEntry("BrightnessOnLevel", 255); + son->setValue(x); + son->setEnabled(v); + } + if (poff) { + v = config->readBoolEntry("EnableBrightnessOff", false); + poff->setChecked(v); + } else { + v = 0; + } + if (soff) { + x = config->readNumEntry("BrightnessOffLevel", 160); + soff->setValue(x); + soff->setEnabled(v); + } + if (performance_on) { + v = config->readBoolEntry("EnablePerformanceOn", false); + performance_on->setChecked(v); + } else { + v = 0; + } + if (performance_val_on) { + QString s = config->readEntry("PerformanceOnLevel", ""); + int ind = 0; + for (int i = 0; i < performance_val_on->count(); i++) + if (performance_val_on->text(i) == s) { + ind = i; + break; + } + performance_val_on->setCurrentItem(ind); + performance_val_on->setEnabled(v); + } + if (performance_off) { + v = config->readBoolEntry("EnablePerformanceOff", false); + performance_off->setChecked(v); + } else { + v = 0; + } + if (performance_val_off) { + QString s = config->readEntry("PerformanceOffLevel", ""); + int ind = 0; + for (int i = 0; i < performance_val_off->count(); i++) + if (performance_val_off->text(i) == s) { + ind = i; + break; + } + performance_val_off->setCurrentItem(ind); + performance_val_off->setEnabled(v); + } + if (throttle_on) { + v = config->readBoolEntry("EnableThrottleOn", false); + throttle_on->setChecked(v); + } else { + v = 0; + } + if (throttle_val_on) { + QString s = config->readEntry("ThrottleOnLevel", ""); + int ind = 0; + for (int i = 0; i < throttle_val_on->count(); i++) + if (throttle_val_on->text(i) == s) { + ind = i; + break; + } + throttle_val_on->setCurrentItem(ind); + throttle_val_on->setEnabled(v); + } + if (throttle_off) { + v = config->readBoolEntry("EnableThrottleOff", false); + throttle_off->setChecked(v); + } else { + v = 0; + } + if (throttle_val_off) { + QString s = config->readEntry("ThrottleOffLevel", ""); + int ind = 0; + for (int i = 0; i < throttle_val_off->count(); i++) + if (throttle_val_off->text(i) == s) { + ind = i; + break; + } + throttle_val_off->setCurrentItem(ind); + throttle_val_off->setEnabled(v); + } + emit changed( useDefaults ); +} + +void ProfileConfig::defaults() +{ + load( true ); +} + + +void ProfileConfig::configChanged() +{ + emit changed(true); +} + + +QString ProfileConfig::quickHelp() const +{ + return i18n("

Laptop Power Profile Setup

This module allows you to configure default values for static laptop " + "system attributes that will change when the laptop is plugged in or unplugged from the wall."); +} + + +void ProfileConfig::slotStartMonitor() +{ + wake_laptop_daemon(); +} + + +#include "profile.moc" + + diff --git a/klaptopdaemon/profile.h b/klaptopdaemon/profile.h new file mode 100644 index 0000000..a9a81be --- /dev/null +++ b/klaptopdaemon/profile.h @@ -0,0 +1,82 @@ +/* + * brightness.h + * + * Copyright (c) 2003 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __BRIGHTNESSCONFIG_H__ +#define __BRIGHTNESSCONFIG_H__ + +#include +#include + +class QWidget; +class QSpinBox; +class KConfig; +class QCheckBox; +class QSlider; +class KIconLoader; +class KIconButton; +class QPushButton; +class KComboBox; + + +class ProfileConfig : public KCModule +{ + Q_OBJECT +public: + ProfileConfig( QWidget *parent=0, const char* name=0); + ~ProfileConfig( ); + + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + void slotStartMonitor(); + void poff_changed(bool); + void pon_changed(bool); + void throttle_off_changed(bool); + void throttle_on_changed(bool); + void performance_off_changed(bool); + void performance_on_changed(bool); + + +private: + KConfig *config; + + QCheckBox *pon, *performance_on, *throttle_on; + QSlider *son; + KComboBox *performance_val_on, *throttle_val_on; + QCheckBox *poff, *performance_off, *throttle_off; + QSlider *soff; + KComboBox *performance_val_off, *throttle_val_off; + + +}; + +#endif + diff --git a/klaptopdaemon/smapi.h b/klaptopdaemon/smapi.h new file mode 100644 index 0000000..fff1285 --- /dev/null +++ b/klaptopdaemon/smapi.h @@ -0,0 +1,54 @@ + +/********************************************************************* + * + * Filename: smapi.h + * Description: header file for the smapi driver + * Author: Thomas Hood + * Created: 19 July 1999 + * + * Please report bugs to the author ASAP. + * + * Copyright (c) 1999 J.D. Thomas Hood, All rights reserved + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To receive a copy of the GNU General Public License, please write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + ********************************************************************/ + +#ifndef __SMAPI_H__ +#define __SMAPI_H__ + +#include "smapibios.h" + + +/****** typedefs ******/ + +typedef smb_inparm_t smapi_inparm_t; +typedef smb_outparm_t smapi_outparm_t; + +typedef union _smapi_ioparm_t { + smapi_inparm_t in; + smapi_outparm_t out; +} smapi_ioparm_t; + + +/****** declarations ******/ + +int smapi_do( + unsigned long ulongIoctlArg, + flag_t fCallerHasWritePerm +); + + +#endif diff --git a/klaptopdaemon/smapibios.h b/klaptopdaemon/smapibios.h new file mode 100644 index 0000000..2751dc8 --- /dev/null +++ b/klaptopdaemon/smapibios.h @@ -0,0 +1,93 @@ + +/********************************************************************* + * + * Filename: smapibios.h + * Description: header file for the IBM SMAPI BIOS + * Author: Thomas Hood + * Created: 14 July 1999 + * + * Please report bugs to the author ASAP. + * + * Copyright (c) 1999 J.D. Thomas Hood, All rights reserved + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To receive a copy of the GNU General Public License, please write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + ********************************************************************/ + +#ifndef __SMAPIBIOS_H__ +#define __SMAPIBIOS_H__ + +/* Is included by smapi.h */ + +/*** SMAPI BIOS error codes ***/ +#define ERR_SMB_MIN ((byte)0x01) +#define ERR_SMB_FUNC_NOT_AVAIL ((byte)0x53) +#define ERR_SMB_FUNC_NOT_SUPPORTED ((byte)0x86) +#define ERR_SMB_SYSTEM_ERROR ((byte)0x90) +#define ERR_SMB_SYSTEM_INVALID ((byte)0x91) +#define ERR_SMB_SYSTEM_BUSY ((byte)0x92) +#define ERR_SMB_DEVICE_ERROR ((byte)0xA0) +#define ERR_SMB_DEVICE_BUSY ((byte)0xA1) +#define ERR_SMB_DEVICE_NOT_ATTACHED ((byte)0xA2) +#define ERR_SMB_DEVICE_DISABLED ((byte)0xA3) +#define ERR_SMB_PARM_INVALID ((byte)0x81) +#define ERR_SMB_PARM_OUT_OF_RANGE ((byte)0xA4) +#define ERR_SMB_PARM_NOT_ACCEPTED ((byte)0xA5) +#define ERR_SMB_MAX ((byte)0xFF) + +/* The following structure definitions come from the ThinkPad 560Z Technical Reference */ + +/*** SMAPI BIOS header ***/ +typedef struct _smb_header { + byte bSig[4]; /* signature */ + byte bVerMajor; /* major version */ + byte bVerMinor; /* minor version */ + byte bLen; /* length */ + byte bChksum; /* checksum */ + word wInfo; /* information word */ + word wRsv1; /* reserve 1 */ + word wR_offset; /* real mode offset */ + word wR_segment; /* real mode segment */ + word wRsv2; /* reserve 2 */ + word wP16_offset; /* 16-bit protect mode offset */ + dword dwP16_base; /* 16-bit protect mode base address */ + dword dwP32_offset; /* 32-bit protect mode offset */ + dword dwP32_base; /* 32-bit protect mode base address */ +} smb_header_t; + +/*** SMAPI BIOS call input parameters ***/ +typedef struct _smb_inparm { + byte bFunc; + byte bSubFunc; + word wParm1; + word wParm2; + word wParm3; + dword dwParm4; + dword dwParm5; +} smb_inparm_t; + + +/*** SMAPI BIOS call output parameters ***/ +typedef struct _smb_outparm { + byte bRc; + byte bSubRc; + word wParm1; + word wParm2; + word wParm3; + dword dwParm4; + dword dwParm5; +} smb_outparm_t; + +#endif diff --git a/klaptopdaemon/smapidev.c b/klaptopdaemon/smapidev.c new file mode 100644 index 0000000..3dbcd6d --- /dev/null +++ b/klaptopdaemon/smapidev.c @@ -0,0 +1,743 @@ +#if defined(__linux__) || defined(__FreeBSD__) +/********************************************************************* + * + * Filename: smapidev.c + * Description: IBM SMAPI (System Management API) interface functions + * Author: Bill Mair, Thomas Hood + * Created: 19 July 1999 + * + * Please report bugs to the author ASAP. + * + * Copyright (c) 1999 J.D. Thomas Hood and Bill Mair, + * All rights reserved + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To receive a copy of the GNU General Public License, please write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + ********************************************************************/ + +#include +#include +#ifdef __linux__ +#include +#else +#include +#endif +#include +#include +#include +#ifdef __linux__ +#include +#else +#include +#endif +#include +#include + +#ifndef __linux__ +typedef uint8_t __u8 ; +typedef uint16_t __u16 ; +typedef uint32_t __u32 ; +#endif + +#include "thinkpad_common.h" +/*#include "thinkpad.h" */ +#include "smapi.h" +#include "smapidev.h" + +/****** defines ******/ + +#define SZ_SMAPIDEV_VERSION "2.0" + +#define SZ_SMAPIDEV_NAME "smapidev" + +/* + * The structures may need to be extended if more + * functionality is added to the SMAPI by IBM. + * + * To cover this, future releases can check the size + * defined in sizeStruct, and reduce the amount of + * information put into the structure accordingly. + */ + +#define SIZE_BIOSINFO_V1 ((size_t)24) +#define SIZE_CPUINFO_V1 ((size_t)16) +#define SIZE_DISPLAYINFO_V1 ((size_t) 8) +#define SIZE_DOCKINGINFO_V1 ((size_t)12) +#define SIZE_ULTRABAYINFO_V1 ((size_t) 8) +#define SIZE_SLAVEINFO_V1 ((size_t)12) +#define SIZE_SENSORINFO_V1 ((size_t) 8) +#define SIZE_SCREENREFRESHINFO_V1 ((size_t)12) +#define SIZE_DISPLAYCAP_V1 ((size_t)12) + + +/****** variables ******/ + +char szSmapidevName[] = SZ_SMAPIDEV_NAME; + + +/****** utility functions ******/ + +/* + * This function returns the binary value of a two-digit bcd number + * If the bcd8 value is 0xFF, as it may be if a location has never been + * initialized in the ThinkPad CMOS RAM, then 0xFF is returned as the + * binary equivalent. + */ +byte byte_of_bcd8( bcd8_t bcd8The ) +{ + byte bTens, bUnits; + + /* catch uninitialized values: simply return them */ + if ( bcd8The == 0xFF ) return 0xFF; + + bUnits = (byte)bcd8The & 0xF; + bTens = (byte)(bcd8The & 0xF0) >> 4; + + if ( bUnits > 9 || bTens > 9 ) { + printf( "%s: Warning: value 0x%x which is supposed to be in BCD format is not; not converting.\n", szSmapidevName, bcd8The ); + return (byte)bcd8The; + } + + return bUnits + (bTens * 10); +} + + +bcd8_t bcd8_of_byte( byte bThe ) +{ + byte bTens, bUnits; + + if ( bThe > 99 ) { + printf( "%s: the value %d being converted to BCD format will be limited to 99.\n", szSmapidevName, bThe ); + bThe = 99; + } + + bTens = bThe / (byte)10; + bUnits = bThe - (bTens * (byte)10); + + return (bTens << 4) | bUnits; +} + +/* + * This function returns the SMAPI BIOS error code if there is one, + * otherwise the ioctl errno as a negative number + */ +int ioctl_smapi( int intFiledesc, smapi_ioparm_t *pioparmThe ) +{ + int intRtn; + + intRtn = ioctl( intFiledesc, IOCTL_SMAPI_REQUEST, pioparmThe ); + if ( intRtn && errno == ETHINKPAD_SUBDRIVER ) return pioparmThe->out.bRc; + if ( intRtn ) return -errno; + return 0; +} + + +/****** functions ******/ + +int smapidev_GetInfo( smapidev_info_t *pinfoThe ) +{ + + strncpy( pinfoThe->szVersion, SZ_SMAPIDEV_VERSION, LEN_VERSION_MAX ); + + /*** Make sure that the returned string is terminated ***/ + pinfoThe->szVersion[LEN_VERSION_MAX] = '\0'; + + return 0; +} + + +/*** smapi-module-access functions ***/ + + +/* + * The Technical Reference fails to mention that the returned + * BIOS revision values are in BCD format + */ +int smapidev_GetBiosInfo( + int intFiledesc, + smapidev_biosinfo_t *pbiosinfoThe +) { + bcd8_t bcd8SysHigh, bcd8SysLow; + bcd8_t bcd8SysMgmtHigh, bcd8SysMgmtLow; + bcd8_t bcd8SMAPIIfaceHigh, bcd8SMAPIIfaceLow; + bcd8_t bcd8VideoHigh, bcd8VideoLow; + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pbiosinfoThe->sizeStruct != SIZE_BIOSINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetBiosInfo\n" , pbiosinfoThe->sizeStruct, SIZE_BIOSINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 0; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pbiosinfoThe->wSysId = ioparmThe.out.wParm1; + pbiosinfoThe->wCountryCode = ioparmThe.out.wParm2; + + bcd8SysHigh = (bcd8_t)( ioparmThe.out.wParm3 >> 8 ); + bcd8SysLow = (bcd8_t)( ioparmThe.out.wParm3 & 0xFF ); + pbiosinfoThe->wSysBiosRevMajor = (word) byte_of_bcd8( bcd8SysHigh ); + pbiosinfoThe->wSysBiosRevMinor = (word) byte_of_bcd8( bcd8SysLow ); + + bcd8SysMgmtHigh = (bcd8_t)( (ioparmThe.out.dwParm4 >> 8) & 0xFF ); + bcd8SysMgmtLow = (bcd8_t)( ioparmThe.out.dwParm4 & 0xFF ); + pbiosinfoThe->wSysMgmtBiosRevMajor = (word) byte_of_bcd8( bcd8SysMgmtHigh ); + pbiosinfoThe->wSysMgmtBiosRevMinor = (word) byte_of_bcd8( bcd8SysMgmtLow ); + + bcd8SMAPIIfaceHigh = (bcd8_t)( (ioparmThe.out.dwParm5 >> 8) & 0xFF ); + bcd8SMAPIIfaceLow = (bcd8_t)( ioparmThe.out.dwParm5 & 0xFF ); + pbiosinfoThe->wSmapiBiosIfaceRevMajor = (word) byte_of_bcd8( bcd8SMAPIIfaceHigh ); + pbiosinfoThe->wSmapiBiosIfaceRevMinor = (word) byte_of_bcd8( bcd8SMAPIIfaceLow ); + + /*** Video BIOS info ***/ + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 8; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + bcd8VideoHigh = (bcd8_t)( (ioparmThe.out.wParm1 >> 8) ); + bcd8VideoLow = (bcd8_t)( ioparmThe.out.wParm1 & 0xFF ); + + pbiosinfoThe->wVideoBiosRevMajor = (word) byte_of_bcd8( bcd8VideoHigh ); + pbiosinfoThe->wVideoBiosRevMinor = (word) byte_of_bcd8( bcd8VideoLow ); + + return 0; +} + + +int smapidev_GetCpuInfo( + int intFiledesc, + smapidev_cpuinfo_t *pcpuinfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pcpuinfoThe->sizeStruct != SIZE_CPUINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetCpuInfo\n" , pcpuinfoThe->sizeStruct, SIZE_CPUINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 1; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pcpuinfoThe->wManufacturer = (word)( 0xFF & ioparmThe.out.wParm1 ); + pcpuinfoThe->wType = (word)( 0xFF & (ioparmThe.out.wParm2 >> 8) ); + pcpuinfoThe->wStepping = (word)( 0xFF & ioparmThe.out.wParm2 ); + + pcpuinfoThe->wClock = (word)( 0xFF & (ioparmThe.out.wParm3 >> 8) ); + + if ( pcpuinfoThe->wClock == 0xfe ) + pcpuinfoThe->wClock = (word) ioparmThe.out.dwParm4; + + pcpuinfoThe->wInternalClock = (word)( 0xFF & ioparmThe.out.wParm3 ); + if ( pcpuinfoThe->wInternalClock == 0xfe ) + pcpuinfoThe->wInternalClock = (word) ioparmThe.out.dwParm5; + + return 0; +} + + +int smapidev_GetDisplayInfo( + int intFiledesc, + smapidev_displayinfo_t *pdisplayinfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pdisplayinfoThe->sizeStruct != SIZE_DISPLAYINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetDisplayInfo\n" , pdisplayinfoThe->sizeStruct, SIZE_DISPLAYINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 2; + ioparmThe.in.wParm1 = (word) 0x300; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pdisplayinfoThe->bPanelType = (byte)(ioparmThe.out.wParm1 >> 8); + pdisplayinfoThe->bPanelDim = (byte)(ioparmThe.out.wParm1 & 0xFF); + pdisplayinfoThe->bCrtType = (byte)(ioparmThe.out.wParm2 >> 8); + pdisplayinfoThe->bCrtFeatures = (byte)(ioparmThe.out.wParm2 & 0xFF); + + return 0; +} + + +int smapidev_GetDockingInfo( + int intFiledesc, + smapidev_dockinginfo_t *pdockinginfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pdockinginfoThe->sizeStruct != SIZE_DOCKINGINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetDockingInfo\n" , pdockinginfoThe->sizeStruct, SIZE_DOCKINGINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 3; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pdockinginfoThe->wID = ioparmThe.out.wParm1; + pdockinginfoThe->fDocked = (flag_t)( ioparmThe.out.bSubRc & 1); + pdockinginfoThe->fKeyUnlocked = (flag_t)((ioparmThe.out.bSubRc >> 6) & 1); + pdockinginfoThe->fBusConnected = (flag_t)((ioparmThe.out.bSubRc >> 7) & 1); + + return 0; +} + + +int smapidev_GetUltrabayInfo( + int intFiledesc, + smapidev_ultrabayinfo_t *pultrabayinfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pultrabayinfoThe->sizeStruct != SIZE_ULTRABAYINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetUltrabayInfo\n" , pultrabayinfoThe->sizeStruct, SIZE_ULTRABAYINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 4; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pultrabayinfoThe->bType = (byte)(ioparmThe.out.wParm2 >> 8); + pultrabayinfoThe->bID = (byte)(ioparmThe.out.wParm2 & 0xFF); + + return 0; +} + + +/* + * The ThinkPad 560Z Technical Reference describes function 0:6 as + * "Get Power Management Module Information" while the ThinkPad 600 + * describes it as "Get Slave Micro Control Unit Information" + */ +int smapidev_GetSlaveControllerInfo( + int intFiledesc, + smapidev_slaveinfo_t *pslaveinfoThe +) { + smapi_ioparm_t ioparmThe; + bcd8_t bcd8High = 0, bcd8Low = 0; + flag_t fInvalidID; + int intRtn; + + /* Check structure size */ + if( pslaveinfoThe->sizeStruct != SIZE_SLAVEINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetSlaveControllerInfo\n" , pslaveinfoThe->sizeStruct, SIZE_SLAVEINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 6; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + if ( ioparmThe.out.wParm2 == 0xFFFF ) { + fInvalidID = 1; + } else { + fInvalidID = 0; + bcd8High = (bcd8_t)( ioparmThe.out.wParm2 >> 8 ); + bcd8Low = (bcd8_t)( ioparmThe.out.wParm2 & 0xFF ); + } + + pslaveinfoThe->fAscii = (ioparmThe.out.bSubRc == 0); + if ( fInvalidID ) { + pslaveinfoThe->wIDMajor = 0xFFFF; + pslaveinfoThe->wIDMinor = 0xFFFF; + } else { + pslaveinfoThe->wIDMajor = byte_of_bcd8( bcd8High ); + pslaveinfoThe->wIDMinor = byte_of_bcd8( bcd8Low ); + } + pslaveinfoThe->szID[0] = (char)(0xFF&(ioparmThe.out.wParm2>>8)); + pslaveinfoThe->szID[1] = (char)(0xFF&ioparmThe.out.wParm2); + pslaveinfoThe->szID[2] = '\0'; /* Add zero termination */ + + return 0; +} + + +int smapidev_GetSensorInfo( + int intFiledesc, + smapidev_sensorinfo_t *psensorinfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( psensorinfoThe->sizeStruct != SIZE_SENSORINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetSensorInfo\n" , psensorinfoThe->sizeStruct, SIZE_SENSORINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 7; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + psensorinfoThe->fLidClosed = (ioparmThe.out.wParm2 >> 8) & 1; + psensorinfoThe->fKeyboardOpen = (ioparmThe.out.wParm2 >> 9) & 1; + psensorinfoThe->fACAdapterAttached = (ioparmThe.out.wParm2 >> 10) & 1; + + return 0; +} + +int smapidev_GetScreenRefreshInfo( + int intFiledesc, + word wMode, + smapidev_screenrefreshinfo_t *pscreenrefreshinfoThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pscreenrefreshinfoThe->sizeStruct != SIZE_SCREENREFRESHINFO_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetScreenRefreshInfo\n" , pscreenrefreshinfoThe->sizeStruct, SIZE_SCREENREFRESHINFO_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0; + ioparmThe.in.bSubFunc = (byte) 9; + ioparmThe.in.wParm1 = wMode; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pscreenrefreshinfoThe->f43i = (ioparmThe.out.wParm2 >> 3) & 1; + pscreenrefreshinfoThe->f48i = (ioparmThe.out.wParm2 >> 7) & 1; + pscreenrefreshinfoThe->f56 = (ioparmThe.out.wParm2 >> 4) & 1; + pscreenrefreshinfoThe->f60 = ioparmThe.out.wParm2 & 1; + pscreenrefreshinfoThe->f70 = (ioparmThe.out.wParm2 >> 5) & 1; + pscreenrefreshinfoThe->f72 = (ioparmThe.out.wParm2 >> 1) & 1; + pscreenrefreshinfoThe->f75 = (ioparmThe.out.wParm2 >> 2) & 1; + pscreenrefreshinfoThe->f85 = (ioparmThe.out.wParm2 >> 6) & 1; + + return 0; +} + + +int smapidev_GetDisplayCapability( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_displaycap_t *pdisplaycapThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + /* Check structure size */ + if( pdisplaycapThe->sizeStruct != SIZE_DISPLAYCAP_V1 ) { +# if DEBUG_STRUCT_SIZES + printf( "Declared size %d does not match expected size %d in GetDisplayCapability\n" , pdisplaycapThe->sizeStruct, SIZE_DISPLAYCAP_V1 ); +# endif + return ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID; + } + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0x10; + ioparmThe.in.bSubFunc = (byte) 0; + switch ( stateplace ) { + case SMAPIDEV_STATEPLACE_CMOS: ioparmThe.in.wParm1 = (word) 1; break; + case SMAPIDEV_STATEPLACE_CURR: ioparmThe.in.wParm1 = (word) 0; break; + case SMAPIDEV_STATEPLACE_CMOS_AND_CURR: + default: return ERR_SMAPIDEV_PARM_INVALID; + } + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + pdisplaycapThe->fSupported = (flag_t)(ioparmThe.out.wParm2 & 1); + switch ( ioparmThe.out.wParm2 & 0xFF ) { + case 0: + pdisplaycapThe->tv = SMAPIDEV_DISPLAYCAPTV_NONE; + break; + case 1: + pdisplaycapThe->tv = SMAPIDEV_DISPLAYCAPTV_NONSIMULTANEOUS; + break; + default: + pdisplaycapThe->tv = SMAPIDEV_DISPLAYCAPTV_OTHER; + return ERR_SMAPIDEV_SMAPI_RESULT_NOT_UNDERSTOOD; + } + + return 0; +} + + +int smapidev_GetDisplayState( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_dispmode_t dispmodeThe, + smapidev_ablestate_t *pablestateThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0x10; + ioparmThe.in.bSubFunc = (byte) 0; + switch ( stateplace ) { + case SMAPIDEV_STATEPLACE_CMOS: ioparmThe.in.wParm1 = (word) 1; break; + case SMAPIDEV_STATEPLACE_CURR: ioparmThe.in.wParm1 = (word) 0; break; + case SMAPIDEV_STATEPLACE_CMOS_AND_CURR: + default: return ERR_SMAPIDEV_PARM_INVALID; + } + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + switch( dispmodeThe ) + { + case SMAPIDEV_DISPMODE_INTERNAL : + *pablestateThe = ( ioparmThe.out.wParm2 & 0x100 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + case SMAPIDEV_DISPMODE_CRT : + *pablestateThe = ( ioparmThe.out.wParm2 & 0x200 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + case SMAPIDEV_DISPMODE_TV : + *pablestateThe = ( ioparmThe.out.wParm2 & 0x400 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + case SMAPIDEV_DISPMODE_CRT_DETECTION_IGNORE : + *pablestateThe = ( ioparmThe.out.wParm2 & 0x4000 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + case SMAPIDEV_DISPMODE_DUAL : + *pablestateThe = ( ioparmThe.out.wParm2 & 0x8000 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + case SMAPIDEV_DISPMODE_SELECT_TV : + *pablestateThe = ( ioparmThe.out.dwParm4 & 1 ) ? SMAPIDEV_ABLESTATE_ENABLED : SMAPIDEV_ABLESTATE_DISABLED ; + break; + + default: + return ERR_SMAPIDEV_PARM_INVALID; + } + + return 0; +} + + +int smapidev_SetDisplayState( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_dispmode_t dispmodeThe, + smapidev_ablestate_t ablestateThe +) { + smapi_ioparm_t ioparmGet; + smapi_ioparm_t ioparmSet; + int intRtn; + + /* We can only update CMOS and current state together */ + if ( stateplace != SMAPIDEV_STATEPLACE_CMOS_AND_CURR ) + return ERR_SMAPIDEV_PARM_INVALID; + + /* No SMAPIDEV_STATE_AUTO or other invalid values are allowed here */ + if( ablestateThe != SMAPIDEV_ABLESTATE_DISABLED && ablestateThe != SMAPIDEV_ABLESTATE_ENABLED ) + { + return ERR_SMAPIDEV_PARM_INVALID; + } + + /* Get the current CMOS state */ + memset( &ioparmGet, 0, sizeof( ioparmGet ) ); + ioparmGet.in.bFunc = (byte) 0x10; + ioparmGet.in.bSubFunc = (byte) 0; + ioparmGet.in.wParm1 = (word) 1; + + intRtn = ioctl_smapi( intFiledesc, &ioparmGet ); + if ( intRtn ) return intRtn; + + memset( &ioparmSet, 0, sizeof( ioparmSet ) ); + ioparmSet.in.bFunc = (byte) 0x10; + ioparmSet.in.bSubFunc = (byte) 1; + ioparmSet.in.wParm1 = ioparmGet.out.wParm2 & 0xC700; + ioparmSet.in.dwParm4 = ioparmGet.out.dwParm4 & 0x0001; + + switch( dispmodeThe ) + { + + case SMAPIDEV_DISPMODE_INTERNAL : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.wParm1 |= 0x100; + else + ioparmSet.in.wParm1 &= ~0x100; + break; + + case SMAPIDEV_DISPMODE_CRT : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.wParm1 |= 0x200; + else + ioparmSet.in.wParm1 &= ~0x200; + break; + + case SMAPIDEV_DISPMODE_TV : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.wParm1 |= 0x400; + else + ioparmSet.in.wParm1 &= ~0x400; + break; + + case SMAPIDEV_DISPMODE_CRT_DETECTION_IGNORE : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.wParm1 |= 0x4000; + else + ioparmSet.in.wParm1 &= ~0x4000; + break; + + case SMAPIDEV_DISPMODE_DUAL : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.wParm1 |= 0x8000; + else + ioparmSet.in.wParm1 &= ~0x8000; + break; + + case SMAPIDEV_DISPMODE_SELECT_TV : + if( ablestateThe == SMAPIDEV_ABLESTATE_ENABLED ) + ioparmSet.in.dwParm4 |= 0x1; + else + ioparmSet.in.dwParm4 &= ~0x1; + break; + + default: + return ERR_SMAPIDEV_PARM_INVALID; + } + + return ioctl_smapi( intFiledesc, &ioparmSet ); +} + + +int smapidev_GetPowerExpenditureMode( + int intFiledesc, + smapidev_powersrc_t powersrcThe, + smapidev_powermode_t *ppowermodeThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + byte bModeAC, bModeBat, bModeSelected; + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0x22; + ioparmThe.in.bSubFunc = (byte) 0; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + bModeAC = (byte)(ioparmThe.out.wParm2 & 0xFF); + bModeBat = (byte)(ioparmThe.out.wParm2 >> 8); + bModeSelected = (powersrcThe == SMAPIDEV_POWERSRC_AC) ? bModeAC : bModeBat; + + switch ( bModeSelected ) { + case 0: *ppowermodeThe = SMAPIDEV_POWERMODE_HIGH; break; + case 1: *ppowermodeThe = SMAPIDEV_POWERMODE_AUTO; break; + case 2: *ppowermodeThe = SMAPIDEV_POWERMODE_MANUAL; break; + default: + case 3: *ppowermodeThe = SMAPIDEV_POWERMODE_UNRECOGNIZED; break; + } + + return 0; +} + + + +int smapidev_SetPowerExpenditureMode( + int intFiledesc, + smapidev_powersrc_t powersrcThe, + smapidev_powermode_t powermodeThe +) { + smapi_ioparm_t ioparmThe; + int intRtn; + byte bMode; + + bMode = + (powermodeThe == SMAPIDEV_POWERMODE_HIGH) ? 0 : + (powermodeThe == SMAPIDEV_POWERMODE_AUTO) ? 1 : + 2 + ; + + memset( &ioparmThe, 0, sizeof( ioparmThe ) ); + ioparmThe.in.bFunc = (byte) 0x22; + ioparmThe.in.bSubFunc = (byte) 0; + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + ioparmThe.in.bFunc = (byte) 0x22; + ioparmThe.in.bSubFunc = (byte) 1; + ioparmThe.in.wParm1 = ioparmThe.out.wParm2; + if ( powersrcThe == SMAPIDEV_POWERSRC_AC ) { + ioparmThe.in.wParm1 &= 0xff00; + ioparmThe.in.wParm1 |= bMode; + } else { /* powersrcThe == SMAPIDEV_POWERSRC_BATTERY */ + ioparmThe.in.wParm1 &= 0x00ff; + ioparmThe.in.wParm1 |= ((word)bMode) << 8; + } + + intRtn = ioctl_smapi( intFiledesc, &ioparmThe ); + if ( intRtn ) return intRtn; + + return 0; +} +#else +int smapi_dummy(){} +#endif diff --git a/klaptopdaemon/smapidev.h b/klaptopdaemon/smapidev.h new file mode 100644 index 0000000..22deedb --- /dev/null +++ b/klaptopdaemon/smapidev.h @@ -0,0 +1,273 @@ + +/********************************************************************* + * + * Filename: smapidev.h + * Description: Header for the SMAPI device driver access library + * Author: Bill Mair, Thomas Hood + * Created: 13 July 1999 + * + * Please report bugs to the author ASAP. + * + * Copyright (c) 1999 Bill Mair, All rights reserved + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To receive a copy of the GNU General Public License, please write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + ********************************************************************/ + +#ifndef __SMAPIDEV_H__ +#define __SMAPIDEV_H__ + +/****** defines ******/ + +/*** smapidev function error codes ***/ +/* + * These codes must not fall in the range 0x0-0xFF which is + * reserved for SMAPI BIOS error codes + */ +#define ERR_SMAPIDEV_MIN ((int)0x1000) +#define ERR_SMAPIDEV_PARM_INVALID ((int)0x1050) +#define ERR_SMAPIDEV_STRUCTURE_SIZE_INVALID ((int)0x1051) +#define ERR_SMAPIDEV_SMAPI_RESULT_NOT_UNDERSTOOD ((int)0x1090) +#define ERR_SMAPIDEV_MAX ((int)0x10FF) + +/****** typedefs ******/ + +/*** enum ***/ + +typedef enum _smapidev_stateplace { + SMAPIDEV_STATEPLACE_CURR=0, + SMAPIDEV_STATEPLACE_CMOS, + SMAPIDEV_STATEPLACE_CMOS_AND_CURR +} smapidev_stateplace_t; + +typedef enum _smapidev_ablestate { + SMAPIDEV_ABLESTATE_DISABLED=0, + SMAPIDEV_ABLESTATE_ENABLED, + SMAPIDEV_ABLESTATE_AUTO +} smapidev_ablestate_t; + +typedef enum _smapidev_displaycaptv { + SMAPIDEV_DISPLAYCAPTV_NONE=0, + SMAPIDEV_DISPLAYCAPTV_NONSIMULTANEOUS, + SMAPIDEV_DISPLAYCAPTV_OTHER +} smapidev_displaycaptv_t; + +/* + * The following are the display modes that can be enabled or disabled + */ +typedef enum _smapidev_dispmode { + SMAPIDEV_DISPMODE_INTERNAL=0, + SMAPIDEV_DISPMODE_CRT, + SMAPIDEV_DISPMODE_TV, + SMAPIDEV_DISPMODE_CRT_DETECTION_IGNORE, + SMAPIDEV_DISPMODE_DUAL, + SMAPIDEV_DISPMODE_SELECT_TV +} smapidev_dispmode_t; + +typedef enum _smapidev_fnkeymode { + SMAPIDEV_FNKEY_NORMAL=0, + SMAPIDEV_FNKEY_STICKY, + SMAPIDEV_FNKEY_LOCKED +} smapidev_fnkeymode_t; + +typedef enum _smapidev_ternality { + SMAPIDEV_TERNALITY_IN=0, + SMAPIDEV_TERNALITY_EX +} smapidev_ternality_t; + +typedef enum _smapidev_powersrc { + SMAPIDEV_POWERSRC_AC=0, + SMAPIDEV_POWERSRC_BATTERY +} smapidev_powersrc_t; + +typedef enum _smapidev_powermode { + SMAPIDEV_POWERMODE_HIGH=0, + SMAPIDEV_POWERMODE_AUTO, + SMAPIDEV_POWERMODE_MANUAL, + SMAPIDEV_POWERMODE_UNRECOGNIZED +} smapidev_powermode_t; + + +/*** struct ***/ + +typedef struct _smapidev_info +{ + char szVersion[LEN_VERSION_MAX+1]; +} smapidev_info_t; + +typedef struct _smapidev_biosinfo +{ + size_t sizeStruct; + word wSysId; + word wCountryCode; + word wSysBiosRevMajor; + word wSysBiosRevMinor; + word wSysMgmtBiosRevMajor; + word wSysMgmtBiosRevMinor; + word wSmapiBiosIfaceRevMajor; + word wSmapiBiosIfaceRevMinor; + word wVideoBiosRevMajor; + word wVideoBiosRevMinor; +} smapidev_biosinfo_t; + +typedef struct _smapidev_cpuinfo +{ + size_t sizeStruct; + word wManufacturer; + word wType; + word wStepping; + word wClock; + word wInternalClock; +} smapidev_cpuinfo_t; + +typedef struct _smapidev_displayinfo +{ + size_t sizeStruct; + byte bPanelType; + byte bPanelDim; + byte bCrtType; + byte bCrtFeatures; +} smapidev_displayinfo_t; + +typedef struct _smapidev_dockinginfo +{ + size_t sizeStruct; + word wID; + flag_t fDocked; + flag_t fKeyUnlocked; + flag_t fBusConnected; +} smapidev_dockinginfo_t; + +typedef struct _smapidev_ultrabayinfo +{ + size_t sizeStruct; + byte bType; + byte bID; +} smapidev_ultrabayinfo_t; + +typedef struct _smapidev_slaveinfo +{ + size_t sizeStruct; + flag_t fAscii; + char szID[3]; + word wIDMajor; + word wIDMinor; +} smapidev_slaveinfo_t; + +typedef struct _smapidev_sensorinfo +{ + size_t sizeStruct; + flag_t fLidClosed; + flag_t fKeyboardOpen; + flag_t fACAdapterAttached; +} smapidev_sensorinfo_t; + +typedef struct _smapidev_screenrefreshinfo +{ + size_t sizeStruct; + flag_t f43i; + flag_t f48i; + flag_t f56; + flag_t f60; + flag_t f70; + flag_t f72; + flag_t f75; + flag_t f85; +} smapidev_screenrefreshinfo_t; + +typedef struct _smapidev_displaycap { + size_t sizeStruct; + flag_t fSupported; + smapidev_displaycaptv_t tv; +} smapidev_displaycap_t; + + +/****** function declarations ******/ + +bcd8_t bcd8_of_byte( byte bThe ); +byte byte_of_bcd8( bcd8_t bcd8The ); +int ioctl_smapi( int intFiledesc, smapi_ioparm_t *pioparmThe ); + +/*** Get/Set####Info ***/ + +int smapidev_GetInfo( smapidev_info_t *pinfoThe ); +int smapidev_GetBiosInfo( + int intFiledesc, + smapidev_biosinfo_t *pbiosinfoThe +); +int smapidev_GetCpuInfo( + int intFiledesc, + smapidev_cpuinfo_t *pcpuinfoThe +); +int smapidev_GetDisplayInfo( + int intFiledesc, + smapidev_displayinfo_t *pdisplayinfoThe +); +int smapidev_GetDockingInfo( + int intFiledesc, + smapidev_dockinginfo_t *pdockinginfoThe +); +int smapidev_GetUltrabayInfo( + int intFiledesc, + smapidev_ultrabayinfo_t *pultrabayinfoThe +); +int smapidev_GetSlaveControllerInfo( + int intFiledesc, + smapidev_slaveinfo_t *pslaveinfoThe +); +int smapidev_GetSensorInfo( + int intFiledesc, + smapidev_sensorinfo_t *psensorinfoThe +); +int smapidev_GetScreenRefreshInfo( + int intFiledesc, + word wMode, + smapidev_screenrefreshinfo_t *pscreenrefreshinfoThe +); + +/*** Get/Set####State ***/ + +int smapidev_GetDisplayCapability( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_displaycap_t *pdisplaycap +); +int smapidev_GetDisplayState( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_dispmode_t dispmode, + smapidev_ablestate_t *pablestate +); +int smapidev_SetDisplayState( + int intFiledesc, + smapidev_stateplace_t stateplace, + smapidev_dispmode_t dispmode, + smapidev_ablestate_t ablestate +); + +/*** PM ***/ + +int smapidev_GetPowerExpenditureMode( + int intFiledesc, + smapidev_powersrc_t powersrc, + smapidev_powermode_t *ppowermode +); +int smapidev_SetPowerExpenditureMode( + int intFiledesc, + smapidev_powersrc_t powersrc, + smapidev_powermode_t powermode +); + +#endif diff --git a/klaptopdaemon/sony.cpp b/klaptopdaemon/sony.cpp new file mode 100644 index 0000000..8183f21 --- /dev/null +++ b/klaptopdaemon/sony.cpp @@ -0,0 +1,200 @@ +/* + * sony.cpp + * + * Copyright (c) 2002 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// my headers: +#include "sony.h" +#include "version.h" +#include "portable.h" + +#include +#include +#include + +// other KDE headers: +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// other Qt headers: +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void wake_laptop_daemon(); + +SonyConfig::SonyConfig(QWidget * parent, const char *name) + : KCModule(parent, name) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + config = new KConfig("kcmlaptoprc"); + + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + top_layout->addWidget(new KRichTextLabel(i18n("This panel allows you to control some of the features of the\n" + "'sonypi' device for your laptop - you should not enable the options below if you\nalso " + "use the 'sonypid' program in your system").replace("\n", " "), this)); + + enableScrollBar = new QCheckBox( i18n("Enable &scroll bar"), this ); + QToolTip::add( enableScrollBar, i18n( "When checked this box enables the scrollbar so that it works under KDE" ) ); + top_layout->addWidget( enableScrollBar ); + connect( enableScrollBar, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + enableMiddleEmulation = new QCheckBox( i18n("&Emulate middle mouse button with scroll bar press"), this ); + QToolTip::add( enableMiddleEmulation, i18n( "When checked this box enables pressing the scroll bar to act in the same way as pressing the middle button on a 3 button mouse" ) ); + top_layout->addWidget( enableMiddleEmulation ); + connect( enableMiddleEmulation, SIGNAL(clicked()), this, SLOT(configChanged()) ); + + if (::access("/dev/sonypi", R_OK) != 0) { + enableMiddleEmulation->setEnabled(0); + enableScrollBar->setEnabled(0); + + // TODO: remove linefeed from string, can't do it right now coz we have a string freeze + top_layout->addWidget(new KRichTextLabel(i18n("The /dev/sonypi is not accessable, if you wish to use the above features its\n" + "protections need to be changed. Clicking on the button below will change them\n").replace("\n", " "), this)); + QHBoxLayout *ll = new QHBoxLayout(); + QPushButton *setupButton = new QPushButton(i18n("Setup /dev/sonypi"), this); + connect( setupButton, SIGNAL(clicked()), this, SLOT(setupHelper()) ); + QToolTip::add( setupButton, i18n( "This button can be used to enable the sony specific features" ) ); + ll->addStretch(2); + ll->addWidget(setupButton); + ll->addStretch(8); + top_layout->addLayout(ll); + } + + + top_layout->addStretch(1); + top_layout->addWidget( new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this), 0, Qt::AlignRight ); + + + load(); +} + +void SonyConfig::setupHelper() +{ + QString kdesu = KStandardDirs::findExe("kdesu"); + if (!kdesu.isEmpty()) { + int rc = KMessageBox::warningContinueCancel(0, + i18n("You will need to supply a root password " + "to allow the protections of /dev/sonypi to be changed."), + i18n("KLaptopDaemon"), KStdGuiItem::cont(), + ""); + if (rc == KMessageBox::Continue) { + KProcess proc; + proc << kdesu; + proc << "-u"; + proc << "root"; + proc << "chmod +r /dev/sonypi"; + proc.start(KProcess::Block); // run it sync so has_acpi below sees the results + } + } else { + KMessageBox::sorry(0, i18n("The /dev/sonypi protections cannot be changed because kdesu cannot be found. Please make sure that it is installed correctly."), + i18n("KLaptopDaemon")); + } + bool enable = ::access("/dev/sonypi", R_OK) == 0; + enableMiddleEmulation->setEnabled(enable); + enableScrollBar->setEnabled(enable); + wake_laptop_daemon(); +} + +SonyConfig::~SonyConfig() +{ + delete config; +} + +void SonyConfig::save() +{ + enablescrollbar = enableScrollBar->isChecked(); + middleemulation = enableMiddleEmulation->isChecked(); + + config->setGroup("SonyDefault"); + + config->writeEntry("EnableScrollBar", enablescrollbar); + config->writeEntry("EnableMiddleEmulation", middleemulation); + config->sync(); + changed(false); + wake_laptop_daemon(); +} + +void SonyConfig::load() +{ + load( false ); +} + +void SonyConfig::load(bool useDefaults) +{ + config->setReadDefaults( useDefaults ); + + config->setGroup("SonyDefault"); + + enablescrollbar = config->readBoolEntry("EnableScrollBar", false); + enableScrollBar->setChecked(enablescrollbar); + middleemulation = config->readBoolEntry("EnableMiddleEmulation", false); + enableMiddleEmulation->setChecked(middleemulation); + + emit changed( useDefaults ); +} + +void SonyConfig::defaults() +{ + load( true ); +} + + +void SonyConfig::configChanged() +{ + emit changed(true); +} + + +QString SonyConfig::quickHelp() const +{ + return i18n("

Sony Laptop Hardware Setup

This module allows you to configure " + "some Sony laptop hardware for your system"); +} + + +void SonyConfig::slotStartMonitor() +{ + wake_laptop_daemon(); +} + + +#include "sony.moc" + + diff --git a/klaptopdaemon/sony.h b/klaptopdaemon/sony.h new file mode 100644 index 0000000..ab31065 --- /dev/null +++ b/klaptopdaemon/sony.h @@ -0,0 +1,71 @@ +/* + * sony.h + * + * Copyright (c) 2002 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __SONYCONFIG_H__ +#define __SONYCONFIG_H__ + +#include +#include + +class QWidget; +class QSpinBox; +class KConfig; +class QCheckBox; +class QSlider; +class KIconLoader; +class KIconButton; +class QPushButton; + + +class SonyConfig : public KCModule +{ + Q_OBJECT +public: + SonyConfig( QWidget *parent=0, const char* name=0); + ~SonyConfig( ); + + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + + void configChanged(); + void slotStartMonitor(); + void setupHelper(); + +private: + KConfig *config; + + QCheckBox *enableScrollBar; + bool enablescrollbar; + QCheckBox *enableMiddleEmulation; + bool middleemulation; +}; + +#endif + diff --git a/klaptopdaemon/thinkpad_common.h b/klaptopdaemon/thinkpad_common.h new file mode 100644 index 0000000..c347e06 --- /dev/null +++ b/klaptopdaemon/thinkpad_common.h @@ -0,0 +1,127 @@ + +/********************************************************************* + * + * Filename: thinkpad_common.h + * Description: stuff required by the "thinkpad" drivers and + * by programs accessing them + * Author: Thomas Hood + * Created: 19 July 1999 + * + * Please report bugs to the author ASAP. + * + * Copyright (c) 1999 J.D. Thomas Hood, All rights reserved + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * To receive a copy of the GNU General Public License, please write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + ********************************************************************/ + +#ifndef __THINKPAD_COMMON_H__ +#define __THINKPAD_COMMON_H__ + +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif + +/* All module (etc.) names should be no longer than this: */ +#define LEN_NAME_MAX 80 + +/* All version strings should be no longer than this: */ +#define LEN_VERSION_MAX 30 + +/****** macros ******/ + +#ifdef DEBUG_IOPARM +#define DEBUG_PRINT_OUTPARMS( ioparmThe ) { \ + printf( "bRc: 0x%x\n", ioparmThe.out.bRc ); \ + printf( "bSubRc: 0x%x\n", ioparmThe.out.bSubRc ); \ + printf( "wParm1: 0x%x\n", ioparmThe.out.wParm1 ); \ + printf( "wParm2: 0x%x\n", ioparmThe.out.wParm2 ); \ + printf( "wParm3: 0x%x\n", ioparmThe.out.wParm3 ); \ + printf( "dwParm4: 0x%lx\n", (unsigned long) ioparmThe.out.dwParm4 ); \ + printf( "dwParm5: 0x%lx\n", (unsigned long) ioparmThe.out.dwParm5 ); \ +} +#define DEBUG_PRINT_INPARMS( ioparmThe ) { \ + printf( "bFunc: 0x%x\n", ioparmThe.in.bFunc ); \ + printf( "bSubFunc: 0x%x\n", ioparmThe.in.bSubFunc ); \ + printf( "wParm1: 0x%x\n", ioparmThe.in.wParm1 ); \ + printf( "wParm2: 0x%x\n", ioparmThe.in.wParm2 ); \ + printf( "wParm3: 0x%x\n", ioparmThe.in.wParm3 ); \ + printf( "dwParm4: 0x%lx\n", (unsigned long) ioparmThe.in.dwParm4 ); \ + printf( "dwParm5: 0x%lx\n", (unsigned long) ioparmThe.in.dwParm5 ); \ +} +#else +#define DEBUG_PRINT_OUTPARMS( ioparmThe ) +#define DEBUG_PRINT_INPARMS( ioparmThe ) +#endif + + +/****** types ******/ +typedef uint8_t byte; +typedef uint16_t word; +typedef uint32_t dword; +typedef char flag_t; +typedef byte bcd8_t; + +/*** ioctl commands ***/ + +/*#include "thinkpad.h" */ +#include "smapi.h" +/*#include "superio.h" */ +/*#include "rtcmosram.h" */ +/*#include "thinkpadpm.h" */ + +#define MAGIC_THINKPAD_IOCTL ('(') +#define IOCTL_THINKPAD_GETVER _IOR (MAGIC_THINKPAD_IOCTL,0x1,thinkpad_ioparm_t) +#define IOCTL_THINKPAD_ENABLE _IOWR(MAGIC_THINKPAD_IOCTL,0x2,thinkpad_ioparm_t) +#define IOCTL_THINKPAD_DISABLE _IOWR(MAGIC_THINKPAD_IOCTL,0x3,thinkpad_ioparm_t) +#define IOCTL_SMAPI_REQUEST _IOWR(MAGIC_THINKPAD_IOCTL,0x10,smapi_ioparm_t) +#define IOCTL_SUPERIO_REQUEST _IOWR(MAGIC_THINKPAD_IOCTL,0x11,superio_ioparm_t) +#define IOCTL_RTCMOSRAM_REQUEST _IOWR(MAGIC_THINKPAD_IOCTL,0x12,rtcmosram_ioparm_t) +#define IOCTL_THINKPADPM_REQUEST _IOWR(MAGIC_THINKPAD_IOCTL,0x20,thinkpadpm_ioparm_t) + +/****** return values ******/ + +/* 0 as a return value always means OK */ + +/* + * We use the following standard UNIX errno's, defined in + * EFAULT memory error + * EBUSY device is already open + * EINVAL function code not recognized + * ENOTTY ioctl code not recognized + * EACCESS inadequate permission to perform action + * + * We use the following standard errnos under names more descriptive + * of our circumstances. Remember that the ioctl handler in the + * driver returns the negatives of these, but they turn up positive + * in user space in errno after an ioctl() call. Our convention + * for ioctl_blah() wrapper functions is to return the errno as a + * negative number. + */ +#define ETHINKPAD_PROGRAMMING (1024) +#define ETHINKPAD_HW_NOT_FOUND (1025) +#define ETHINKPAD_MODULE_DISABLED (1026) +#define ETHINKPAD_MODULE_NOT_FOUND (1027) +#define ETHINKPAD_SUBDRIVER (1028) + +/* + * Subdriver error codes are returned in the parameter block + * and errno is set to THINKPAD_SUBDRIVER + * + */ + +#endif /* __THINKPAD_COMMON_H__ */ diff --git a/klaptopdaemon/version.h b/klaptopdaemon/version.h new file mode 100644 index 0000000..aa0cdd4 --- /dev/null +++ b/klaptopdaemon/version.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2002 Paul Campbell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LAPTOP_VERSION "1.4" diff --git a/klaptopdaemon/wake_laptop.cpp b/klaptopdaemon/wake_laptop.cpp new file mode 100644 index 0000000..6b2a2b9 --- /dev/null +++ b/klaptopdaemon/wake_laptop.cpp @@ -0,0 +1,39 @@ +/* + * wake_laptop.cpp + * Copyright (C) 2003 Paul Campbell + * + * send restart message to laptop daemon thru kded so that the daemon + * gets started if required + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include + +KDE_EXPORT void +wake_laptop_daemon() +{ + DCOPClient *dclient = kapp->dcopClient(); + if (!dclient || (!dclient->isAttached() && !dclient->attach())) + return; + + QByteArray data; + QDataStream arg( data, IO_WriteOnly ); + (void) dclient->send( "kded", "klaptopdaemon", "restart()", data ); +} diff --git a/klaptopdaemon/warning.cpp b/klaptopdaemon/warning.cpp new file mode 100644 index 0000000..29944e0 --- /dev/null +++ b/klaptopdaemon/warning.cpp @@ -0,0 +1,602 @@ +/* + * warning.cpp + * + * Copyright (c) 1999 Paul Campbell + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "warning.h" +#include "portable.h" +#include "version.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +extern void wake_laptop_daemon(); + +WarningConfig::WarningConfig (int t, QWidget * parent, const char *name) + : KCModule(parent, name), + checkSuspend(0), + checkStandby(0), + checkHibernate(0) +{ + KGlobal::locale()->insertCatalogue("klaptopdaemon"); // For translation of klaptopdaemon messages + + type = t; + apm = laptop_portable::has_power_management(); + config = new KConfig("kcmlaptoprc"); + + my_load(0); + + if (!apm) { + QVBoxLayout *top_layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + KActiveLabel* explain = laptop_portable::no_power_management_explanation(this); + top_layout->addWidget(explain, 0); + + top_layout->addStretch(1); + } else { + QGridLayout *grid = new QGridLayout( this, 11, 2, /* rows x cols */ + KDialog::marginHint(), + KDialog::spacingHint() ); + grid->setColStretch( 1, 1 ); + + int curRow = 0; + // setup the trigger stuff: + if (type) { + checkCriticalTime = new QCheckBox( i18n("Critical &trigger:"), this ); + checkCriticalPercent = new QCheckBox( i18n("Critical &trigger:"), this ); + editCriticalTime = new QSpinBox(1, 60*24, 1, this); + editCriticalTime->setSuffix(i18n("keep short, unit in spinbox", "min")); + QToolTip::add(editCriticalTime, i18n("When this amount of battery life is left the actions below will be triggered")); + editCriticalPercent = new QSpinBox(1, 100, 1, this); + editCriticalPercent->setSuffix(i18n("keep short, unit in spinbox", "%")); + QToolTip::add(editCriticalPercent, i18n("When this amount of battery life is left the actions below will be triggered")); + grid->addWidget(checkCriticalTime, curRow, 0); + grid->addWidget(editCriticalTime, curRow++, Qt::AlignLeft); + grid->addWidget(checkCriticalPercent, curRow, 0); + grid->addWidget(editCriticalPercent, curRow++, Qt::AlignLeft); + + connect(editCriticalTime, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + connect(editCriticalPercent, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + connect(checkCriticalTime, SIGNAL(toggled(bool)), this, SLOT(configChanged())); + connect(checkCriticalPercent, SIGNAL(toggled(bool)), this, SLOT(configChanged())); + connect(checkCriticalTime, SIGNAL(toggled(bool)), this, SLOT(checkCriticalTimeChanged(bool))); + connect(checkCriticalPercent, SIGNAL(toggled(bool)), this, SLOT(checkCriticalPercentChanged(bool))); + } else { + checkLowTime = new QCheckBox( i18n("Low &trigger:"), this ); + checkLowPercent = new QCheckBox( i18n("Low &trigger:"), this ); + editLowTime = new QSpinBox(1, 60*24, 1, this); + editLowTime->setSuffix(i18n("keep short, unit in spinbox", "min")); + QToolTip::add(editLowTime, i18n("When this amount of battery life is left the actions below will be triggered")); + editLowPercent = new QSpinBox(1, 100, 1, this); + editLowPercent->setSuffix(i18n("keep short, unit in spinbox", "%")); + QToolTip::add(editLowPercent, i18n("When this amount of battery life is left the actions below will be triggered")); + grid->addWidget(checkLowTime, curRow, 0); + grid->addWidget(editLowTime, curRow++, Qt::AlignLeft); + grid->addWidget(checkLowPercent, curRow, 0); + grid->addWidget(editLowPercent, curRow++, Qt::AlignLeft); + + connect(editLowTime, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + connect(editLowPercent, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + connect(checkLowTime, SIGNAL(toggled(bool)), this, SLOT(configChanged())); + connect(checkLowPercent, SIGNAL(toggled(bool)), this, SLOT(configChanged())); + connect(checkLowTime, SIGNAL(toggled(bool)), this, SLOT(checkLowTimeChanged(bool))); + connect(checkLowPercent, SIGNAL(toggled(bool)), this, SLOT(checkLowPercentChanged(bool))); + } + + + // setup the Run Command stuff + checkRunCommand = new QCheckBox(i18n("Run &command:"), this); + grid->addWidget(checkRunCommand, curRow, 0); + + editRunCommand = new KURLRequester( this ); + editRunCommand->setEnabled(false); + connect( checkRunCommand, SIGNAL(toggled(bool)), + editRunCommand, SLOT(setEnabled(bool)) ); + connect( checkRunCommand, SIGNAL(clicked()), + this, SLOT(configChanged()) ); + connect( editRunCommand, SIGNAL(textChanged(const QString&)), + this, SLOT(configChanged()) ); + grid->addWidget(editRunCommand, curRow++, 1); + QToolTip::add( editRunCommand, i18n( "This command will be run when the battery gets low" ) ); + + // setup the Play Sound stuff + checkPlaySound = new QCheckBox(i18n("&Play sound:"), this); + grid->addWidget(checkPlaySound, curRow, 0); + + editPlaySound = new KURLRequester( this ); + editPlaySound->setEnabled(false); + connect( checkPlaySound, SIGNAL(toggled(bool)), + editPlaySound, SLOT(setEnabled(bool)) ); + connect( checkPlaySound, SIGNAL(clicked()), + this, SLOT(configChanged()) ); + connect( editPlaySound, SIGNAL(textChanged(const QString&)), + this, SLOT(configChanged()) ); + grid->addWidget(editPlaySound, curRow++, 1); + QToolTip::add( editPlaySound, i18n( "This sound will play when the battery gets low" ) ); + + // setup the System Sound stuff + checkBeep = new QCheckBox(i18n("System &beep"), this); + grid->addWidget(checkBeep, curRow++, 0); + connect(checkBeep, SIGNAL(clicked()), this, SLOT(configChanged())); + QToolTip::add( checkBeep, i18n( "The system will beep if this is enabled" ) ); + + checkNotify = new QCheckBox(i18n("&Notify"), this); + grid->addWidget(checkNotify, curRow++, 0); + connect(checkNotify, SIGNAL(clicked()), this, SLOT(configChanged())); + + int can_suspend = laptop_portable::has_suspend(); + int can_standby = laptop_portable::has_standby(); + int can_hibernate = laptop_portable::has_hibernation(); + int can_brightness = laptop_portable::has_brightness(); + + if (can_brightness) { + checkBrightness = new QCheckBox(i18n("Panel b&rightness"), this); + checkBrightness->setMinimumSize(checkBrightness->sizeHint()); + QToolTip::add( checkBrightness, i18n( "If enabled the back panel brightness will change" ) ); + grid->addWidget(checkBrightness, curRow, 0); + connect(checkBrightness, SIGNAL(toggled(bool)), this, SLOT(brightness_changed(bool))); + QHBoxLayout *v = new QHBoxLayout(); + v->addWidget(new QLabel("-", this)); + valueBrightness = new QSlider(0, 255, 16, 160, Qt::Horizontal, this); + QToolTip::add( valueBrightness, i18n( "How bright or dim to make the back panel" ) ); + valueBrightness->setMaximumWidth(70); + v->addWidget(valueBrightness); + v->addWidget(new QLabel("+", this)); + v->addStretch(1); + grid->addLayout(v, curRow, 1); + valueBrightness->setEnabled(0); + connect(valueBrightness, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + ++curRow; + } else { + checkBrightness = 0; + valueBrightness = 0; + } + QStringList performance_list; + int current_performance; + bool *active_list; + bool has_performance = laptop_portable::get_system_performance(0, current_performance, performance_list, active_list); + if (has_performance) { + performance = new QCheckBox(i18n("System performance"), this); + QToolTip::add( performance, i18n( "If enabled the laptop's power performance profile will change" ) ); + grid->addWidget(performance, curRow, 0); + connect (performance, SIGNAL(toggled(bool)), this, SLOT(performance_changed(bool))); + + QHBoxLayout *v = new QHBoxLayout(); + performance_val = new KComboBox(0, this); + performance_val->insertStringList(performance_list); + performance_val->setEnabled(0); + connect (performance_val, SIGNAL(activated(int)), this, SLOT(configChanged())); + QToolTip::add( performance_val, i18n( "The performance profile to change to" ) ); + v->addWidget(performance_val); + v->addStretch(1); + grid->addLayout(v, curRow, 1); + ++curRow; + } else { + performance = 0; + performance_val = 0; + } + QStringList throttle_list; + int current_throttle; + bool has_throttle = laptop_portable::get_system_throttling(0, current_throttle, throttle_list, active_list); + if (has_throttle) { + throttle = new QCheckBox(i18n("CPU throttling"), this); + QToolTip::add( throttle, i18n( "If enabled the CPU performance will be throttled" ) ); + grid->addWidget(throttle, curRow, 0); + connect (throttle, SIGNAL(toggled(bool)), this, SLOT(throttle_changed(bool))); + + QHBoxLayout *v = new QHBoxLayout(); + throttle_val = new KComboBox(0, this); + throttle_val->insertStringList(throttle_list); + throttle_val->setEnabled(0); + connect (throttle_val, SIGNAL(activated(int)), this, SLOT(configChanged())); + QToolTip::add( throttle_val, i18n( "How much to throttle the CPU performance by" ) ); + v->addWidget(throttle_val); + v->addStretch(1); + grid->addLayout(v, curRow, 1); + ++curRow; + } else { + throttle = 0; + throttle_val = 0; + } + + + + QVButtonGroup *b = new QVButtonGroup(i18n("System State Change"), this); + QToolTip::add( b, i18n( "You may choose one of the following to occur when the battery gets low" ) ); + b->layout()->setSpacing( KDialog::spacingHint() ); + if (can_standby) { + checkStandby = new QRadioButton(i18n("Standb&y"), b); + QToolTip::add( checkStandby, i18n( "Move the system into the standby state - a temporary lower power state" ) ); + checkStandby->setMinimumSize(checkStandby->sizeHint()); + connect(checkStandby, SIGNAL(clicked()), this, SLOT(configChanged())); + } + if (can_suspend) { + checkSuspend = new QRadioButton(i18n("&Suspend"), b); + QToolTip::add( checkSuspend, i18n( "Move the system into the suspend state - also known as 'save-to-ram'" ) ); + checkSuspend->setMinimumSize(checkSuspend->sizeHint()); + connect(checkSuspend, SIGNAL(clicked()), this, SLOT(configChanged())); + } + if (can_hibernate) { + checkHibernate = new QRadioButton(i18n("H&ibernate"), b); + QToolTip::add( checkHibernate, i18n( "Move the system into the hibernate state - also known as 'save-to-disk'" ) ); + checkHibernate->setMinimumSize(checkHibernate->sizeHint()); + connect(checkHibernate, SIGNAL(clicked()), this, SLOT(configChanged())); + } + // setup the logout option + checkLogout = new QRadioButton(i18n("&Logout"), b); + connect(checkLogout, SIGNAL(clicked()), this, SLOT(configChanged())); + // setup the shutdown option + checkShutdown = new QRadioButton(i18n("System power off"), b); + QToolTip::add( checkShutdown, i18n( "Power the laptop off" ) ); + connect(checkShutdown, SIGNAL(clicked()), this, SLOT(configChanged())); + + checkNone = new QRadioButton(i18n("&None"), b); + connect(checkNone, SIGNAL(clicked()), this, SLOT(configChanged())); + + grid->addMultiCellWidget(b, curRow, curRow, 0, 1, Qt::AlignLeft|Qt::AlignTop); + curRow++; + + + QLabel* explain; + if (type) { + explain = new QLabel(i18n("This panel controls how and when you receive warnings that your battery power is going to run out VERY VERY soon."), this); + } else { + explain = new QLabel(i18n("This panel controls how and when you receive warnings that your battery power is about to run out"), this); + } + explain->setAlignment( Qt::WordBreak ); + grid->addMultiCellWidget(explain, curRow, curRow, 0, 1); + ++curRow; + + if (!can_suspend && !can_standby && !can_hibernate) { + // display help text: + QLabel* note = laptop_portable::how_to_do_suspend_resume(this); + grid->addMultiCellWidget(note, curRow, curRow, 0, 1); + ++curRow; + } + grid->setRowStretch(curRow++, 1); + + grid->addWidget(new QLabel( i18n("Version: %1").arg(LAPTOP_VERSION), this), + curRow, 1, Qt::AlignRight); + + } + my_load(1); +} + +WarningConfig::~WarningConfig() +{ + delete config; +} + +void WarningConfig::brightness_changed(bool v) +{ + valueBrightness->setEnabled(v); + configChanged(); +} + +void WarningConfig::throttle_changed(bool v) +{ + throttle_val->setEnabled(v); + configChanged(); +} + +void WarningConfig::performance_changed(bool v) +{ + performance_val->setEnabled(v); + configChanged(); +} + +void WarningConfig::checkLowTimeChanged(bool state) +{ + checkLowPercent->setChecked(state ? false : true); + editLowPercent->setEnabled(state ? false : true); +} + +void WarningConfig::checkLowPercentChanged(bool state) +{ + checkLowTime->setChecked(state ? false : true); + editLowTime->setEnabled(state ? false : true); +} + +void WarningConfig::checkCriticalTimeChanged(bool state) +{ + checkCriticalPercent->setChecked(state ? false : true); + editCriticalPercent->setEnabled(state ? false : true); +} + +void WarningConfig::checkCriticalPercentChanged(bool state) +{ + checkCriticalTime->setChecked(state ? false: true); + editCriticalTime->setEnabled(state ? false : true); +} + + +void WarningConfig::save() +{ + if (apm) { + runcommand = checkRunCommand->isChecked(); + playsound = checkPlaySound->isChecked(); + logout = checkLogout->isChecked(); + shutdown = checkShutdown->isChecked(); + beep = checkBeep->isChecked(); + notify = checkNotify->isChecked(); + do_suspend = (checkSuspend? checkSuspend->isChecked() : false); + do_standby = (checkStandby? checkStandby->isChecked() : false); + do_hibernate = (checkHibernate? checkHibernate->isChecked() : false); + do_brightness = (checkBrightness? checkBrightness->isChecked() : false); + val_brightness = (valueBrightness? valueBrightness->value() : 255); + do_performance = (performance? performance->isChecked() : false); + val_performance = (performance_val? performance_val->currentText() : ""); + do_throttle = (throttle? throttle->isChecked() : false); + val_throttle = (throttle_val? throttle_val->currentText() : ""); + runcommand_val = editRunCommand->url(); + if (type) { + time_based_action_critical = checkCriticalTime->isChecked(); + critical_val_time = editCriticalTime->value(); + critical_val_percent = editCriticalPercent->value(); + } else { + time_based_action_low = checkLowTime->isChecked(); + low_val_time = editLowTime->value(); + low_val_percent = editLowPercent->value(); + } + + sound_val = editPlaySound->url(); + } + config->setGroup((type?"BatteryCritical":"BatteryLow")); + + if (config->group() == "BatteryLow") { + config->writeEntry("TimeBasedAction", time_based_action_low); + config->writeEntry("LowValTime", low_val_time); + config->writeEntry("LowValPercent", low_val_percent); + } else { + config->writeEntry("TimeBasedAction", time_based_action_critical); + config->writeEntry("CriticalValTime", critical_val_time); + config->writeEntry("CriticalValPercent", critical_val_percent); + } + config->writeEntry("RunCommand", runcommand); + config->writeEntry("PlaySound", playsound); + config->writeEntry("Logout", logout); + config->writeEntry("Shutdown", shutdown); + config->writeEntry("SystemBeep", beep); + config->writeEntry("Notify", notify); + config->writeEntry("Suspend", do_suspend); + config->writeEntry("Standby", do_standby); + config->writeEntry("Hibernate", do_hibernate); + config->writeEntry("Brightness", do_brightness); + config->writeEntry("BrightnessValue", val_brightness); + config->writeEntry("Performance", do_performance); + config->writeEntry("PerformanceValue", val_performance); + config->writeEntry("Throttle", do_throttle); + config->writeEntry("ThrottleValue", val_throttle); + config->writeEntry("RunCommandPath", runcommand_val); + config->writeEntry("PlaySoundPath", sound_val); + config->sync(); + wake_laptop_daemon(); +} + +void WarningConfig::load() +{ + load( false ); +} + +void WarningConfig::load(bool useDefaults) +{ + if (config == NULL) + return; + my_load(0, useDefaults); + my_load(1, useDefaults); +} + +void WarningConfig::my_load(int x, bool useDefaults ) +{ + config->setReadDefaults( useDefaults ); + + // open the config file + if (!x) { + config->setGroup((type?"BatteryCritical":"BatteryLow")); + + if (config->group() == "BatteryLow") { + time_based_action_low = config->readBoolEntry("TimeBasedAction", true); + low_val_time = config->readNumEntry("LowValTime", 15); + low_val_percent = config->readNumEntry("LowValPercent", 7); + } else { + time_based_action_critical = config->readBoolEntry("TimeBasedAction", true); + critical_val_time = config->readNumEntry("CriticalValTime", 5); + critical_val_percent = config->readNumEntry("CriticalValPercent", 3); + } + runcommand = config->readBoolEntry("RunCommand", false); + playsound = config->readBoolEntry("PlaySound", false); + logout = config->readBoolEntry("Logout", false); + shutdown = config->readBoolEntry("Shutdown", false); + beep = config->readBoolEntry("SystemBeep", true); + notify = config->readBoolEntry("Notify", (type && checkSuspend ? false : true)); + do_suspend = config->readBoolEntry("Suspend", (type && checkSuspend ? true :false)); + do_standby = config->readBoolEntry("Standby", false); + do_hibernate = config->readBoolEntry("Hibernate", false); + do_brightness = config->readBoolEntry("Brightness", false); + val_brightness = config->readNumEntry("BrightnessValue", 255); + do_performance = config->readBoolEntry("Performance", false); + val_performance = config->readEntry("PerformanceValue", ""); + do_throttle = config->readBoolEntry("Throttle", false); + val_throttle = config->readEntry("ThrottleValue", ""); + runcommand_val = config->readEntry("RunCommandPath"); + sound_val = config->readEntry("PlaySoundPath"); + have_time = config->readNumEntry("HaveTime", 2); + if (laptop_portable::has_power_management()) + have_time = laptop_portable::has_battery_time(); + + } else + if (apm) { + checkRunCommand->setChecked(runcommand); + checkPlaySound->setChecked(playsound); + checkBeep->setChecked(beep); + if (checkBrightness) + checkBrightness->setChecked(do_brightness); + if (valueBrightness) { + valueBrightness->setValue(val_brightness); + valueBrightness->setEnabled(do_brightness); + } + if (performance) + performance->setChecked(do_performance); + if (performance_val) { + int ind = 0; + for (int i = 0; i < performance_val->count(); i++) + if (performance_val->text(i) == val_performance) { + ind = i; + break; + } + performance_val->setCurrentItem(ind); + performance_val->setEnabled(do_performance); + } + if (throttle) + throttle->setChecked(do_throttle); + if (throttle_val) { + int ind = 0; + for (int i = 0; i < throttle_val->count(); i++) + if (throttle_val->text(i) == val_throttle) { + ind = i; + break; + } + throttle_val->setCurrentItem(ind); + throttle_val->setEnabled(do_throttle); + } + + checkLogout->setChecked(logout); + checkNotify->setChecked(notify); + checkShutdown->setChecked(shutdown); + if (checkHibernate) { + checkHibernate->setChecked(do_hibernate); + } else { + do_hibernate = 0; + } + if (checkStandby) { + checkStandby->setChecked(do_standby); + } else { + do_standby = 0; + } + if (checkSuspend) { + checkSuspend->setChecked(do_suspend); + } else { + do_suspend = 0; + } + checkNone->setChecked(!do_suspend&!do_standby&!do_hibernate&!logout&!shutdown); + editRunCommand->setURL(runcommand_val); + + if(type) { + checkCriticalTime->setChecked(time_based_action_critical ? true : false); + editCriticalTime->setValue(critical_val_time); + checkCriticalPercent->setChecked(time_based_action_critical ? false : true); + editCriticalPercent->setValue(critical_val_percent); + } else { + checkLowTime->setChecked(time_based_action_low ? true : false); + editLowTime->setValue(low_val_time); + checkLowPercent->setChecked(time_based_action_low ? false : true); + editLowPercent->setValue(low_val_percent); + } + + editPlaySound->setURL(sound_val); + } + emit changed(useDefaults); +} + +void WarningConfig::defaults() +{ + load( true ); +} + + +void WarningConfig::configChanged() +{ + emit changed(true); +} + + +#if 0 +void WarningConfig::enableRunCommand(bool enable) +{ + editRunCommand->setEnabled(enable); + buttonBrowseRunCommand->setEnabled(enable); + configChanged(); +} + +void WarningConfig::enablePlaySound(bool enable) +{ + editPlaySound->setEnabled(enable); + buttonBrowsePlaySound->setEnabled(enable); + configChanged(); +} + +void WarningConfig::browseRunCommand() +{ + KURL url = KFileDialog::getOpenURL(QString::null, QString::null, this ); + + if( url.isEmpty() ) + return; + + if( !url.isLocalFile() ) + { + KMessageBox::sorry( 0L, i18n( "Only local files are currently supported." ) ); + return; + } + + editRunCommand->setText( url.path() ); + configChanged(); +} + +void WarningConfig::browsePlaySound() +{ + KURL url = KFileDialog::getOpenURL(QString::null, QString::null, this ); + + if( url.isEmpty() ) + return; + + if( !url.isLocalFile() ) + { + KMessageBox::sorry( 0L, i18n( "Only local files are currently supported." ) ); + return; + } + + editPlaySound->setText( url.path() ); + configChanged(); +} +#endif + +QString WarningConfig::quickHelp() const +{ + return i18n("

Low battery Warning

This module allows you to " + "set an alarm in case your battery's charge is about to run out."); +} + +#include "warning.moc" diff --git a/klaptopdaemon/warning.h b/klaptopdaemon/warning.h new file mode 100644 index 0000000..3eb1b04 --- /dev/null +++ b/klaptopdaemon/warning.h @@ -0,0 +1,106 @@ +/* + * warning.h + * + * Copyright (c) 1999 Paul Campbell + * Copyright (c) 2002 Marc Mutz + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifndef __WARNINGCONFIG_H__ +#define __WARNINGCONFIG_H__ + +#include +#include + +class QWidget; +class KConfig; +class KURLRequester; +class QCheckBox; +class QRadioButton; +class QSpinBox; +class QSlider; +class KComboBox; + +class WarningConfig : public KCModule +{ + Q_OBJECT +public: + WarningConfig(int x, QWidget *parent=0, const char* name=0); + ~WarningConfig(); + void save( void ); + void load(); + void load(bool useDefaults); + void defaults(); + + virtual QString quickHelp() const; + +private slots: + void configChanged(); + void brightness_changed(bool v); + void throttle_changed(bool v); + void performance_changed(bool v); + void checkLowTimeChanged(bool state); + void checkLowPercentChanged(bool state); + void checkCriticalTimeChanged(bool state); + void checkCriticalPercentChanged(bool state); + +private: + void my_load(int x, bool useDefaults=false ); + + KConfig *config; + + KURLRequester* editRunCommand; + KURLRequester* editPlaySound; + QCheckBox* checkLowTime; + QCheckBox* checkLowPercent; + QCheckBox* checkCriticalTime; + QCheckBox* checkCriticalPercent; + QSpinBox* editLowTime; + QSpinBox* editLowPercent; + QSpinBox* editCriticalTime; + QSpinBox* editCriticalPercent; + + QCheckBox *checkRunCommand; + QCheckBox *checkPlaySound; + QCheckBox *checkBeep; + QCheckBox *checkNotify; + QCheckBox *checkBrightness; + QSlider *valueBrightness; + QCheckBox *performance, *throttle; + KComboBox *performance_val, *throttle_val; + QRadioButton *checkNone; + QRadioButton *checkShutdown; + QRadioButton *checkLogout; + QRadioButton *checkSuspend; + QRadioButton *checkStandby; + QRadioButton *checkHibernate; + + bool apm, runcommand, playsound, beep, notify, do_suspend, do_standby, do_hibernate, logout, shutdown, do_brightness; + bool do_performance, do_throttle; + bool time_based_action_low, time_based_action_critical; + QString val_performance, val_throttle; + int val_brightness; + QString runcommand_val, sound_val; + int low_val_time, low_val_percent, critical_val_time, critical_val_percent; + int have_time, type; +}; + +#endif + diff --git a/klaptopdaemon/xautolock.cc b/klaptopdaemon/xautolock.cc new file mode 100644 index 0000000..4f856e1 --- /dev/null +++ b/klaptopdaemon/xautolock.cc @@ -0,0 +1,277 @@ +//---------------------------------------------------------------------------- +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones +// Copyright (c) 2003 Lubos Lunak +// +// KDE screensaver engine +// + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "xautolock.h" +#include "xautolock.moc" + +#include +#include + +#include +#include +#include +#include "xautolock_c.h" + +#ifdef HAVE_DPMS +extern "C" { +#include +#ifndef Bool +#define Bool BOOL +#endif +#include + +#ifndef HAVE_DPMSINFO_PROTO +Status DPMSInfo ( Display *, CARD16 *, BOOL * ); +#endif +} +#endif + +int xautolock_useXidle = 0; +int xautolock_useMit = 0; +xautolock_corner_t xautolock_corners[ 4 ]; + +static XAutoLock* self = NULL; + +static int catchFalseAlarms(Display *, XErrorEvent *) +{ + return 0; +} + +//=========================================================================== +// +// Detect user inactivity. +// Named XAutoLock after the program that it is based on. +// +XAutoLock::XAutoLock() +{ + self = this; + int dummy = 0; + dummy = dummy; // shut up + xautolock_useXidle = 0; + xautolock_useMit = 0; +#ifdef HAVE_XIDLE + useXidle = XidleQueryExtension( qt_xdisplay(), &dummy, &dummy ); +#endif +#ifdef HAVE_XSCREENSAVER + if( !xautolock_useXidle ) + xautolock_useMit = XScreenSaverQueryExtension( qt_xdisplay(), &dummy, &dummy ); +#endif + if( !xautolock_useXidle && !xautolock_useMit ) + { + kapp->installX11EventFilter( this ); + int (*oldHandler)(Display *, XErrorEvent *); + oldHandler = XSetErrorHandler(catchFalseAlarms); + XSync(qt_xdisplay(), False ); + xautolock_initDiy( qt_xdisplay()); + XSync(qt_xdisplay(), False ); + XSetErrorHandler(oldHandler); + } + + mTimeout = DEFAULT_TIMEOUT; + mDPMS = true; + resetTrigger(); + + time(&mLastTimeout); + mActive = false; + + mTimerId = startTimer( CHECK_INTERVAL ); + +} + +//--------------------------------------------------------------------------- +// +// Destructor. +// +XAutoLock::~XAutoLock() +{ + self = NULL; +} + +//--------------------------------------------------------------------------- +// +// The time in seconds of continuous inactivity. +// +void XAutoLock::setTimeout(int t) +{ + mTimeout = t; + resetTrigger(); +} + +void XAutoLock::setDPMS(bool s) +{ + mDPMS = s; +} + +//--------------------------------------------------------------------------- +// +// Start watching Activity +// +void XAutoLock::start() +{ + resetTrigger(); + time(&mLastTimeout); + mActive = true; +} + +//--------------------------------------------------------------------------- +// +// Stop watching Activity +// +void XAutoLock::stop() +{ + mActive = false; +} + +//--------------------------------------------------------------------------- +// +// Reset the trigger time. +// +void XAutoLock::resetTrigger() +{ + mTrigger = time(0) + mTimeout; +} + +//--------------------------------------------------------------------------- +// +// Move the trigger time in order to postpone (repeat) emitting of timeout(). +// +void XAutoLock::postpone() +{ + mTrigger = time(0) + 60; // delay by 60sec +} + +//--------------------------------------------------------------------------- +// +// Set the remaining time to 't', if it's shorter than already set. +// +void XAutoLock::setTrigger( time_t t ) +{ + if( t < mTrigger ) + mTrigger = t; +} + +//--------------------------------------------------------------------------- +// +// Process new windows and check the mouse. +// +void XAutoLock::timerEvent(QTimerEvent *ev) +{ + if (ev->timerId() != mTimerId) + { + return; + } + + int (*oldHandler)(Display *, XErrorEvent *) = NULL; + if( !xautolock_useXidle && !xautolock_useMit ) + { // only the diy way needs special X handler + XSync( qt_xdisplay(), False ); + oldHandler = XSetErrorHandler(catchFalseAlarms); + } + + xautolock_processQueue(); + + time_t now = time(0); + if ((now > mLastTimeout && now - mLastTimeout > TIME_CHANGE_LIMIT) || + (mLastTimeout > now && mLastTimeout - now > TIME_CHANGE_LIMIT+1)) + { + /* the time has changed in one large jump. This could be because + the date was changed, or the machine was suspended. We'll just + reset the triger. */ + resetTrigger(); + } + + mLastTimeout = now; + + xautolock_queryIdleTime( qt_xdisplay()); + xautolock_queryPointer( qt_xdisplay()); + + if( !xautolock_useXidle && !xautolock_useMit ) + XSetErrorHandler(oldHandler); + + bool activate = false; + + //kdDebug() << now << " " << mTrigger << endl; + if (now >= mTrigger) + { + resetTrigger(); + activate = true; + } + +#ifdef HAVE_DPMS + BOOL on; + CARD16 state; + DPMSInfo( qt_xdisplay(), &state, &on ); + + //kdDebug() << "DPMSInfo " << state << " " << on << endl; + // If DPMS is active, it makes XScreenSaverQueryInfo() report idle time + // that is always smaller than DPMS timeout (X bug I guess). So if DPMS + // saving is active, simply always activate our saving too, otherwise + // this could prevent locking from working. + if(state == DPMSModeStandby || state == DPMSModeSuspend || state == DPMSModeOff) + activate = true; + if(!on && mDPMS) { + activate = false; + resetTrigger(); + } +#endif + +#ifdef HAVE_XSCREENSAVER + static XScreenSaverInfo* mitInfo = 0; + if (!mitInfo) mitInfo = XScreenSaverAllocInfo (); + if (XScreenSaverQueryInfo (qt_xdisplay(), DefaultRootWindow (qt_xdisplay()), mitInfo)) { + //kdDebug() << "XScreenSaverQueryInfo " << mitInfo->state << " " << ScreenSaverDisabled << endl; + if (mitInfo->state == ScreenSaverDisabled) + activate = false; + } +#endif + + if(mActive && activate) + emit timeout(); +} + +bool XAutoLock::x11Event( XEvent* ev ) +{ + xautolock_processEvent( ev ); +// don't futher process key events that were received only because XAutoLock wants them + if( ev->type == KeyPress && !ev->xkey.send_event + && !xautolock_useXidle && !xautolock_useMit + && !QWidget::find( ev->xkey.window )) + return true; + return false; +} + +bool XAutoLock::ignoreWindow( WId w ) +{ + if( w != qt_xrootwin() && QWidget::find( w )) + return true; + return false; +} + +extern "C" +void xautolock_resetTriggers() +{ + self->resetTrigger(); +} + +extern "C" +void xautolock_setTrigger( time_t t ) +{ + self->setTrigger( t ); +} + +extern "C" +int xautolock_ignoreWindow( Window w ) +{ + return self->ignoreWindow( w ); +} diff --git a/klaptopdaemon/xautolock.h b/klaptopdaemon/xautolock.h new file mode 100644 index 0000000..aa618f2 --- /dev/null +++ b/klaptopdaemon/xautolock.h @@ -0,0 +1,77 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 1999 Martin R. Jones +// + +#ifndef __XAUTOLOCK_H__ +#define __XAUTOLOCK_H__ + +#include + +#include + +//=========================================================================== +// +// Detect user inactivity. +// Named XAutoLock after the program that it is based on. +// +class XAutoLock : public QWidget +{ + Q_OBJECT +public: + XAutoLock(); + ~XAutoLock(); + + //----------------------------------------------------------------------- + // + // The time in seconds of continuous inactivity. + // + void setTimeout(int t); + + void setDPMS(bool s); + + //----------------------------------------------------------------------- + // + // Start watching Activity + // + void start(); + + //----------------------------------------------------------------------- + // + // Stop watching Activity + // + void stop(); + + //----------------------------------------------------------------------- + // + // Should be called only from a slot connected to the timeout() signal. Will + // result in the timeout() signal being emitted again with a delay (i.e. postponed). + // + void postpone(); + + // internal + void resetTrigger(); + // internal + void setTrigger( time_t ); + // internal + bool ignoreWindow( WId ); + +signals: + void timeout(); + +protected: + virtual void timerEvent(QTimerEvent *ev); + virtual bool x11Event( XEvent* ); + +protected: + int mTimerId; + int mTimeout; + time_t mTrigger; + bool mActive; + time_t mLastTimeout; + bool mDPMS; +}; + +#endif diff --git a/klaptopdaemon/xautolock_c.h b/klaptopdaemon/xautolock_c.h new file mode 100644 index 0000000..a53ad93 --- /dev/null +++ b/klaptopdaemon/xautolock_c.h @@ -0,0 +1,76 @@ +/***************************************************************************** + * + * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) + * + * Content: This file is part of version 2.x of xautolock. It takes care + * of most OS dependencies, and defines the program's default + * settings. + * + * Please send bug reports etc. to eyckmans@imec.be. + * + * -------------------------------------------------------------------------- + * + * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans. + * + * Versions 2.0 and above of xautolock are available under version 2 of the + * GNU GPL. Earlier versions are available under other conditions. For more + * information, see the License file. + * + *****************************************************************************/ + +#ifndef __xautolock_c_h +#define __xautolock_c_h + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_XSCREENSAVER +#define HasScreenSaver +#include +#endif + +/* I'd first need to get my hands on this */ +#undef HAVE_XIDLE +#undef HasXidle + +#define DEFAULT_TIMEOUT 600 + +#define CHECK_INTERVAL 5000 /* ms */ + +#define CREATION_DELAY 30 /* should be > 10 and + < min (45,(MIN_MINUTES*30)) */ +#define TIME_CHANGE_LIMIT 120 /* if the time changes by more + than x secs then we will + assume someone has changed + date or machine has suspended */ + +#define cornerSize 5 + +#define cornerDelay 5 + +#define cornerRedelay 5 + +typedef enum { ca_nothing, ca_dontLock, ca_forceLock } xautolock_corner_t; + +#ifdef __cplusplus +extern "C" +{ +#endif +void xautolock_processEvent( XEvent* ev ); +void xautolock_queryIdleTime( Display* d); +void xautolock_processQueue( void ); +void xautolock_queryPointer (Display* d); +void xautolock_initDiy (Display* d); +void xautolock_resetTriggers( void ); +void xautolock_setTrigger( time_t ); +int xautolock_ignoreWindow( Window ); +extern int xautolock_useXidle; +extern int xautolock_useMit; +extern xautolock_corner_t xautolock_corners[ 4 ]; +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/klaptopdaemon/xautolock_diy.c b/klaptopdaemon/xautolock_diy.c new file mode 100644 index 0000000..b9df2f8 --- /dev/null +++ b/klaptopdaemon/xautolock_diy.c @@ -0,0 +1,289 @@ +/***************************************************************************** + * + * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) + * + * Content: This file is part of version 2.x of xautolock. It implements + * the stuff used when the program is not using a screen saver + * extension and thus has to use the good old "do it yourself" + * approach for detecting user activity. + * + * The basic idea is that we initially traverse the window tree, + * selecting SubstructureNotify on all windows and adding each + * window to a temporary list. About +- 30 seconds later, we + * scan this list, now asking for KeyPress events. The delay + * is needed in order to interfere as little as possible with + * the event propagation mechanism. Whenever a new window is + * created by an application, a similar process takes place. + * + * Please send bug reports etc. to eyckmans@imec.be. + * + * -------------------------------------------------------------------------- + * + * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans. + * + * Versions 2.0 and above of xautolock are available under version 2 of the + * GNU GPL. Earlier versions are available under other conditions. For more + * information, see the License file. + * + *****************************************************************************/ + +#include +#include +#include + +#include "xautolock_c.h" + +static void selectEvents (Window window, Bool substructureOnly); + +/* + * Window queue management. + */ +typedef struct item +{ + Window window; + time_t creationtime; + struct item* next; +} xautolock_anItem, *xautolock_item; + +static struct +{ + Display* display; + struct item* head; + struct item* tail; +} queue; + +static void +addToQueue (Window window) +{ + xautolock_item newItem = malloc(sizeof(xautolock_anItem)); + + newItem->window = window; + newItem->creationtime = time (0); + newItem->next = 0; + + if (!queue.head) queue.head = newItem; + if ( queue.tail) queue.tail->next = newItem; + + queue.tail = newItem; +} + +static void +processQueue (time_t age) +{ + if (queue.head) + { + time_t now = time (0); + xautolock_item current = queue.head; + + while (current && current->creationtime + age < now) + { + selectEvents (current->window, False); + queue.head = current->next; + free (current); + current = queue.head; + } + + if (!queue.head) queue.tail = 0; + } +} + +/* + * Function for selecting all interesting events on a given + * (tree of) window(s). + */ +static void +selectEvents (Window window, Bool substructureOnly) +{ + Window root; /* root window of the window */ + Window parent; /* parent of the window */ + Window* children; /* children of the window */ + unsigned nofChildren = 0; /* number of children */ + unsigned i; /* loop counter */ + XWindowAttributes attribs; /* attributes of the window */ + + if( xautolock_ignoreWindow( window )) + return; + /* + * Start by querying the server about the root and parent windows. + */ + if (!XQueryTree (queue.display, window, &root, &parent, + &children, &nofChildren)) + { + return; + } + + if (nofChildren) (void) XFree ((char*) children); + + /* + * Build the appropriate event mask. The basic idea is that we don't + * want to interfere with the normal event propagation mechanism if + * we don't have to. + * + * On the root window, we need to ask for both substructureNotify + * and KeyPress events. On all other windows, we always need + * substructureNotify, but only need Keypress if some other client + * also asked for them, or if they are not being propagated up the + * window tree. + */ +#if 0 + if (substructureOnly) + { + (void) XSelectInput (queue.display, window, SubstructureNotifyMask); + } + else + { + if (parent == None) /* the *real* rootwindow */ + { + attribs.all_event_masks = + attribs.do_not_propagate_mask = KeyPressMask; + } + else if (!XGetWindowAttributes (queue.display, window, &attribs)) +#else + { + if (!XGetWindowAttributes (queue.display, window, &attribs)) +#endif + { + return; + } + +#if 0 + (void) XSelectInput (queue.display, window, + SubstructureNotifyMask + | ( ( attribs.all_event_masks + | attribs.do_not_propagate_mask) + & KeyPressMask)); +#else + { + int mask = SubstructureNotifyMask | attribs.your_event_mask; + if( !substructureOnly ) + { + mask |= ( ( attribs.all_event_masks + | attribs.do_not_propagate_mask) + & KeyPressMask ); + } + (void) XSelectInput (queue.display, window, mask ); + } +#endif + + } + + /* + * Now ask for the list of children again, since it might have changed + * in between the last time and us selecting SubstructureNotifyMask. + * + * There is a (very small) chance that we might process a subtree twice: + * child windows that have been created after our XSelectinput() has + * been processed but before we get to the XQueryTree() bit will be + * in this situation. This is harmless. It could be avoided by using + * XGrabServer(), but that'd be an impolite thing to do, and since it + * isn't required... + */ + if (!XQueryTree (queue.display, window, &root, &parent, + &children, &nofChildren)) + { + return; + } + + /* + * Now do the same thing for all children. + */ + for (i = 0; i < nofChildren; ++i) + { + selectEvents (children[i], substructureOnly); + } + + if (nofChildren) (void) XFree ((char*) children); +} + +#if 0 +/* + * Function for processing any events that have come in since + * last time. It is crucial that this function does not block + * in case nothing interesting happened. + */ +void +processEvents (void) +{ + while (XPending (queue.display)) + { + XEvent event; + + if (XCheckMaskEvent (queue.display, SubstructureNotifyMask, &event)) + { + if (event.type == CreateNotify) + { + addToQueue (event.xcreatewindow.window); + } + } + else + { + (void) XNextEvent (queue.display, &event); + } + + /* + * Reset the triggers if and only if the event is a + * KeyPress event *and* was not generated by XSendEvent(). + */ + if ( event.type == KeyPress + && !event.xany.send_event) + { + resetTriggers (); + } + } + + /* + * Check the window queue for entries that are older than + * CREATION_DELAY seconds. + */ + processQueue ((time_t) CREATION_DELAY); +} +#else +void xautolock_processEvent( XEvent* event ) +{ + if (event->type == CreateNotify) + { + addToQueue (event->xcreatewindow.window); + } + /* + * Reset the triggers if and only if the event is a + * KeyPress event *and* was not generated by XSendEvent(). + */ + if ( event->type == KeyPress + && !event->xany.send_event) + { + xautolock_resetTriggers (); + } +} + +void xautolock_processQueue() +{ + /* + * Check the window queue for entries that are older than + * CREATION_DELAY seconds. + */ + processQueue ((time_t) CREATION_DELAY); +} +#endif + + +/* + * Function for initialising the whole shebang. + */ +void +xautolock_initDiy (Display* d) +{ + int s; + + queue.display = d; + queue.tail = 0; + queue.head = 0; + + for (s = -1; ++s < ScreenCount (d); ) + { + Window root = RootWindowOfScreen (ScreenOfDisplay (d, s)); + addToQueue (root); +#if 0 + selectEvents (root, True); +#endif + } +} diff --git a/klaptopdaemon/xautolock_engine.c b/klaptopdaemon/xautolock_engine.c new file mode 100644 index 0000000..62f968a --- /dev/null +++ b/klaptopdaemon/xautolock_engine.c @@ -0,0 +1,419 @@ +/***************************************************************************** + * + * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) + * + * Content: This file is part of version 2.x of xautolock. It implements + * the program's core functions. + * + * Please send bug reports etc. to eyckmans@imec.be. + * + * -------------------------------------------------------------------------- + * + * Copyright 1990,1992-1999,2001-2002 by Stefan De Troch and Michel Eyckmans. + * + * Versions 2.0 and above of xautolock are available under version 2 of the + * GNU GPL. Earlier versions are available under other conditions. For more + * information, see the License file. + * + *****************************************************************************/ + +#include +#include + +#include "xautolock_c.h" + +/* + * Function for querying the idle time from the server. + * Only used if either the Xidle or the Xscreensaver + * extension is present. + */ +void +xautolock_queryIdleTime (Display* d) +{ + Time idleTime = 0; /* millisecs since last input event */ + +#ifdef HasXidle + if (xautolock_useXidle) + { + XGetIdleTime (d, &idleTime); + } + else +#endif /* HasXIdle */ + { +#ifdef HasScreenSaver + if( xautolock_useMit ) + { + static XScreenSaverInfo* mitInfo = 0; + if (!mitInfo) mitInfo = XScreenSaverAllocInfo (); + XScreenSaverQueryInfo (d, DefaultRootWindow (d), mitInfo); + idleTime = mitInfo->idle; + } + else +#endif /* HasScreenSaver */ + { + d = d; /* shut up */ + return; /* DIY */ + } + } + + if (idleTime < CHECK_INTERVAL ) + { + xautolock_resetTriggers (); + } +} + +/* + * Function for monitoring pointer movements. This implements the + * `corners' feature and as a side effect also tracks pointer + * related user activity. The latter actually is only needed when + * we're using the DIY mode of operations, but it's much simpler + * to do it unconditionally. + */ +void +xautolock_queryPointer (Display* d) +{ + Window dummyWin; /* as it says */ + int dummyInt; /* as it says */ + unsigned mask; /* modifier mask */ + int rootX; /* as it says */ + int rootY; /* as it says */ + int corner; /* corner index */ + time_t now; /* as it says */ + time_t newTrigger; /* temporary storage */ + int i; /* loop counter */ + static Window root; /* root window the pointer is on */ + static Screen* screen; /* screen the pointer is on */ + static unsigned prevMask = 0; /* as it says */ + static int prevRootX = -1; /* as it says */ + static int prevRootY = -1; /* as it says */ + static Bool firstCall = True; /* as it says */ + + /* + * Have a guess... + */ + if (firstCall) + { + firstCall = False; + root = DefaultRootWindow (d); + screen = ScreenOfDisplay (d, DefaultScreen (d)); + } + + /* + * Find out whether the pointer has moved. Using XQueryPointer for this + * is gross, but it also is the only way never to mess up propagation + * of pointer events. + */ + if (!XQueryPointer (d, root, &root, &dummyWin, &rootX, &rootY, + &dummyInt, &dummyInt, &mask)) + { + /* + * Pointer has moved to another screen, so let's find out which one. + */ + for (i = -1; ++i < ScreenCount (d); ) + { + if (root == RootWindow (d, i)) + { + screen = ScreenOfDisplay (d, i); + break; + } + } + } + + if ( rootX == prevRootX + && rootY == prevRootY + && mask == prevMask) + { + xautolock_corner_t* corners = xautolock_corners; + /* + * If the pointer has not moved since the previous call and + * is inside one of the 4 corners, we act according to the + * contents of the "corners" array. + * + * If rootX and rootY are less than zero, don't lock even if + * ca_forceLock is set in the upper-left corner. Why? 'cause + * on initial server startup, if (and only if) the pointer is + * never moved, XQueryPointer() can return values less than + * zero (only some servers, Openwindows 2.0 and 3.0 in + * particular). + */ + if ( (corner = 0, + rootX <= cornerSize && rootX >= 0 + && rootY <= cornerSize && rootY >= 0) + || (corner++, + rootX >= WidthOfScreen (screen) - cornerSize - 1 + && rootY <= cornerSize) + || (corner++, + rootX <= cornerSize + && rootY >= HeightOfScreen (screen) - cornerSize - 1) + || (corner++, + rootX >= WidthOfScreen (screen) - cornerSize - 1 + && rootY >= HeightOfScreen (screen) - cornerSize - 1)) + { + now = time (0); + + switch (corners[corner]) + { + case ca_forceLock: +#if 0 + newTrigger = now + (useRedelay ? cornerRedelay : cornerDelay) - 1; +#else + newTrigger = now + 2 - 1; +#endif + +#if 0 + if (newTrigger < lockTrigger) + { + setLockTrigger (newTrigger - now); + } +#else + xautolock_setTrigger( newTrigger ); +#endif + break; + + case ca_dontLock: + xautolock_resetTriggers (); + +#ifdef __GNUC__ + default: ; /* Makes gcc -Wall shut up. */ +#endif /* __GNUC__ */ + } + } + } + else + { +#if 0 + useRedelay = False; +#endif + prevRootX = rootX; + prevRootY = rootY; + prevMask = mask; + + xautolock_resetTriggers (); + } +} + +#if 0 +/* + * Support for deciding whether to lock or kill. + */ +void +evaluateTriggers (Display* d) +{ + static time_t prevNotification = 0; + time_t now = 0; + + /* + * Obvious things first. + * + * The triggers are being moved all the time while in disabled + * mode in order to make absolutely sure we cannot run into + * trouble by an enable message coming in at an odd moment. + * Otherwise we possibly might lock or kill too soon. + */ + if (disabled) + { + resetTriggers (); + } + + /* + * Next, wait for (or kill, if we were so told) the previous + * locker (if any). Note that this must also be done while in + * disabled mode. Not only to avoid a potential zombie proces + * hanging around until we are re-enabled, but also to prevent + * us from incorrectly setting a kill trigger at the moment + * when we are finally re-enabled. + */ +#ifdef VMS + if (vmsStatus == 0) + { +#else /* VMS */ + if (lockerPid) + { +#if !defined (UTEKV) && !defined (SYSV) && !defined (SVR4) + union wait status; /* childs process status */ +#else /* !UTEKV && !SYSV && !SVR4 */ + int status = 0; /* childs process status */ +#endif /* !UTEKV && !SYSV && !SVR4 */ + + if (unlockNow && !disabled) + { + (void) kill (lockerPid, SIGTERM); + } + +#if !defined (UTEKV) && !defined (SYSV) && !defined (SVR4) + if (wait3 (&status, WNOHANG, 0)) +#else /* !UTEKV && !SYSV && !SVR4 */ + if (waitpid (-1, &status, WNOHANG)) +#endif /* !UTEKV && !SYSV && !SVR4 */ + { + /* + * If the locker exited normally, we disable any pending kill + * trigger. Otherwise, we assume that it either has crashed or + * was not able to lock the display because of an existing + * locker (which may have been started manually). In both of + * the later cases, disabling the kill trigger would open a + * loop hole. + */ + if ( WIFEXITED (status) + && WEXITSTATUS (status) == EXIT_SUCCESS) + { + disableKillTrigger (); + } + + useRedelay = True; + lockerPid = 0; + } +#endif /* VMS */ + + setLockTrigger (lockTime); + + /* + * No return here! The pointer may be sitting in a corner, while + * parameter settings may be such that we need to start another + * locker without further delay. If you think this cannot happen, + * consider the case in which the locker simply crashed. + */ + } + + unlockNow = False; + + /* + * Note that the above lot needs to be done even when we're in + * disabled mode, since we may have entered said mode with an + * active locker around. + */ + if (disabled) return; + + /* + * Is it time to run the killer command? + */ + now = time (0); + + if (killTrigger && now >= killTrigger) + { + /* + * There is a dirty trick here. On the one hand, we don't want + * to block until the killer returns, but on the other one + * we don't want to have it interfere with the wait() stuff we + * do to keep track of the locker. To obtain both, the killer + * command has already been patched by KillerChecker() so that + * it gets backgrounded by the shell started by system(). + * + * For the time being, VMS users are out of luck: their xautolock + * will indeed block until the killer returns. + */ + (void) system (killer); + setKillTrigger (killTime); + } + + /* + * Now trigger the notifier if required. + */ + if ( notifyLock + && now + notifyMargin >= lockTrigger + && prevNotification < now - notifyMargin - 1) + { + if (notifierSpecified) + { + /* + * Here we use the same dirty trick as for the killer command. + */ + (void) system (notifier); + } + else + { + (void) XBell (d, bellPercent); + (void) XSync (d, 0); + } + + prevNotification = now; + } + + /* + * Finally fire up the locker if time has somehow come. + */ + if ( lockNow + || now >= lockTrigger) + { +#ifdef VMS + if (vmsStatus != 0) +#else /* VMS */ + if (!lockerPid) +#endif /* VMS */ + { + switch (lockerPid = vfork ()) + { + case -1: + lockerPid = 0; + break; + + case 0: + (void) close (ConnectionNumber (d)); +#ifdef VMS + vmsStatus = 0; + lockerPid = lib$spawn ((lockNow ? &nowLockerDescr : &lockerDescr), + 0, 0, &1, 0, 0, &vmsStatus); + + if (!(lockerPid & 1)) exit (lockerPid); + +#ifdef SLOW_VMS + (void) sleep (SLOW_VMS_DELAY); +#endif /* SLOW_VMS */ +#else /* VMS */ + (void) execl ("/bin/sh", "/bin/sh", "-c", + (lockNow ? nowLocker : locker), 0); +#endif /* VMS */ + _exit (EXIT_FAILURE); + + default: + /* + * In general xautolock should keep its fingers off the real + * screensaver because no universally acceptable policy can + * be defined. In no case should it decide to disable or enable + * it all by itself. Setting the screensaver policy is something + * the locker should take care of. After all, xautolock is not + * supposed to know what the "locker" does and doesn't do. + * People might be using xautolock for totally different + * purposes (which, by the way, is why it will accept a + * different set of X resources after being renamed). + * + * Nevertheless, simply resetting the screensaver is a + * convenience action that aids many xlock users, and doesn't + * harm anyone (*). The problem with older versions of xlock + * is that they can be told to replace (= disable) the real + * screensaver, but forget to reset that same screensaver if + * it was already active at the time xlock starts. I guess + * xlock initially wasn't designed to be run without a user + * actually typing the comand ;-). + * + * (*) Well, at least it used not to harm anyone, but with the + * advent of DPMS monitors, it now can mess up the power + * saving setup. Hence we better make it optional. + * + * Also, some xlock versions also unconditionally call + * XResetScreenSaver, yielding the same kind of problems + * with DPMS that xautolock did. The latest and greatest + * xlocks also have a -resetsaver option for this very + * reason. You may want to upgrade. + */ + if (resetSaver) (void) XResetScreenSaver(d); + + setLockTrigger (lockTime); + (void) XSync (d,0); + } + + /* + * Once the locker is running, all that needs to be done is to + * set the killTrigger if needed. Notice that this must be done + * even if we actually failed to start the locker. Otherwise + * the error would "propagate" from one feature to another. + */ + if (killerSpecified) setKillTrigger (killTime); + + useRedelay = False; + } + + lockNow = False; + } +} +#endif diff --git a/kmilo/Makefile.am b/kmilo/Makefile.am new file mode 100644 index 0000000..9a0949a --- /dev/null +++ b/kmilo/Makefile.am @@ -0,0 +1,18 @@ +if include_kmilo_powerbook +POWERBOOK_SUBDIR=powerbook +endif + +if include_kmilo_pbb +POWERBOOK2_SUBDIR=powerbook2 +endif + +if include_kmilo_kvaio +KVAIO_SUBDIR=kmilo_kvaio +endif + +if include_kmilo_delli8k +KDELLI8k_SUBDIR=delli8k +endif + + +SUBDIRS=kmilod $(POWERBOOK_SUBDIR) $(POWERBOOK2_SUBDIR) $(KVAIO_SUBDIR) generic thinkpad asus $(KDELLI8k_SUBDIR) diff --git a/kmilo/README b/kmilo/README new file mode 100644 index 0000000..f05588f --- /dev/null +++ b/kmilo/README @@ -0,0 +1,17 @@ +This is a kded module that can be extended to support various types of hardware +input devices that exist, such as those on keyboards. + +It presently supports: +- Apple PowerBooks +- Sony Vaio Laptops (tested on Vaio PCG-GRX series) +- IBM Thinkpads +- Asus Laptops +- Dell laptops (see delli8k/README for models) + +The output device is skinnable, though not extensible by 3rd parties currently. +This will come in the future when the API is finalised. + +It also lacks very much functionality. Any input is appreciated. + +Header files are not presently installed in order to avoid committing to an API. + diff --git a/kmilo/TODO b/kmilo/TODO new file mode 100644 index 0000000..8a31d85 --- /dev/null +++ b/kmilo/TODO @@ -0,0 +1,7 @@ +- Configuration + +- Pluginify the skins + +- Support for more laptops, keyboards, etc. + +- Add a debug area diff --git a/kmilo/asus/Makefile.am b/kmilo/asus/Makefile.am new file mode 100644 index 0000000..39217c0 --- /dev/null +++ b/kmilo/asus/Makefile.am @@ -0,0 +1,37 @@ +# This file is part of the KDE project +# Copyright (C) 2003 George Staikos +# Copyright (C) 2004 Chris Howells +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +#SUBDIRS = . kcmthinkpad + +INCLUDES=-I$(srcdir)/../kmilod $(all_includes) + +kde_module_LTLIBRARIES = kmilo_asus.la + +kmilo_asus_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kmilo_asus_la_LIBADD = ../kmilod/libkmilo.la $(LIB_KIO) +kmilo_asus_la_SOURCES = asus.cpp +METASOURCES = AUTO + +noinst_HEADERS = asus.h + +services_DATA = kmilo_asus.desktop +servicesdir = $(kde_servicesdir)/kmilo + +messages: + $(XGETTEXT) $(asus_thinkpad_la_SOURCES) -o $(podir)/kmilo_asus.pot diff --git a/kmilo/asus/README b/kmilo/asus/README new file mode 100644 index 0000000..b375940 --- /dev/null +++ b/kmilo/asus/README @@ -0,0 +1,43 @@ +Asus Laptop plugin for KMilo + +Chris Howells + +About +----- + +This KMilo module, in conjunction with the Asus asus_acpi Linux kernel +module, allows some of the special keys on the keyboard of an Asus laptop to +be fully utilised. + +The asus_acpi kernel modules exports a control and monitoring interface +using the Linux kernel's /proc psuedo file system. + +The /proc file system +--------------------- + +/proc/acpi/asus/brn - Sets/gets the brightness of the LCD backlight +Values between 0 (most dim) and 15 (most bright) + +/proc/acpi/asus/info - Shows information about the laptop + +/proc/acpi/asus/lcd - Sets/gets whether the LCD is on or off +Values of 0 or 1 + +/proc/acpi/asus/disp - Sets/gets whether the LCD/VGA/TV out is used +Values of +0 - no display +1 - LCD only +2 - CRT only +3 - LCD + CRT +4 - TV out only +5 - LCD + TV out +6 - CRT + TV out +7 - LCD + CRT + TV out + +Changes +------- + +Todo +---- +* Support lcd and disp stuff +* Maybe support volume stuff diff --git a/kmilo/asus/asus.cpp b/kmilo/asus/asus.cpp new file mode 100644 index 0000000..e1fbfa0 --- /dev/null +++ b/kmilo/asus/asus.cpp @@ -0,0 +1,213 @@ +/* + This file is part of the KDE project + + Copyright (c) 2004 Chris Howells + Much code and ideas stolen from Jonathan Riddell's ThinkPad plugin + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; version + 2 of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include +#include + +#include +#include + +#include "kmilointerface.h" + +#include "asus.h" + +#ifdef Q_OS_FREEBSD +#include +#include +#endif + +#define ROUND(x) (int(x + 0.5)) + +namespace KMilo { + +AsusMonitor::AsusMonitor(QObject* parent, const char* name, const QStringList& args): Monitor(parent, name, args) +{ +} + +AsusMonitor::~AsusMonitor() +{ +} + +bool AsusMonitor::init() +{ + kdDebug() << "loading asus kmilo plugin" << endl; + +#ifdef Q_OS_FREEBSD + /* + * Check if the sysctls are in place by looking up their MIBs. + * Caching the MIBs results in a major speedup. + */ + size_t len = 4; + if ( sysctlnametomib("hw.acpi.asus.lcd_brightness", brightness_mib, &len) == -1 || + sysctlnametomib("hw.acpi.asus.lcd_backlight", backlight_mib, &len) == -1 || + sysctlnametomib("hw.acpi.asus.video_output", video_mib, &len) == -1 ) + { + kdDebug() << "The driver's sysctls don't seem to exist, check that the acpi_asus module is loaded" << endl; + return false; + } +#else + // we need to read the /proc file system and store the current values into a struct + QDir dir("/proc/acpi/asus"); + if (!dir.exists()) + { + kdDebug() << "/proc/acpi/asus doesn't exist, check that the asus_acpi module is loaded" << endl; + return false; + } +#endif + else + { + clearStruct(asus_state); + clearStruct(last_asus_state); + if (!readProc(&asus_state)) + { + return false; + } + } + + return true; +} + +Monitor::DisplayType AsusMonitor::poll() +{ + + // save last state and get new one + memcpy(&last_asus_state, &asus_state, sizeof(asus_state_struct)); + readProc(&asus_state); + + Monitor::DisplayType pollResult = None; + + if (last_asus_state.brightness != asus_state.brightness) + { + pollResult = Brightness; + float value = (float)asus_state.brightness / 15; + m_progress = ROUND(value * 100); + } + + /*if (last_asus_state.lcd != asus_state.lcd) + { + if (asus_state.lcd == 0) + { + _interface->displayText(i18n("Display changed: LCD off")); + } + else + { + _interface->displayText(i18n("Display changed: LCD on")); + } + }*/ + + if (last_asus_state.display != asus_state.display) + { + switch (asus_state.display) + { + case 0: + _interface->displayText(i18n("Display changed: off")); + break; + case 1: + _interface->displayText(i18n("Display changed: LCD on")); + break; + case 2: + _interface->displayText(i18n("Display changed: CRT on")); + break; + case 3: + _interface->displayText(i18n("Display changed: LCD and CRT on")); + break; + case 4: + _interface->displayText(i18n("Display changed: TV out on")); + break; + case 5: + _interface->displayText(i18n("Display changed: LCD and TV out on")); + break; + case 6: + _interface->displayText(i18n("Display changed: CRT and TV out on")); + break; + case 7: + _interface->displayText(i18n("Display changed: LCD, CRT and TV out on")); + break; + } + } + + return pollResult; +} + + +int AsusMonitor::progress() const +{ + return m_progress; +} + +bool AsusMonitor::readProc(asus_state_struct* asus_state) +{ +#ifdef Q_OS_FREEBSD + int value; + size_t value_len = sizeof(value); + + if ( sysctl(brightness_mib, 4, &value, &value_len, NULL, 0) != -1 ) + asus_state->brightness = value; + + if ( sysctl(backlight_mib, 4, &value, &value_len, NULL, 0) != -1 ) + asus_state->lcd = value; + + if ( sysctl(video_mib, 4, &value, &value_len, NULL, 0) != -1 ) + asus_state->display = value; +#else + asus_state->brightness = readProcEntry(QString("brn")); + //asus_state->lcd = readProcEntry(QString("lcd")); + //disabled because it does not yet work on my S5200N (asus_acpi bug) + //asus_state->display = readProcEntry(QString("disp")); + //FIXME +#endif + return true; +} + +int AsusMonitor::readProcEntry(const QString &name) +{ + QFile f(QString("/proc/acpi/asus/%1").arg(name).local8Bit()); + + if (f.open(IO_ReadOnly)) + { + QString line; + if (f.readLine(line, 1024) > 0) + { + line = line.stripWhiteSpace(); + int value = line.section(' ', 0, 0).toInt(); + if (value > 0) + { + return value; + } + } + } + return 0; +} + +void AsusMonitor::clearStruct(asus_state_struct& asus_state) +{ + asus_state.brightness = 0; + asus_state.lcd = 0; + asus_state.display = 0; +} + +} + +K_EXPORT_COMPONENT_FACTORY(kmilo_asus, KGenericFactory("kmilo_asus")) diff --git a/kmilo/asus/asus.h b/kmilo/asus/asus.h new file mode 100644 index 0000000..90361d8 --- /dev/null +++ b/kmilo/asus/asus.h @@ -0,0 +1,88 @@ +/* + This file is part of the KDE project + + Copyright (c) 2004 Chris Howells + Much code and ideas stolen from Jonathan Riddell's ThinkPad plugin + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; version + 2 of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef ASUS_H +#define ASUS_H + +#include +#include + +#include "monitor.h" + +namespace KMilo { + +typedef struct +{ + unsigned int brightness; + unsigned int lcd; + unsigned int display; +} asus_state_struct; + +/** + * KMilo plugin for Asus Laptops + */ +class AsusMonitor: public Monitor { + public: + AsusMonitor(QObject *parent, const char *name, const QStringList&); + virtual ~AsusMonitor(); + + /** + * Reimplemented from KMilo::Monitor. + * Loads configuration. + */ + virtual bool init(); + + /** + * Reimplemented from KMilo::Monitor. + * Called by KMilo, this checks the /proc file system and acts on any changes + */ + virtual DisplayType poll(); + + /** + * Reimplemented from KMilo::Monitor. + * Called by KMilo if poll() returns a brightness change. + * Returns the new brightness percentage. + */ + virtual int progress() const; + + private: + + int m_progress; + + asus_state_struct last_asus_state; + asus_state_struct asus_state; + + bool readProc(asus_state_struct* ); + int readProcEntry(const QString &); + + void clearStruct(asus_state_struct& asus_state); + +#ifdef Q_OS_FREEBSD + int brightness_mib[4]; + int backlight_mib[4]; + int video_mib[4]; +#endif +}; + +} // close namespace + +#endif diff --git a/kmilo/asus/kmilo_asus.desktop b/kmilo/asus/kmilo_asus.desktop new file mode 100644 index 0000000..5e662bb --- /dev/null +++ b/kmilo/asus/kmilo_asus.desktop @@ -0,0 +1,97 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KMilo Plugin +X-KDE-ModuleType=Plugin +Name=Asus Laptop Plugin +Name[ar]=ملحق حاسوب Asus المحمول +Name[br]=Lugent hezoug Asus +Name[bs]=Dodatak za Asus laptope +Name[ca]=Connector per portàtils Asus +Name[cs]=Asus Laptop modul +Name[da]=Asus bærbar plugin +Name[de]=Asus Notebook-Plugin +Name[el]=Πρόσθετο Sony Vaio +Name[es]=Extensión para el portátil Asus +Name[et]=Asuse sülearvuti plugin +Name[eu]=Asus Laptop plugina +Name[fa]=وصلۀ رایانۀ کیفی Asus +Name[fi]=Asus-kannettavan liitännäinen +Name[fr]=Module externe pour les portables Asus +Name[ga]=Breiseán Ríomhaire Glúine Asus +Name[he]=תוסף למחשבי ברכיים בעלי ASUS +Name[hu]=ASUS modul +Name[is]=Asus ferðatölvuíforrit +Name[it]=Plugin per portatili Asus +Name[ja]=Asus ラップトップ プラグイン +Name[ka]=Asus-ის ლეპტოპის მოდული +Name[kk]=Asus ноутбуктің модулі +Name[km]=កម្មវិធី​ជំនួយកុំព្យូទ័រ​យួរដៃ Asus +Name[lt]=Asus Laptop priedas +Name[nb]=Asus Laptop tillegg +Name[nds]=Asus-Klappreeknermoduul +Name[ne]=एसस ल्यापटप प्लगइन +Name[nl]=Asus Laptop-plugin +Name[nn]=Programtillegg for Asus-bærbare +Name[pa]=Asus ਲੈਪਟਾਪ ਪਲੱਗਿੰਨ +Name[pl]=Wtyczka laptopa Asus +Name[pt]='Plugin' para Portáteis Asus +Name[pt_BR]=Plugin para Laptops Asus +Name[ru]=Ноутбук Asus +Name[sk]=Modul pre Asus laptop +Name[sl]=Vstavek za prenosnik Asus +Name[sr]=Прикључак за Asus-ове лаптопе +Name[sr@Latn]=Priključak za Asus-ove laptope +Name[sv]=Insticksprogram för Asus bärbar dator +Name[ta]=Asus மடிக்கணினி சொருகுப்பொருள் +Name[tr]=Asus Dizüstü Bilgisayar Eklentisi +Name[uk]=Втулок лептопа Asus +Name[uz]=Asus laptopi uchun plagin +Name[uz@cyrillic]=Asus лаптопи учун плагин +Name[zh_CN]=华硕笔记本插件 +Name[zh_TW]=華碩筆記型電腦外掛程式 +Comment=Enables support for special Asus laptop keys +Comment[ar]=تمكّن الدعم لمفاتيح حاسوب Asus المحمول الخاصة +Comment[bg]=Тази приставка позволява поддръжката на специалните клавиши на Asus +Comment[bs]=Omogućuje podršku za posebne tipke na Asus laptopima +Comment[ca]=Habilita el funcionament per a tecles especials dels portàtils Asus +Comment[cs]=Umožňuje podporu speciálních kláves laptopů Asus +Comment[da]=Aktiverer støtte for specielle Asus bærbares taster +Comment[de]=Dieses Plugin aktiviert die Unterstützung für Sondertasten bei Asus-Tastaturen +Comment[el]=Ενεργοποιεί την υποστήριξη για ειδικά πλήκτρα φορητού Asus +Comment[es]=Activa el soporte de las teclas especiales del portátil Asus +Comment[et]=Võimaldab kasutada Asuse sülearvuti eriklahve +Comment[eu]=Asus eramangarrien tekla berezientzako euskarria gaitzen du +Comment[fa]=Asus فعال‌سازی پشتیبانی برای کلیدهای ویژۀ رایانۀ کیفی +Comment[fi]=Tämä liitännäinen mahdollistaa erikoisnäppäinten tuen Asus-merkkisille kannettaville tietokoneille. +Comment[fr]=Ce module active la gestion des touches spéciales des ordinateurs portables Asus +Comment[ga]=Tacaigh le heochracha speisialta ar ríomhairí glúine Asus +Comment[he]=מוסיף תמיכה בשביל מקשים מיוחדים של Asus +Comment[hu]=Ez a bővítőmodul lehetővé teszi az ASUS noteszgépek speciális billentyűinek használatát +Comment[is]=Virkjar stuðning fyrir sérhnappa Asus ferðavéla +Comment[it]=Abilita il supporto per i tasti speciali dei portatili Asus +Comment[ja]=Asus ラップトップの特殊キーをサポートします +Comment[ka]=რთავს Asus-ის ლეპტოპის სპეციალური კლავიშების მხარდაჭერას +Comment[kk]=Asus ноутбугінің арнаулы пернелерін қолдауы +Comment[km]=បើក​ការគាំទ្រ​គ្រាប់ចុច​កុំព្យូទ័រ​យួរដៃ Asus ពិសេស +Comment[lt]=Įgalina specialų Asus laptop raktų palaikymą +Comment[nb]=Muliggjør støtte for spesielle taster på Asus maskiner +Comment[nds]=Maakt de Sünnertasten-Ünnerstütten för Asus-Klappreekners an +Comment[ne]=विशेष ल्यापटप कुञ्जीका लागि समर्थन सक्षम पार्दछ +Comment[nl]=Activeert de ondersteuning voor speciale Asus-laptop-toetsen +Comment[nn]=Dette programtillegget gjer det mogleg å bruka spesialtastar på Asus-bærbare +Comment[pa]=ਖਾਸ Asus ਲੈਪਟਾਪ ਸਵਿੱਚਾਂ ਲਈ ਖਾਸ ਸਹਿਯੋਗ +Comment[pl]=Włącza obsługę specjalnych klawiszy laptopa Asus +Comment[pt]=Activa o suporte a teclas especiais dos portáteis Asus +Comment[pt_BR]=Habilita suporte à teclas especiais dos laptops Asus +Comment[ru]=Этот модуль поддерживает специальные клавиши ноутбука Asus +Comment[sk]=Povoľuje podporu pre špeciálne klávesy Asus laptopu +Comment[sl]=Omogoči podporo posebnim tipkam prenosnikov Asus +Comment[sr]=Подршка за посебне тастере на Asus-овим лаптопима +Comment[sr@Latn]=Podrška za posebne tastere na Asus-ovim laptopima +Comment[sv]=Aktiverar stöd för speciella tangenter på Asus bärbar dator +Comment[ta]=விசேஷ ஆஸ்சஸ் மடிக்கணினி விசைகளுக்கான ஆதரவை செயல்படுத்துகிறது +Comment[tr]=Asus dizüstü bilgisayarlar için özel tuş desteğini etkinleştirir +Comment[uk]=Уможливлює підтримку спеціальних клавіш для лептопа Asus +Comment[zh_CN]=启用华硕笔记本的特殊按键 +Comment[zh_TW]=開啟華碩筆記型電腦特殊鍵支援 +X-KDE-Library=kmilo_asus diff --git a/kmilo/configure.in.in b/kmilo/configure.in.in new file mode 100644 index 0000000..048c5b3 --- /dev/null +++ b/kmilo/configure.in.in @@ -0,0 +1,60 @@ + +################################################################## +## +## KMilo configure script +## George Staikos +## +################################################################## + +dnl --------------------------------------------------------------------- +dnl PowerBook IPC Library + +AC_ARG_WITH(powerbook, + [AC_HELP_STRING(--with-powerbook, + [enable support for PPC PowerBook @<:@default=check@:>@])], + [], with_powerbook=check) + +have_pbbipc="" +have_pbb="" +if test "x$with_powerbook" != xno; then + +KDE_CHECK_LIB(pbbipc, create_msgport, +[ +KEYBOARD_LIBS="-lpbbipc $KEYBOARD_LIBS" +AC_DEFINE(HAVE_POWERBOOK, 1, [If we have Apple PowerBook support]) +have_pbbipc=true +]) + +KDE_CHECK_LIB(pbb, init_libpbb, +[ +KEYBOARD_LIBS="-lpbb $KEYBOARD_LIBS" +AC_DEFINE(HAVE_POWERBOOK, 1, [If we have Apple PowerBook support]) +have_pbb=true +]) + +if test "x$with_powerbook" != xcheck && test -z "$have_pbbipc$have_pbb"; then + AC_MSG_ERROR([--with-powerbook was given, but test for libpbb failed]) +fi +fi + +AM_CONDITIONAL(include_kmilo_powerbook, test x$have_pbbipc = xtrue) +AM_CONDITIONAL(include_kmilo_pbb, test x$have_pbb = xtrue) + +dnl ----------------------------------------------------------------------- +dnl Check if Dell I8K module should be compiled (Linux systems only) +AC_MSG_CHECKING([if dellI8k KMilo module should be compiled]) +case "$host" in + *-*-linux*) kmilo_delli8k_compile=yes; UNAME='Linux' ;; + *) kmilo_delli8k_compile=no; UNAME='' ;; +esac + +AC_MSG_RESULT($kmilo_delli8k_compile) +AM_CONDITIONAL(include_kmilo_delli8k, test x$kmilo_delli8k_compile = xyes) +dnl ----------------------------------------------------------------------- + + + +AC_CHECK_HEADER(linux/sonypi.h, [have_sonypi=true]) +AM_CONDITIONAL(include_kmilo_kvaio, test x$have_sonypi = xtrue) + +AC_SUBST(KEYBOARD_LIBS) diff --git a/kmilo/delli8k/Makefile.am b/kmilo/delli8k/Makefile.am new file mode 100644 index 0000000..8b495c2 --- /dev/null +++ b/kmilo/delli8k/Makefile.am @@ -0,0 +1,36 @@ +# This file is part of the KDE project +# Copyright (C) 2003 George Staikos +# Copyright (C) 2004 Barry O'Donovan +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +INCLUDES=-I$(srcdir)/../kmilod $(all_includes) + +kde_module_LTLIBRARIES = kmilo_delli8k.la + +kmilo_delli8k_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kmilo_delli8k_la_LIBADD = ../kmilod/libkmilo.la $(LIB_KIO) +kmilo_delli8k_la_SOURCES = delli8k.cpp +METASOURCES = AUTO + +noinst_HEADERS = delli8k.h + +services_DATA = kmilo_delli8k.desktop +servicesdir = $(kde_servicesdir)/kmilo + +messages: + $(XGETTEXT) $(kmilo_delli8k_la_SOURCES) -o $(podir)/kmilo_delli8k.pot + diff --git a/kmilo/delli8k/README b/kmilo/delli8k/README new file mode 100644 index 0000000..80ae5b0 --- /dev/null +++ b/kmilo/delli8k/README @@ -0,0 +1,98 @@ +Dell Laptop Buttons Plug-in for KMilo + +Barry O'Donovan mail@barryodonovan.com, November 2004 +http://www.barryodonovan.com/ + +KMilo is a service for kded, the KDE daemon. KMilo is new to KDE 3.2. +It allows plug-ins which interact with the special buttons found on +some keyboards and laptops. + +This plug-in reads the /proc/i8k file that is created by the i8k kernel +module. If this file does not exist then the plug-in will not load. + +The code in this module is heavily based on: + - the Asus Laptop plug-in for KMilo by Chris Howells (howells@kde.org) + - the Thinkpad plug-in by Jonathan Riddell (jr@jriddell.org) + +Also, for the Dell specific implementations, code was taken from the +i8kutils package of Massimo Dal Zotto which can be +downloaded from http://www.debian.org/~dz/i8k/ + +LICENSE: + + delli8k - KMilo plug-in for special volume keys of Dell laptops + Copyright (C) 2004 Barry O'Donovan + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +COMPATIBILITY: + +This plug-in should work on any Linux distribution that has the i8k module +loaded or compiled into the kernel. Compatibility is really dependant on +the i8kutils package of Massimo Dal Zotto which can be +downloaded from http://www.debian.org/~dz/i8k/. Currently (20041122), this +should support: + + Inspiron 1100 (BIOS A06), one fan, no buttons + Inspiron 2650 (BIOS A05) + Inspiron 3700 (BIOS A15), no fan speed + Inspiron 3800 (BIOS A14), no fan speed + Inspiron 4000 (BIOS A10), no fan speed + Inspiron 4100 + Inspiron 4150 + Inspiron 5100 (BIOS A06), one fan, no buttons + Inspiron 5150 (BIOS A24), one fan, no buttons + Inspiron 8000 (BIOS A17) + Inspiron 8100 (BIOS A04) + Inspiron 8200 (BIOS A06) + Latitude C400 (BIOS A01) + Latitude C510 (BIOS A07) + Latitude C600 (BIOS A17) + Latitude C610 + Latitude C800 (BIOS A17) + Latitude C810 (BIOS A12) + Latitude C840 (BIOS A10) + Latitude CPiA (BIOS A14), no fan speed + Latitude CPx J750GT (BIOS A13), no fan speed + Latitude D600 (BIOS A05) + Latitude D800 (BIOS A00) + Latitude X200 (BIOS A07) + +That driver seems *NOT WORKING* on the following models: + + Inspiron 2500 (BIOS A10) + Inspiron 3200 + Inspiron 3500 + Inspiron 5000e (BIOS A06) + Inspiron 5150 (BIOS A23) + Inspiron 7000 + Inspiron 7500 + Latitude CPx H450GT + Latitude LS H500ST + +HISTORY: + +22 November 2004 - Initial release + +TODO: + +KCM Module + - set volume step size + - set dcop mixer device + - allow use of special keys + (this may require the user to set up key codes under X) + + diff --git a/kmilo/delli8k/delli8k.cpp b/kmilo/delli8k/delli8k.cpp new file mode 100644 index 0000000..74c0d60 --- /dev/null +++ b/kmilo/delli8k/delli8k.cpp @@ -0,0 +1,256 @@ +/* + This file is part of the KDE project + + Copyright (c) 2004 Barry O'Donovan (barry.odonovan@kdemail.net) + + The code in this module is heavily based on: + - the Asus Laptop plug-in for KMilo + Copyright (c) 2004 Chris Howells (howells@kde.org) + - the Thinkpad plug-in + Copyright (c) 2004 Jonathan Riddell (jr@jriddell.org) + - the i8k kernel module and utilities (http://www.debian.org/~dz/i8k/) + Copyright (c) 2001-2003 Massimo Dal Zotto + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +#include "kmilointerface.h" + +#include +#include + +#include "i8k.h" + +/* For compatibilty with i8k kernel driver 1.1 */ +#define I8K_VOL_MUTE_1_1 3 + +#include "delli8k.h" + +namespace KMilo +{ + +DellI8kMonitor::DellI8kMonitor( QObject* parent, const char* name, const QStringList& args ) + : Monitor( parent, name, args ) +{ +} + +DellI8kMonitor::~DellI8kMonitor() +{ +} + +bool DellI8kMonitor::init() +{ + kdDebug() << "KMilo: loading Dell I8k KMilo plugin" << endl; + + // Ensure the Dell I8k kernel module is installed/loaded + if( ( m_fd = open( I8K_PROC, O_RDONLY ) ) < 0 ) + { + kdDebug() << "KMilo: DellI8kMonitor: unable to open i8k proc file: " << I8K_PROC + << " in init()" << endl; + return false; + } + else + { + kmixClient = new DCOPRef( "kmix", "Mixer0" ); + kmixWindow = new DCOPRef( "kmix", "kmix-mainwindow#1" ); + retrieveVolume(); + retrieveMute(); + } + + return true; +} + +Monitor::DisplayType DellI8kMonitor::poll() +{ + Monitor::DisplayType pollResult = None; + + if( ( m_status = fn_status( m_fd ) ) < 0 ) + { + kdDebug() << "KMilo: DellI8kMonitor: unable to read fn status in poll()" << endl; + return pollResult; + } + else + { + switch( m_status ) + { + case I8K_VOL_UP: + pollResult = Volume; + retrieveVolume(); + setVolume( m_volume + DELLI8K_VOLUME_STEPSIZE ); + m_progress = m_volume; + break; + case I8K_VOL_DOWN: + pollResult = Volume; + retrieveVolume(); + setVolume( m_volume - DELLI8K_VOLUME_STEPSIZE ); + m_progress = m_volume; + break; + case I8K_VOL_MUTE: + case I8K_VOL_MUTE_1_1: + pollResult = None; + retrieveMute(); + setMute( !m_mute ); + if( m_mute ) + _interface->displayText( i18n( "Mute On" ) ); + else + _interface->displayText( i18n( "Mute Off" ) ); + break; + case 0: + break; + default: + kdDebug() << "KMile: DellI8kMonitor: invalid button status: " << m_status + << " in poll()" << endl; + break; + } + } + + return pollResult; +} + +int DellI8kMonitor::progress() const +{ + return m_progress; +} + +bool DellI8kMonitor::retrieveVolume() +{ + bool kmix_error = false; + + DCOPReply reply = kmixClient->call( "masterVolume"); + + if( reply.isValid() ) + { + m_volume = reply; + } + else + { + kmix_error = true; + } + + if (kmix_error) + { + // maybe the error occurred because kmix wasn't running + if( kapp->startServiceByDesktopName( "kmix" ) == 0 ) // trying to start kmix + { + // trying again + reply = kmixClient->call( "masterVolume"); + if( reply.isValid() ) + { + m_volume = reply; + kmix_error = false; + kmixWindow->send( "hide" ); + } + } + } + + if (kmix_error) + { + kdError() << "KMilo: DellI8kMonitor could not access kmix/Mixer0 via dcop" << endl; + return false; + } + + return true; +} + +void DellI8kMonitor::setVolume(int volume) +{ + if( !retrieveVolume() ) + { + return; + } + + if( volume > 100 ) + { + m_volume = 100; + } + else if( volume < 0 ) + { + m_volume = 0; + } + else + { + m_volume = volume; + } + + kmixClient->send("setMasterVolume", m_volume); + + m_progress = m_volume; +} + +bool DellI8kMonitor::retrieveMute() +{ + bool kmix_error = false; + + DCOPReply reply = kmixClient->call( "masterMute" ); + + if( reply.isValid() ) + { + m_mute = reply; + } + else + { + kmix_error = true; + } + + if (kmix_error) + { + // maybe the error occurred because kmix wasn't running + if( kapp->startServiceByDesktopName( "kmix" ) == 0 ) // trying to start kmix + { + // trying again + reply = kmixClient->call( "masterVolume" ); + if( reply.isValid() ) + { + m_volume = reply; + kmix_error = false; + kmixWindow->send( "hide" ); + } + } + } + + if (kmix_error) + { + kdError() << "KMilo: DellI8kMonitor could not access kmix/Mixer0 via dcop in isMute()" << endl; + return false; + } + + return true; +} + +void DellI8kMonitor::setMute( bool b ) +{ + m_mute = b; + kmixClient->send( "setMasterMute", m_mute ); +} + +int DellI8kMonitor::fn_status( int fd ) +{ + int args[1]; + int rc; + + if( ( rc = ioctl( fd, I8K_FN_STATUS, &args ) ) < 0 ) + { + kdError() << "KMilo: DellI8kMonitor: ioctl failed in fn_status()" << endl; + return rc; + } + + return args[0]; +} + +} //close namespace + +K_EXPORT_COMPONENT_FACTORY( kmilo_delli8k, KGenericFactory( "kmilo_delli8k" ) ) diff --git a/kmilo/delli8k/delli8k.h b/kmilo/delli8k/delli8k.h new file mode 100644 index 0000000..d33f6ff --- /dev/null +++ b/kmilo/delli8k/delli8k.h @@ -0,0 +1,89 @@ +/* + This file is part of the KDE project + + Copyright (c) 2004 Barry O'Donovan + + The code in this module is heavily based on: + - the Asus Laptop plug-in for KMilo + Copyright (c) 2004 Chris Howells (howells@kde.org) + - the Thinkpad plug-in + Copyright (c) 2004 Jonathan Riddell (jr@jriddell.org) + - the i8k kernel module and utilities (http://www.debian.org/~dz/i8k/) + Copyright (c) 2001-2003 Massimo Dal Zotto + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef DELLI8K_H +#define DELLI8K_H + +#include +#include + +#include "monitor.h" + +#define DELLI8K_VOLUME_STEPSIZE 5 + +namespace KMilo { + + +/** + * KMilo plugin for Dell Laptops (conforming to the i8k driver) + */ +class DellI8kMonitor: public Monitor +{ + public: + DellI8kMonitor( QObject *parent, const char *name, const QStringList& ); + virtual ~DellI8kMonitor(); + + /** + * Reimplemented from KMilo::Monitor. + * Loads configuration. + */ + virtual bool init(); + + /** + * Reimplemented from KMilo::Monitor. + * Called by KMilo, this checks the /proc file system and acts on any changes + */ + virtual DisplayType poll(); + + /** + * Reimplemented from KMilo::Monitor. + * Called by KMilo if poll() returns a volume change. + * Returns the new volume percentage. + */ + virtual int progress() const; + + private: + + void setVolume( int volume ); + void setMute( bool b ); + DCOPRef *kmixClient; + DCOPRef *kmixWindow; + bool retrieveVolume(); + bool retrieveMute(); + int m_status, m_volume; + bool m_mute; + + int m_progress; + int m_fd; + + int fn_status( int fd ); +}; + +} //close namespace + +#endif diff --git a/kmilo/delli8k/i8k.h b/kmilo/delli8k/i8k.h new file mode 100644 index 0000000..1c45ba5 --- /dev/null +++ b/kmilo/delli8k/i8k.h @@ -0,0 +1,46 @@ +/* + * i8k.h -- Linux driver for accessing the SMM BIOS on Dell laptops + * + * Copyright (C) 2001 Massimo Dal Zotto + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef _LINUX_I8K_H +#define _LINUX_I8K_H + +#define I8K_PROC "/proc/i8k" +#define I8K_PROC_FMT "1.0" + +#define I8K_BIOS_VERSION _IOR ('i', 0x80, int) /* broken: meant 4 bytes */ +#define I8K_MACHINE_ID _IOR ('i', 0x81, int) /* broken: meant 16 bytes */ +#define I8K_POWER_STATUS _IOR ('i', 0x82, size_t) +#define I8K_FN_STATUS _IOR ('i', 0x83, size_t) +#define I8K_GET_TEMP _IOR ('i', 0x84, size_t) +#define I8K_GET_SPEED _IOWR('i', 0x85, size_t) +#define I8K_GET_FAN _IOWR('i', 0x86, size_t) +#define I8K_SET_FAN _IOWR('i', 0x87, size_t) + +#define I8K_FAN_LEFT 1 +#define I8K_FAN_RIGHT 0 +#define I8K_FAN_OFF 0 +#define I8K_FAN_LOW 1 +#define I8K_FAN_HIGH 2 +#define I8K_FAN_MAX I8K_FAN_HIGH + +#define I8K_VOL_UP 1 +#define I8K_VOL_DOWN 2 +#define I8K_VOL_MUTE 4 + +#define I8K_AC 1 +#define I8K_BATTERY 0 + +#endif diff --git a/kmilo/delli8k/kmilo_delli8k.desktop b/kmilo/delli8k/kmilo_delli8k.desktop new file mode 100644 index 0000000..4dd7c97 --- /dev/null +++ b/kmilo/delli8k/kmilo_delli8k.desktop @@ -0,0 +1,96 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KMilo Plugin +X-KDE-ModuleType=Plugin +Name=Dell I8k Laptop Plugin +Name[ar]=ملحق حاسوب Dell I8k المحمول +Name[br]=Lugent hezoug Dell I8k +Name[bs]=Dodatak za Dell I8k laptope +Name[ca]=Connector per portàtils Dell I8k +Name[cs]=Dell I8k Laptop modul +Name[da]=Dell I8k bærbar plugin +Name[de]=Dell I8k Notebook-Plugin +Name[el]=Πρόσθετο φορητού Dell I8k +Name[es]=Extensión para el portátil Dell I8k +Name[et]=Dell I8k sülearvuti plugin +Name[eu]=Dell I8k Laptop Plugina +Name[fa]=Dell I8k وصلۀ رایانۀ کیفی +Name[fi]=Dell I8k -kannettavan liitännäinen +Name[fr]=Module externe pour les Dell I8k +Name[ga]=Breiseán Ríomhaire Glúine Dell I8k +Name[he]=תוסף למחשבי ברכיים בעלי Dell l8k +Name[hu]=Dell I8k modul +Name[is]=Dell I8k ferðatölvuíforrit +Name[it]=Plugin portatili Dell I8k +Name[ja]=Dell I8k ラップトップ プラグイン +Name[ka]=Dell I8k ლეპტოპის მოდული +Name[kk]=Dell I8k ноутбуктің модулі +Name[km]=កម្មវិធី​ជំនួយកុំព្យូទ័រ​យួរដៃ Dell I8k +Name[lt]=Dell I8k Laptop priedas +Name[nb]=Dell I8k Laptop tillegg +Name[nds]=Dell I8k-Klappreeknermoduul +Name[ne]=डेल I8k ल्यापटप प्लगइन +Name[nl]=Dell i8000 Laptop-plugin +Name[nn]=Programtillegg for Dell I8K-bærbare +Name[pa]=Dell I8k ਲੈਪਟਾਪ ਪਲੱਗਿੰਨ +Name[pl]=Wtyczka laptopa Dell I8k +Name[pt]='Plugin' para Portáteis Dell I8k +Name[pt_BR]=Plugin para Laptops Dell I8k +Name[ru]=Ноутбук Dell I8k +Name[sk]=Modul pre Dell l8k laptop +Name[sl]=Vstavek za prenosnik Dell I8k +Name[sr]=Прикључак за Dell-ове I8k лаптопе +Name[sr@Latn]=Priključak za Dell-ove I8k laptope +Name[sv]=Insticksprogram för Dell I8k bärbar dator +Name[ta]=டெல் 18கே மடிக்கணினி சொருகுப்பொருள் +Name[tr]=Dell I8k Laptop Eklentisi +Name[uk]=Втулок лептопа Dell I8k +Name[uz]=Dell I8k laptopi uchun plagin +Name[uz@cyrillic]=Dell I8k лаптопи учун плагин +Name[zh_CN]=Dell I8k 笔记本插件 +Name[zh_TW]=Dell I8k 筆記型電腦外掛程式 +Comment=Enables support for special Dell laptop keys +Comment[ar]=تمكّن الدعم لمفاتيح حاسوب Dell المحمول الخاصة +Comment[bg]=Тази приставка позволява поддръжката на специалните клавиши на Dell +Comment[bs]=Omogućuje podršku za posebne tipke na Dell laptopima +Comment[ca]=Habilita el funcionament per a tecles especials dels portàtils Dell +Comment[cs]=Umožňuje podporu speciálních kláves laptopů Dell +Comment[da]=Aktiverer støtte for specielle Dell bærbares taster +Comment[de]=Dieses Plugin aktiviert die Unterstützung für Sondertasten bei Dell-Notebook-Tastaturen +Comment[el]=Ενεργοποιεί την υποστήριξη για ειδικά πλήκτρα φορητού Dell +Comment[es]=Activa el soporte de las teclas especiales del portátil Dell +Comment[et]=Võimaldab kasutada Delli sülearvuti eriklahve +Comment[eu]=Dell eramangarrien tekla berezientzako euskarria gaitzen du +Comment[fa]=فعال‌سازی پشتیبانی برای کلیدهای ویژۀ رایانۀ کیفیDell +Comment[fi]=Tämä liitännäinen mahdollistaa erikoisnäppäinten tuen Dellin kannettaville tietokoneille. +Comment[fr]=Ce module active la gestion des touches spéciales des ordinateurs portables Dell +Comment[ga]=Tacaigh le heochracha speisialta ar ríomhairí glúine Dell +Comment[he]=מוסיף תמיכה בשביל מקשים מיוחדים של Dell +Comment[hu]=Ez a bővítőmodul lehetővé teszi a Dell noteszgépek speciális billentyűinek használatát +Comment[is]=Virkjar stuðning fyrir sérhnappa Dell ferðavéla +Comment[it]=Abilita il supporto per i tasti speciali dei portatili Dell +Comment[ja]=Dell ラップトップの特殊キーをサポートします +Comment[ka]=რთავს Dell-ის ლეპტოპის სპეციალური კლავიშების მხარდაჭერას +Comment[kk]=Dell ноутбуктің арнаулы пернелерін қолдауы +Comment[km]=បើក​ការគាំទ្រ​សម្រាប់គ្រាប់ចុច​កុំព្យូទ័រ​យួរដៃ Dell +Comment[lt]=Įgalina specialų Dell nešiojamo kompiuterio raktų palaikymą +Comment[nb]=Muliggjør støtte for spesielle taster på Dell bærbare maskiner +Comment[nds]=Maakt de Sünnertasten-Ünnerstütten för Dell-Klappreekners an +Comment[ne]=विशेष डेल ल्यापटप कुञ्जीका लागि समर्थन सक्षम पार्दछ +Comment[nl]=Activeert de ondersteuning voor speciale Dell-laptop-toetsen +Comment[nn]=Dette programtillegget gjer det mogleg å bruka spesialtastar på Dell-bærbare +Comment[pl]=Włącza obsługę specjalnych klawiszy laptopa Dell +Comment[pt]=Activa o suporte a teclas especiais dos portáteis Dell +Comment[pt_BR]=Habilita suporte para teclas especiais nos laptops Dell +Comment[ru]=Этот модуль поддерживает специальные клавиши ноутбука Dell +Comment[sk]=Povoľuje podporu pre špeciálne klávesy Dell laptopu +Comment[sl]=Omogoči podporo posebnim tipkam prenosnikov Dell +Comment[sr]=Подршка за посебне тастере на Dell-овим лаптопима +Comment[sr@Latn]=Podrška za posebne tastere na Dell-ovim laptopima +Comment[sv]=Aktiverar stöd för speciella tangenter på Dell bärbar dator +Comment[ta]=விசேஷ டெல் மடிக்கணினி விசைகளுக்கான ஆதரவை செயல்படுத்துகிறது +Comment[tr]=Dell dizüstü bilgisayarların özel tuşları için desteği etkinleştirir +Comment[uk]=Уможливлює підтримку спеціальних клавіш для лептопа Dell +Comment[zh_CN]=此插件启用 Dell 笔记本的特殊按键 +Comment[zh_TW]=開啟 Dell 筆記型電腦特殊鍵支援 +X-KDE-Library=kmilo_delli8k diff --git a/kmilo/demo/Makefile.am b/kmilo/demo/Makefile.am new file mode 100644 index 0000000..8ac7a46 --- /dev/null +++ b/kmilo/demo/Makefile.am @@ -0,0 +1,32 @@ +# This file is part of the KDE project +# Copyright (C) 2003 George Staikos + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +INCLUDES=-I$(srcdir)/../kmilod $(all_includes) + +kde_module_LTLIBRARIES = kmilo_demo.la + +kmilo_demo_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kmilo_demo_la_LIBADD = ../kmilod/libkmilo.la $(LIB_KIO) +kmilo_demo_la_SOURCES = demo.cpp +METASOURCES = AUTO + +noinst_HEADERS = demo.h + +services_DATA = kmilo_demo.desktop +servicesdir = $(kde_servicesdir)/kmilo + diff --git a/kmilo/demo/demo.cpp b/kmilo/demo/demo.cpp new file mode 100644 index 0000000..668d137 --- /dev/null +++ b/kmilo/demo/demo.cpp @@ -0,0 +1,56 @@ +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include + +#include "demo.h" + +namespace KMilo { + +Demo::Demo(QObject *parent, const char *name, const QStringList& args) +: Monitor(parent, name, args) { +} + + +Demo::~Demo() { +} + + +bool Demo::init() { +return true; +} + + +Monitor::DisplayType Demo::poll() { +Monitor::DisplayType rc = None; +return rc; +} + + +int Demo::progress() const { + return 10; +} + +}; + +K_EXPORT_COMPONENT_FACTORY(kmilo_demo, KGenericFactory) + diff --git a/kmilo/demo/demo.h b/kmilo/demo/demo.h new file mode 100644 index 0000000..6f57cfc --- /dev/null +++ b/kmilo/demo/demo.h @@ -0,0 +1,39 @@ +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef _DEMO_H_ +#define _DEMO_H_ + +#include "monitor.h" + +class Demo : public KMilo::Monitor { + public: + Demo(QObject *parent, const char *name, const QStringList&); + virtual ~Demo(); + + virtual bool init(); + virtual DisplayType poll(); + virtual int progress() const; + + private: +}; + +#endif diff --git a/kmilo/demo/kmilo_demo.desktop b/kmilo/demo/kmilo_demo.desktop new file mode 100644 index 0000000..288903f --- /dev/null +++ b/kmilo/demo/kmilo_demo.desktop @@ -0,0 +1,110 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KMilo Plugin +X-KDE-ModuleType=Plugin +Name=Demo Plugin +Name[ar]=ملحق للعرض +Name[bg]=Демонстрационна приставка +Name[ca]=Connector demo +Name[cy]=Ategyn Arddangosiad +Name[da]=Demo-plugin +Name[de]=Demo-Plugin +Name[el]=Πρόσθετο επίδειξης +Name[eo]=Demo-kromaĵo +Name[es]=Extensión de demostración +Name[et]=Demoplugin +Name[eu]=Demo Plugina +Name[fa]=وصلۀ Demo +Name[fi]=Esimerkkiliitännäinen +Name[fr]=Module externe de démonstration +Name[ga]=Breiseán Taispeána +Name[he]=תוסף לדוגמה +Name[hi]=डेमो प्लगइन +Name[hu]=Mintamodul +Name[is]=Sýnishorn af íforriti +Name[it]=Plugin dimostrativo +Name[ja]=デモプラグイン +Name[ka]=Demo მოდული +Name[kk]=Үлгілі модулі +Name[km]=កម្មវិធី​ជំនួយ​សាកល្បង +Name[lt]=Demo priedas +Name[mk]=Демо приклучок +Name[nb]=Programtillegg for demo +Name[nds]=Demo-Moduul +Name[ne]=डेमो प्लगइन +Name[nl]=Demo-plugin +Name[nn]=Demo-programtillegg +Name[pa]=ਫ਼ਰਜੀ ਪਲੱਗਿੰਨ +Name[pl]=Wtyczka demonstracyjna +Name[pt]='Plugin' de Demonstração +Name[pt_BR]=Plug-in de Demonstração +Name[ro]=Modul demonstrativ +Name[ru]=Демонстрационный модуль +Name[sk]=Testovací modul +Name[sl]=Demonstracijski vstavek +Name[sr]=Демонстрациони прикључак +Name[sr@Latn]=Demonstracioni priključak +Name[sv]=Demoinsticksprogram +Name[ta]= முன்னோட்ட சொருகி +Name[tg]=Модули Намоиш +Name[uk]=Демонстраційний втулок +Name[uz]=Demo plagini +Name[uz@cyrillic]=Демо плагини +Name[wa]=Tchôke-divins di mostraedje +Name[zh_CN]=演示插件 +Name[zh_TW]=示範用外掛程式 +Comment=This plugin does nothing. +Comment[ar]=لا يفعل هذا الملحق أى شئ.. +Comment[bg]=Тази приставка не прави нищо +Comment[bs]=Ovaj dodatak ne radi ništa. +Comment[ca]=Aquest connector no fa res. +Comment[cy]=Nid yw'r ategyn yma yn gwneud unrhyw beth. +Comment[da]=Dette plugin gør ingenting. +Comment[de]=Dieses Plugin macht nichts. +Comment[el]=Αυτό το πρόσθετο δεν κάνει τίποτα. +Comment[eo]=Tiu kromaĵo faras nenion. +Comment[es]=Esta extensión no hace nada. +Comment[et]=See plugin ei tee mitte kui midagi. +Comment[eu]=Plugin honek ez du ezer egiten. +Comment[fa]=این وصله کاری انجام نمی‌دهد. +Comment[fi]=Tämä liitännäinen ei tee mitään. +Comment[fr]=Ce module ne fait rien. +Comment[ga]=Ní dhéanann an breiseán seo faic. +Comment[he]=התוסף הזה לא עושה כלום +Comment[hi]=यह प्लगइन कुछ नहीं करता है. +Comment[hu]=Ez a bővítőmodul nem csinál semmit +Comment[is]=Þetta íforrit gerir ekki neitt. +Comment[it]=Questo plugin non fa niente +Comment[ja]=このプラグインは何もしません +Comment[ka]=ეს მოდული არაფერს არ აკეთებს +Comment[kk]=Бұл модуль ештеңе істемейді. +Comment[km]=កម្មវិធី​ជំនួយ​នេះ​មិន​ធ្វើ​អ្វី ។ +Comment[lt]=Šis priedas nieko nedaro. +Comment[mk]=Овој приклучок не прави ништо. +Comment[ms]=Plug masuk ini tidak melakukan apa-apa. +Comment[nb]=Dette programtillegget utfører ingen funksjoner +Comment[nds]=Dit Moduul deit nix. +Comment[ne]=यो प्लगइनले केही गर्दैन । +Comment[nl]=Deze plugin doet niets. +Comment[nn]=Dette programtillegget gjer ikkje noko som helst. +Comment[pa]=ਇਹ ਪਲੱਗਿੰਨ ਕੁਝ ਨਹੀਂ ਕਰਦੀ ਹੈ। +Comment[pl]=Ta wtyczka nic nie robi. +Comment[pt]=Este 'plugin' não faz nada. +Comment[pt_BR]=Este plug-in não faz coisa alguma. +Comment[ro]=Acest modul nu face nimic. +Comment[ru]=Этот модуль ничего не делает. +Comment[sk]=Tento modul nič nerobí. +Comment[sl]=Ta vstavek ne naredi ničesar. +Comment[sr]=Овај прикључак ништа не ради. +Comment[sr@Latn]=Ovaj priključak ništa ne radi. +Comment[sv]=Det här insticksprogrammet gör ingenting. +Comment[ta]= செருகுப்பொருள் செயல்படவில்லை. +Comment[tg]=Ин модул ҳеҷ чиз намекунад. +Comment[tr]=Bu plugin birşey yapmaz. +Comment[uk]=Цей втулок нічого не робить. +Comment[uz]=Bu plagin hech narsa bajarmaydi. +Comment[uz@cyrillic]=Бу плагин ҳеч нарса бажармайди. +Comment[wa]=Ci tchôke-divins chal ni fwait rén do tot. +Comment[zh_CN]=此插件不完成任何工作。 +Comment[zh_TW]=這個外掛程式不做任何事。 +X-KDE-Library=kmilo_demo diff --git a/kmilo/generic/Makefile.am b/kmilo/generic/Makefile.am new file mode 100644 index 0000000..1dd7094 --- /dev/null +++ b/kmilo/generic/Makefile.am @@ -0,0 +1,34 @@ +# This file is part of the KDE project +# Copyright (C) 2003 George Staikos + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +INCLUDES=-I$(srcdir)/../kmilod $(all_includes) + +kde_module_LTLIBRARIES = kmilo_generic.la + +kmilo_generic_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kmilo_generic_la_LIBADD = ../kmilod/libkmilo.la $(LIB_KIO) +kmilo_generic_la_SOURCES = generic_monitor.cpp +METASOURCES = AUTO + +noinst_HEADERS = generic_monitor.h + +services_DATA = kmilo_generic.desktop +servicesdir = $(kde_servicesdir)/kmilo + +messages: + $(XGETTEXT) $(kmilo_generic_la_SOURCES) -o $(podir)/kmilo_generic.pot diff --git a/kmilo/generic/README b/kmilo/generic/README new file mode 100644 index 0000000..1727e8e --- /dev/null +++ b/kmilo/generic/README @@ -0,0 +1,38 @@ +This module provides support for the VolumeUp, VolumeDown and Mute Internet +keys found in many laptops and special keyboards. + +Please note that in order this module to work, mentioned special keys have to +generate appropriate X key symbols (keysyms), namely XF86AudioLowerVolume, +XF86AudioRaiseVolume, XF86AudioMute. You can use "xev" program to watch events +generated by X server and "xmodmap" program to assign events (keycodes) to +keysyms. Also watch kernel log (dmesg) for unknown scancodes. + +If you use CTRL in conjunction with volUp/Down it changes the volume by 1%, +otherwise by 10%. + +This module is now configurable (though with no configuration GUI), you can +change which channels (kmix device indexes) to change volume on, you can also +tweak volume changing steps. Channels are represented by numeric indexes +starting from zero, in order to get the right channel, you have to experiment +a little (keep the kmix mixer window open). ;) Examples: + +# Change "fast" step to 5% and "slow" step to 2%: +kwriteconfig --file kmilodrc --group "generic monitor" --key volumeStepFast 5 +kwriteconfig --file kmilodrc --group "generic monitor" --key volumeStepSlow 2 + +# Change channel to set volume on to 1 (use -1 to use kmix' master device): +kwriteconfig --file kmilodrc --group "generic monitor" --key volumeDeviceIdx 1 + +# You can also specify different mute channel (leave it unset or set it to -1 +# to use the same channel for muting and changing volume): +kwriteconfig --file kmilodrc --group "generic monitor" --key muteDeviceIdx 2 + +# KMilo now supports an extra channel, whose volume and mute will be set to +# whatever your primary channel is set to. (leave it unset or set it to -1 to +# disable this functionality): +kwriteconfig --file kmilodrc --group "generic monitor" --key extraDeviceIdx 5 + +# Use following call to apply these settings without restarting your session: +dcop kded kmilod reconfigure + +Have fun. diff --git a/kmilo/generic/generic_monitor.cpp b/kmilo/generic/generic_monitor.cpp new file mode 100644 index 0000000..40e7169 --- /dev/null +++ b/kmilo/generic/generic_monitor.cpp @@ -0,0 +1,324 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 Willi Richert + Pretty much ripped off from : + George Staikos :) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include + +#include +#include + +#include "generic_monitor.h" +#include "kmilointerface.h" +#include +#include + +#define CONFIG_FILE "kmilodrc" + + +using namespace KMilo; + +GenericMonitor::GenericMonitor(QObject *parent, const char *name, const QStringList& args) +: Monitor(parent, name, args) +{ + _poll = false; + m_displayType = Monitor::None; + + m_mute = false; + m_progress = 0; + m_minVolume = 0; + m_maxVolume = 100; + m_volume = 50; +} + +GenericMonitor::~GenericMonitor() +{ + if(ga) { + ga->remove("FastVolumeUp"); + ga->remove("FastVolumeDown"); + ga->remove("SlowVolumeUp"); + ga->remove("SlowVolumeDown"); + ga->remove("Mute"); + delete ga; + } +} + +bool GenericMonitor::init() +{ + KConfig config(CONFIG_FILE); + reconfigure(&config); + + if(!m_enabled) + return false; // exit early if we are not supposed to run + + static const ShortcutInfo shortcuts[] = { + { "FastVolumeUp", Qt::Key_VolumeUp, SLOT(fastVolumeUp()) }, + { "FastVolumeDown", Qt::Key_VolumeDown, SLOT(fastVolumeDown()) }, + { "SlowVolumeUp", Qt::CTRL+Qt::Key_VolumeUp, SLOT(slowVolumeUp()) }, + { "SlowVolumeDown", Qt::CTRL+Qt::Key_VolumeDown, SLOT(slowVolumeDown()) }, + { "Mute", KShortcut("XF86AudioMute"), SLOT(mute()) } + }; + + ga = new KGlobalAccel(this, "miloGenericAccel"); + + ShortcutInfo si; + int len = (int)sizeof(shortcuts)/sizeof(ShortcutInfo); + for (int i = 0; i < len; i++) { + si = shortcuts[i]; + + ga->insert(si.name, QString::null, QString::null, + si.symbol, si.symbol, + this, + si.slot, false); + } + + ga->readSettings(); + ga->updateConnections(); + + kmixClient = new DCOPRef("kmix", "Mixer0"); + kmixWindow = new DCOPRef("kmix", "kmix-mainwindow#1"); + + return true; +} + +void GenericMonitor::reconfigure(KConfig *config) +{ + config->setGroup("generic monitor"); + + m_volumeDeviceIdx = config->readNumEntry("volumeDeviceIdx", -1); + m_muteDeviceIdx = config->readNumEntry("muteDeviceIdx", m_volumeDeviceIdx); + m_extraDeviceIdx = config->readNumEntry("extraDeviceIdx", -1); + m_volumeStepFast = config->readNumEntry("volumeStepFast", 10); + m_volumeStepSlow = config->readNumEntry("volumeStepSlow", 1); + m_enabled = config->readBoolEntry("enabled", true); +} + +bool GenericMonitor::retrieveKmixDevices() +{ + if(m_volumeDeviceIdx != -1 && m_muteDeviceIdx != -1) + return true; // both indexes already set + + DCOPReply reply = kmixClient->call("masterDeviceIndex"); + if (!reply.isValid()) + { // maybe the error occurred because kmix wasn't running + _interface->displayText(i18n("Starting KMix...")); + if (kapp->startServiceByDesktopName("kmix")==0) // trying to start kmix + { + reply = kmixClient->call("masterDeviceIndex"); + if (reply.isValid()) + kmixWindow->send("hide"); + } + } + + if (!reply.isValid()) + { + kdDebug() << "KMilo: GenericMonitor could not access kmix/Mixer0 via dcop" + << endl; + _interface->displayText(i18n("It seems that KMix is not running.")); + + return false; + } else { + if (m_volumeDeviceIdx == -1) + m_volumeDeviceIdx = reply; + if (m_muteDeviceIdx == -1) + m_muteDeviceIdx = m_volumeDeviceIdx; // this is the behaviour documented in README + return true; + } +} + +bool GenericMonitor::retrieveVolume() +{ + bool kmix_error = false; + + if(!retrieveKmixDevices()) + return false; + + DCOPReply reply = kmixClient->call("absoluteVolume", m_volumeDeviceIdx); + if (reply.isValid()) + m_volume = reply; + else + kmix_error = true; + + if (kmix_error) // maybe the error occurred because kmix wasn't running + { + _interface->displayText(i18n("Starting KMix...")); + if (kapp->startServiceByDesktopName("kmix")==0) // trying to start kmix + { + // trying again + reply = kmixClient->call("absoluteVolume", m_volumeDeviceIdx); + if (reply.isValid()) + { + m_volume = reply; + kmix_error = false; + kmixWindow->send("hide"); + } + } + } + + if (kmix_error) + { + kdDebug() << "KMilo: GenericMonitor could not access kmix/Mixer0 via dcop" + << endl; + _interface->displayText(i18n("It seems that KMix is not running.")); + + return false; + } else { + reply = kmixClient->call("absoluteVolumeMax", m_volumeDeviceIdx); + m_maxVolume = reply; + reply = kmixClient->call("absoluteVolumeMin", m_volumeDeviceIdx); + m_minVolume = reply; + return true; + } +} + +void GenericMonitor::volumeChange(int direction, int step) +{ + if (!retrieveVolume()) + return; + + /* Following snippet of code may seem to be overcomplicated, but it works for both devices with + * volume grain < 100 (32 tested) and devices with volume grain > 100 (256 tested) while preserving + * accuracy for devices with fine grain and preserving usability for devices with rough grain. */ + int userVisibleVolume = qRound(m_volume * 100.0 / (m_maxVolume - m_minVolume)); + userVisibleVolume += direction * step; // add requested volume step + long previousVolume = m_volume; + m_volume = qRound(m_minVolume + userVisibleVolume * (m_maxVolume - m_minVolume) / 100.0); + if (m_volume == previousVolume) // if the change was rounded to zero + m_volume += direction; + + if (m_volume > m_maxVolume) + m_volume = m_maxVolume; + if (m_volume < m_minVolume) + m_volume = m_minVolume; + + displayVolume(); +} + +void GenericMonitor::slowVolumeUp() { volumeChange( 1, m_volumeStepSlow); } +void GenericMonitor::slowVolumeDown() { volumeChange(-1, m_volumeStepSlow); } +void GenericMonitor::fastVolumeUp() { volumeChange( 1, m_volumeStepFast); } +void GenericMonitor::fastVolumeDown() { volumeChange(-1, m_volumeStepFast); } + +void GenericMonitor::displayVolume() +{ + _interface->displayProgress(i18n("Volume"), qRound(m_volume * 100.0 / (m_maxVolume - m_minVolume))); + + // If we got this far, the DCOP communication with kmix works, + // so we don't have to test the result. + // Also, device indexes are set to their proper values. + kmixClient->send("setAbsoluteVolume", m_volumeDeviceIdx, m_volume); + if(m_extraDeviceIdx != -1) + // for simplicity, use relative volume rather that absolute (extra precision is not needed here) + kmixClient->send("setVolume", m_extraDeviceIdx, qRound(m_volume * 100.0 / (m_maxVolume - m_minVolume))); + + // if mute then unmute + if (m_mute) + { + m_mute = false; + kmixClient->send("setMute", m_muteDeviceIdx, m_mute); + } +} + +bool GenericMonitor::retrieveMute() +{ + bool kmix_error = false; + + if(!retrieveKmixDevices()) + return false; + + DCOPReply reply = kmixClient->call("mute", m_muteDeviceIdx); + if (reply.isValid()) + m_mute = reply; + else + kmix_error = true; + + if (kmix_error) + { + // maybe the error occurred because kmix wasn't running + _interface->displayText(i18n("Starting KMix...")); + if (kapp->startServiceByDesktopName("kmix")==0) // trying to start kmix + { + // trying again + reply = kmixClient->call("mute", m_muteDeviceIdx); + if (reply.isValid()) + { + m_mute = reply; + kmix_error = false; + kmixWindow->send("hide"); + } + } else + { + kmixWindow->send("hide"); + kmix_error = true; + } + } + + if (kmix_error) + { + kdDebug() << "KMilo: GenericMonitor could not access kmix/Mixer0 via dcop" + << endl; + _interface->displayText(i18n("It seems that KMix is not running.")); + + return false; + } else { + return true; + } +} + +void GenericMonitor::mute() +{ + if (!retrieveMute()) + return; + + m_mute = !m_mute; + QString muteText; + if (m_mute) + { + muteText = i18n("Mute on"); + } else { + muteText = i18n("Mute off"); + } + + kmixClient->send("setMute", m_muteDeviceIdx, m_mute); + if(m_extraDeviceIdx != -1) + kmixClient->send("setMute", m_extraDeviceIdx, m_mute); + + _interface->displayText(muteText); +} + +int GenericMonitor::progress() const +{ + return m_progress; +} + +Monitor::DisplayType GenericMonitor::poll() +{ + return m_displayType; +} + + +K_EXPORT_COMPONENT_FACTORY(kmilo_generic, KGenericFactory("kmilo_generic")) + +#include "generic_monitor.moc" diff --git a/kmilo/generic/generic_monitor.h b/kmilo/generic/generic_monitor.h new file mode 100644 index 0000000..c2477c4 --- /dev/null +++ b/kmilo/generic/generic_monitor.h @@ -0,0 +1,94 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 Willi Richert + Pretty much ripped of from : + George Staikos :) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef _GENERICMONITOR_H_ +#define _GENERICMONITOR_H_ + +#include +#include +#include +#include + +#include "kmilod.h" +#include "monitor.h" + +namespace KMilo { + +// now the key data (from kkeyserver_x11.h and $QTDIR/include/qnamespace.h) +struct ShortcutInfo +{ + const char* name; + uint symbol; + const char *slot; +}; + + +class GenericMonitor : public Monitor +{ + Q_OBJECT + +public: + GenericMonitor(QObject *parent, const char *name, const QStringList&); + virtual ~GenericMonitor(); + + virtual bool init(); + virtual int progress() const; + virtual DisplayType poll(); + virtual void reconfigure(KConfig*); + +public slots: + void slowVolumeUp(); + void slowVolumeDown(); + void fastVolumeUp(); + void fastVolumeDown(); + void mute(); + +private: + bool retrieveKmixDevices(); + void volumeChange(int direction, int step); + bool retrieveMute(); + bool retrieveVolume(); + void displayVolume(); + + KGlobalAccel *ga; + + DCOPRef *kmixClient, *kmixWindow; + + int m_progress; + long m_volume; + bool m_mute; + + long m_maxVolume, m_minVolume; + + // following properties are read from config file: + int m_volumeStepFast, m_volumeStepSlow; + int m_volumeDeviceIdx, m_muteDeviceIdx, m_extraDeviceIdx; + bool m_enabled; + + Monitor::DisplayType m_displayType; +}; + +} + +#endif diff --git a/kmilo/generic/kmilo_generic.desktop b/kmilo/generic/kmilo_generic.desktop new file mode 100644 index 0000000..89d55d0 --- /dev/null +++ b/kmilo/generic/kmilo_generic.desktop @@ -0,0 +1,108 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KMilo Plugin +X-KDE-ModuleType=Plugin +Name=Generic Keyboard Plugin +Name[ar]=ملحق عام للوحة المفاتيح +Name[bg]=Приставка за клавиатурата +Name[bs]=Opšti dodatak za tastaturu +Name[ca]=Connector de teclat genèric +Name[cs]=Obecný modul klávesnice +Name[cy]=Ategyn Bysellfwrdd Cyffredinol +Name[da]=Generisk tastatur-plugin +Name[de]=Allgemeines Tastatur-Plugin +Name[el]=Γενικευμένο πρόσθετο πληκτρολογίου +Name[eo]=Komuna klavar-kromprogramo +Name[es]=Extensión de teclado genérico +Name[et]=Tavaline klaviatuuriplugin +Name[eu]=Teklatu Arruntaren Plugina +Name[fa]=وصلۀ کلی صفحه کلید +Name[fi]=Yleinen näppäimistöliitännäinen +Name[fr]=Module externe de clavier générique +Name[ga]=Breiseán Cineálach Méarchláir +Name[he]=תוסף גנרי למקלדות +Name[hi]=जेनेरिक कुंजीपट प्लगइन +Name[hu]=Általános billentyűzet-bővítőmodul +Name[is]=Almennt lyklaborðsíforrit +Name[it]=Plugin tastiera generica +Name[ja]=一般キーボードプラグイン +Name[ka]=სტანდარტული კლავიატურა მოდული +Name[kk]=Негізгі пернетақта модулі +Name[km]=កម្មវិធី​ជំនួយ​ក្តារចុច​ទូទៅ +Name[lt]=Bendro pobūdžio klaviatūros priedas +Name[mk]=Општ приклучок за тастатура +Name[nb]=Programtillegg for generisk tastatur +Name[nds]=Allgemeen Tastatuurmoduul +Name[ne]=जेनेरिक कुञ्जीपाटी प्लगइन +Name[nl]=Algemene toetsenbord-plugin +Name[nn]=Programtillegg for generisk tastatur +Name[pa]=ਸਧਾਰਨ ਕੀ-ਬੋਰਡ ਪਲੱਗਿੰਨ +Name[pl]=Wtyczka zwykłej klawiatury +Name[pt]='Plugin' de Teclado Genérico +Name[pt_BR]=Plug-in de Teclado Genérico +Name[ro]=Modul generic de tastatură +Name[ru]=Модуль клавиатуры +Name[sk]=Modul pre generickú klávesnicu +Name[sl]=Generični vstavek za tipkovnice +Name[sr]=Генерички прикључак тастатуре +Name[sr@Latn]=Generički priključak tastature +Name[sv]=Allmänt insticksprogram för tangentbord +Name[ta]= பொதுவான விசைப்பலகை சொருகுபொருள் +Name[tg]=Модули Умумии Забонак +Name[tr]=Generic Klavye Plugini +Name[uk]=Загальний втулок клавіатури +Name[uz]=Umumiy tugmatag plagini +Name[uz@cyrillic]=Умумий тугматаг плагини +Name[wa]=Tchôke-divins djenerike di taprece +Name[zh_CN]=常规键盘插件 +Name[zh_TW]=一般鍵盤外掛程式 +Comment=This plugin enables support for special keys on all sorts of keyboards and laptops. +Comment[ar]=تمكّن الدعم للمفاتيح الخاصة فى كل أنواع لوحات المفاتيح والحواسيب المحمولة. +Comment[bg]=Тази приставка позволява поддръжката на специалните клавиши на различните видове лаптопи и специални клавиатури +Comment[bs]=Ovaj dodatak (plugin) omogućuje podršku za posebne tipke na raznim vrstama tastatura i laptopa. +Comment[ca]=Aquest connector activa el funcionament per a tecles especials en tot tipus de teclats i portàtils. +Comment[cs]=Tento modul umožňuje používat zvláštní klávesy na všech typech klávesnic a notebooků. +Comment[cy]=Mae'r ategyn yn galluogi cynhaliaeth ar gyfer bysyll arbennig ar bob math o bysellfyrdd a gluniaduron. +Comment[da]=Dette plugin aktivere støtte for specielle taster på alle slags tastaturer og bærbare. +Comment[de]=Dieses Plugin aktiviert die Unterstützung für die Sondertasten diverser Tastaturen und Notebooks. +Comment[el]=Αυτό το πρόσθετο ενεργοποιεί την υποστήριξη για ειδικά πλήκτρα σε όλα τα είδη των πληκτρολογίων και φορητών υπολογιστών. +Comment[es]=Esta extensión activa el soporte de las teclas especiales en todo tipo de teclados y portátiles. +Comment[et]=See plugin võimaldab kasutada eriklahve igasugustel klaviatuuridel ja sülearvutitel. +Comment[eu]=Plugin honek tekla berezientzako euskarria gaitzen du teklatu eta magaleko mota guztietan. +Comment[fa]=این وصله، برای کلیدهای ویژه روی همۀ انواع صفحه کلید و رایانه‌های کیفی، پشتیبانی را فعال می‌سازد. +Comment[fi]=Tämä liitännäinen mahdollistaa erikoisnäppäinten tuen kaikenlaisille näppäimistöille ja kannettavilla tietokoneille. +Comment[fr]=Ce module active la gestion des touches spéciales pour toutes sortes de claviers et de portables. +Comment[ga]=Tacaíonn an breiseán seo le cnaipí speisialta ar neart sóirt méarchlár agus ríomhairí glúine. +Comment[he]=תוסף זה מאפשר את השימוש בכל המקשים המיוחדים במקלדת ומחשבים ניידים. +Comment[hi]=यह प्लगइन सभी क़िस्म के कुंजीपट तथा लैपटॉप पर विशिष्ट कुंजी समर्थन सक्षम करता है +Comment[hu]=Ez a bővítőmodul lehetővé teszi az extra billentyűk használatát speciális billentyűzeteknél és noteszgépeken. +Comment[is]=Þetta íforrit virkjar sérhnappana sem eru á allskynd gerðum lyklaborða og ferðavéla. +Comment[it]=Questo plugin abilita il supporto per i tasti speciali su qualsiasi tipo di tastiera e portatile. +Comment[ja]=このプラグインはあらゆる種類のキーボードとラップトップで特殊キーをサポートします +Comment[ka]=ეს მოდული რთავს ყველანაერი ტიპის კლავიატურების (მათ შორის ლეპტოპების) სპეციალური კლავიშების მხარდაჭერას. +Comment[kk]=Бұл модуль барлық пернетақталар мен ноутбуктердегі арнаулы пернелерді қолдайды. +Comment[km]=កម្មវិធី​ជំនួយ​នេះបើក​ការគាំទ្រ សម្រាប់​គ្រាប់ចុច​ពិសេស​នៅ​លើ​ប្រភេទ​ក្តារចុច និង​កុំព្យូទ័រ​យួរដៃ​ទាំងអស់ ។ +Comment[lt]=Šis priedas įgalina ypatingų klavišų palaikymą įvairių tipų klaviatūrose bei nešiojamuose kompiuteriuose. +Comment[mk]=Овој приклучок дава поддршка за специјалните копчиња на сите видови на тастатури и лаптопи. +Comment[nb]=Dette programtillegget muliggjør støtte for spesielle taster på alle tastatur og bærbare maskiner +Comment[nds]=Dit Moduul maakt de Sünnertasten-Ünnerstütten för all Oorden vun Tastaturen un Klappreekners an. +Comment[ne]=यो प्लगइनले कुञ्जीपाटी र ल्यापटपको सबै क्रमबद्धतामा विशेष कुञ्जीका लागि समर्थन सक्षम पार्दछ । +Comment[nl]=Deze plugin biedt ondersteuning voor allerlei speciale toetsen op laptops en gewone toetsenborden. +Comment[nn]=Dette programtillegget gjer det mogleg å bruka spesialtastar på alle tastatur og bærbare maskiner. +Comment[pl]=Ta wtyczka umożliwia używanie klawiszy specjalnych na wszystkich rodzajach klawiatur i laptopach. +Comment[pt]=Este 'plugin' activa o suporte para as teclas especiais em todos os tipos de teclados e portáteis. +Comment[pt_BR]=Este plug-in habilita suporte para teclas especiais em todos os tipos de laptops e teclados. +Comment[ro]=Acest modul activează suportul pentru tastele speciale de pe tot felul de tastaturi şi laptop-uri. +Comment[ru]=Этот модуль поддерживает специальные клавиши на всех типах клавиатур и ноутбуках. +Comment[sk]=Tento modul obsahuje podporu pre špeciálne klávesy na rôznych klávesniciach a prenosných počítačoch. +Comment[sl]=Ta vstavek omogoča podporo za posebne tipke na vseh vrstah tipkovnic in prenosnikov. +Comment[sr]=Овај прикључак омогућава подршку за специјалне тастере на свакаквим тастатурама и лаптоповима. +Comment[sr@Latn]=Ovaj priključak omogućava podršku za specijalne tastere na svakakvim tastaturama i laptopovima. +Comment[sv]=Det här insticksprogrammet aktiverar stöd för speciella tangenter för alla typer av tangentbord och bärbara datorer. +Comment[ta]=எல்லா அடுக்குகளிலும் உள்ள விசைபலகைகள் மற்றும் மடிக் கணினிகளின் விசேஷ விசைகளுக்கு இந்த சொருகு சாதனம் ஆதரவளிக்கிறது. +Comment[tg]=Ин модул пуштибонии калидҳои махсусро дар ҳамаи навъҳои забонакҳо ва компютерҳои дастӣ дармегиронад. +Comment[tr]=Bu plugin tüm klavye ve dizüstülerdeki özel tuşlar için desteği sağlar. +Comment[uk]=Цей втулок додає підтримку спеціальних клавіш для різних типів клавіатур та лептопів. +Comment[zh_CN]=此插件启用各种键盘和便携电脑的特殊按键。 +Comment[zh_TW]=這個外掛程式開啟所有鍵盤與筆記型電腦的特殊鍵支援。 +X-KDE-Library=kmilo_generic diff --git a/kmilo/kmilo_kvaio/Makefile.am b/kmilo/kmilo_kvaio/Makefile.am new file mode 100644 index 0000000..a711565 --- /dev/null +++ b/kmilo/kmilo_kvaio/Makefile.am @@ -0,0 +1,39 @@ +# This file is part of the KDE project +# Copyright (C) 2003 George Staikos + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +SUBDIRS = . kcmkvaio + +INCLUDES=-I$(srcdir)/../kmilod $(all_includes) + +kde_module_LTLIBRARIES = kmilo_kvaio.la + +kmilo_kvaio_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kmilo_kvaio_la_LIBADD = ../kmilod/libkmilo.la $(LIB_KIO) -lXext -lXtst +kmilo_kvaio_la_SOURCES = kmilo_kvaio.cpp kvaiodriverinterface.cpp kvaio.cpp + +METASOURCES = AUTO + +KDE_OPTIONS = nofinal + +noinst_HEADERS = kmilo_kvaio.h kvaiodriverinterface.h kvaio.h + +services_DATA = kmilo_kvaio.desktop +servicesdir = $(kde_servicesdir)/kmilo + +messages: + $(XGETTEXT) $(kmilo_kvaio_la_SOURCES) -o $(podir)/kmilo_kvaio.pot diff --git a/kmilo/kmilo_kvaio/README.sonypi.h b/kmilo/kmilo_kvaio/README.sonypi.h new file mode 100644 index 0000000..5940b38 --- /dev/null +++ b/kmilo/kmilo_kvaio/README.sonypi.h @@ -0,0 +1,18 @@ +(C) 2003, 2004: Mirko Boehm +Licensed under the terms of the LGPL. + +This file explains the bad hack of copying the sonypi.h header file into this +directory: +----------------------------------------------------------------------------- + +Along with glibc, an outdated header snapshot is installed. The event +definitions in include/linux/sonypi.h in newer kernels differ too much from +it. Since the code shipped here depends on the proper event definitions, I +decided to ship a copy of a more up to date include file here. + +The solution is not optimal, but it works, and I try to keep the files in this +directory up to date. + +If somebody knows a better solution, please let me know at mirko@kde.org. + + diff --git a/kmilo/kmilo_kvaio/kcmkvaio/Makefile.am b/kmilo/kmilo_kvaio/kcmkvaio/Makefile.am new file mode 100644 index 0000000..6555b6c --- /dev/null +++ b/kmilo/kmilo_kvaio/kcmkvaio/Makefile.am @@ -0,0 +1,15 @@ +kde_module_LTLIBRARIES = kcm_kvaio.la + +kcm_kvaio_la_SOURCES = kcmkvaio_general.ui main.cpp + +kcm_kvaio_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kcm_kvaio_la_LIBADD = ../kvaiodriverinterface.lo $(LIB_KDEUI) + +INCLUDES= $(all_includes) + +kcm_kvaio_la_METASOURCES = AUTO + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcmkvaio.pot + +xdg_apps_DATA = kvaio.desktop diff --git a/kmilo/kmilo_kvaio/kcmkvaio/kcmkvaio_general.ui b/kmilo/kmilo_kvaio/kcmkvaio/kcmkvaio_general.ui new file mode 100644 index 0000000..ac376f3 --- /dev/null +++ b/kmilo/kmilo_kvaio/kcmkvaio/kcmkvaio_general.ui @@ -0,0 +1,273 @@ + +KCMKVaioGeneral + + + KCMKVaioGeneral + + + + 0 + 0 + 536 + 226 + + + + KVaio: General Options + + + + unnamed + + + 0 + + + + tlOff + + + NoFrame + + + Plain + + + Cannot find the <i>Sony Programmable Interrupt Controller</i>. If this is a Sony Vaio Laptop, make sure the <b>sonypi</b> driver module loads without failures. + + + + + frameMain + + + NoFrame + + + Plain + + + + unnamed + + + 0 + + + + bgBattery + + + System Power + + + + unnamed + + + + mTLBattery + + + Remaining battery capacity: + + + AlignVCenter|AlignRight + + + + + mKPBattery + + + + + kledAC + + + Off + + + Rectangular + + + + 0 + 255 + 0 + + + + + + tlAC + + + + + + + AC + + + AlignVCenter|AlignLeft + + + + + kledBat1 + + + + 5 + 5 + 0 + 0 + + + + Off + + + Rectangular + + + + 255 + 255 + 0 + + + + + + tlBat1 + + + + + + + Bat 1 + + + AlignVCenter|AlignLeft + + + + + kledBat2 + + + Off + + + Rectangular + + + Raised + + + + 255 + 255 + 0 + + + + + + tlBat2 + + + + + + + Bat 2 + + + AlignVCenter|AlignLeft + + + + + + + bgGeneral + + + Other Options + + + + unnamed + + + + mCbPowerMsgs + + + Periodically inform about battery and AC adapter status + + + + + mCbBackButtonMsg + + + Show battery and AC status on Back button press + + + + + cbReportUnknownEvents + + + Report unhandled events using On Screen Display + + + + + + + + + + + cbReportUnknownEvents + toggled(bool) + KCMKVaioGeneral + slotChanged() + + + mCbPowerMsgs + toggled(bool) + KCMKVaioGeneral + slotChanged() + + + mCbBackButtonMsg + toggled(bool) + KCMKVaioGeneral + slotChanged() + + + + kcmkvaio_general.ui.h + + + changed(); + + + slotChanged() + + + + + kprogress.h + kled.h + kled.h + kled.h + + diff --git a/kmilo/kmilo_kvaio/kcmkvaio/kcmkvaio_general.ui.h b/kmilo/kmilo_kvaio/kcmkvaio/kcmkvaio_general.ui.h new file mode 100644 index 0000000..96d4938 --- /dev/null +++ b/kmilo/kmilo_kvaio/kcmkvaio/kcmkvaio_general.ui.h @@ -0,0 +1,15 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ +#include + +void KCMKVaioGeneral::slotChanged() +{ + emit(changed()); +} + diff --git a/kmilo/kmilo_kvaio/kcmkvaio/kvaio.desktop b/kmilo/kmilo_kvaio/kcmkvaio/kvaio.desktop new file mode 100644 index 0000000..12be7eb --- /dev/null +++ b/kmilo/kmilo_kvaio/kcmkvaio/kvaio.desktop @@ -0,0 +1,146 @@ +[Desktop Entry] +Type=Application +Exec=kcmshell kvaio +Icon=laptop +DocPath=kcontrol/kvaio/index.html + +X-KDE-Library=kvaio +X-KDE-ParentApp=kcontrol + +Name=Sony Vaio Laptop +Name[ar]=حاسوب سونى فايو المحمولة +Name[bg]=Лаптоп Sony Vaio +Name[br]=Hezoug Sony Vaio +Name[bs]=Sony Vaio laptop +Name[ca]=Portàtil Sony Vaio +Name[cs]=Sony Vaio notebook +Name[cy]=Gluniadur Sony Vaio +Name[da]=Sony Vaio bærbar +Name[de]=Sony Vaio Notebook +Name[el]=Φορητός υπολογιστής Sony Vaio +Name[es]=Portátil Sony Vaio +Name[et]=Sony Vaio sülearvuti +Name[eu]=Sony Vaio Magalekoa +Name[fa]=Sony Vaio رایانۀ کیفی +Name[fi]=Sony Vaio -liitännäinen +Name[fr]=Portable Vaio de Sony +Name[ga]=Ríomhaire Glúine Sony Vaio +Name[he]=מחשב ברכיים מסוג Sony Vaio +Name[hu]=Sony Vaio noteszgép +Name[is]=Sony Vaio kjöltutölva +Name[it]=Portatile Sony Vaio +Name[ja]=Sony Vaio ラップトップ +Name[kk]=Sony Vaio ноутбугі +Name[km]=កុំព្យូទ័រ​យួរដៃ Sony Vaio +Name[mk]=Лаптоп Sony Vaio +Name[nb]=Programtillegg for Sony Vaio +Name[nds]=Sony Vaio-Klappreekner +Name[ne]=सोनी भाइयो लयापटप +Name[nn]=Sony Vaio-bærbar +Name[pa]=Sony Vaio ਲੈਪਟਾਪ +Name[pl]=Wtyczka Sony Vaio +Name[pt]='Plugin' para o Sony Vaio +Name[pt_BR]=Laptop Sony Vaio +Name[ro]=Laptop Sony Vaio +Name[ru]=Ноутбук Sony Vaio +Name[sk]=Sony Vaio +Name[sl]=Prenosnik Sony Vaio +Name[sr]=Sony-јев Vaio лаптоп +Name[sr@Latn]=Sony-jev Vaio laptop +Name[sv]=Sony Vaio bärbar dator +Name[ta]=சோனி வையோ மடிக் கணிப்பொறி +Name[tr]=Sony Vaio Dizüstü +Name[uk]=Лептоп Sony Vaio +Name[uz]=Sony Vaio laptopi +Name[uz@cyrillic]=Sony Vaio лаптопи +Name[zh_CN]=索尼 Vaio 插件 +Name[zh_TW]=Sony Vaio 筆記型電腦 +Comment=Configure the KDE Interface to the Sony Programmable Interrupt Controller Driver +Comment[ar]=إعداد واجهة كدى لجهاز لمشغل التحكّم بالمقاطعة القابل للبرمجة من سونى +Comment[bg]=Настройване на Sony Programmable Interrupt Controller Driver +Comment[bs]=Podesite KDE interfejs za Sony Programmable Interrupt Controler drajver +Comment[ca]=Configura la interfície entre KDE i el controlador d'interrupcions programables Sony +Comment[cs]=Nastavení KDE rozhraní ovladače programovatelného řadiče přerušení Sony +Comment[cy]=Ffurfweddu'r Rhyngwyneb KDE i'r Gyrrydd Rheolydd Ymyriadau Rhaglenadwy Sony +Comment[da]=Indstil KDE's grænseflade til Sony's programmerbare Interrupt Controller Driver +Comment[de]=Einrichten der KDE-Schnittstelle zum "Sony Programmable Interrupt Controller" Treiber +Comment[el]=Ρυθμίστε το περιβάλλον χρήσης του KDE για τον Sony Programmable Interrupt Controller Driver +Comment[es]=Configurar la interfaz de KDE para el controlador programable de interrupciones de Sony +Comment[et]=KDE liides Sony programmeeritava katkestuskontrolleri draiveri seadistamiseks +Comment[eu]=Konfiguratu Sonyren Interrupzio Kontrolatzaile Programagarriaren Gidariarentzako KDE Interfazea +Comment[fa]=پیکربندی واسط KDE در گردانندۀ کنترل‌کنندۀ قابل برنامه‌ریزی دارای وقفه +Comment[fi]=Aseta KDE:n liityntää Sonyn ohjelmoitavalle keskeytysajurille +Comment[fr]=Configuration de l'interface KDE pour le pilote du contrôleur d'interruption programmable de Sony +Comment[ga]=Cumraigh comhéadan KDE do Tiománaí an Rialtóir Idirbhriste Inríomhchláraithe Sony +Comment[hi]=केडीई इंटरफेस को सोनी प्रोग्रामेबल इंटरप्ट कन्ट्रोलर ड्राइवर के लिए कॉन्फ़िगर करता है +Comment[hu]=A Sony Vaio noteszgépek speciális kezelőelemeinek beállítása +Comment[is]=Stilla viðmót KDE á Sony Programmable Interrupt stýringuna +Comment[it]=Configura l'interfaccia KDE al driver del controller programmabile interrupt Sony +Comment[ja]=Sony Programmable Interrupt Controller Driver の KDE インターフェースを設定 +Comment[kk]=Sony бағдарламаулы үзілім контроллердің драйверінің KDE интерфейсін баптау +Comment[km]=កំណត់​រចនា​សម្ព័ន្ធ​ចំណុច​ប្រទាក់ KDE ទៅ​កម្មវិធី​បញ្ជា Sony Programmable Interrupt Controller +Comment[lt]=KDE sąsaja Sony Programmable Interrupt Controller Driver konfigūravimui +Comment[ms]= Selaraskan Antaramuka KDE untuk Pemacu Pengawal Gangguan Boleh Aturcara Sony +Comment[nb]=Sett opp KDE-grensesnitt til Sony Programmable Interrupt Controller Driver +Comment[nds]=KDE-Koppelsteedinstellen för den programmeerboren Interrupt-Controller-Driever vun Sony +Comment[ne]=सोनी कार्यक्रमयोग्य अवरोध नियन्त्रक ड्राइभरमा KDE इन्टरफेस कन्फिगर गर्नुहोस् +Comment[nl]=Voor het instellen van KDE's communicatie met het stuurprogramma van de Sony Programmeerbare Interrupt Controller +Comment[nn]=Set opp KDE-grensesnittet til Sony Programmable Interrupt Controller Driver +Comment[pl]=Konfigurujacja sterownika programowalnego kontrolora przerwań Sony w KDE +Comment[pt]=Configurar a Interface para o KDE do Controlador do Programmable Interrupt Controller da Sony +Comment[pt_BR]=Configura a Interface do KDE para o Driver Controlador de Interrupção Programável da Sony +Comment[ro]=Configurează interfaţa KDE către modulul Sony de control al întreruperilor +Comment[ru]=Настройка интерфейса KDE для драйвера программируемого контроллера прерываний Sony +Comment[sk]=Nastavenie rozhrania KDE k Sony Programmable Interrupt Controller Driver +Comment[sl]=Nastavite vmesnik KDE za gonilnik Sony Programmable Interrupt Controller +Comment[sr]=Подесите KDE-ов интерфејс за управљачки програм Sony-јевог програмабилног контролера прекида +Comment[sr@Latn]=Podesite KDE-ov interfejs za upravljački program Sony-jevog programabilnog kontrolera prekida +Comment[sv]=Anpassa KDE:s gränssnitt till Sonys drivrutin för programmerbar avbrottshantering +Comment[ta]=சோனி நிரல் தடங்கல் கட்டுப்பாட்டு சாதனத்துக்கு கேடிஇ இடைமுகத்தை வடிவமை +Comment[tg]=Танзимкунии Интерфейси KDE барои Гардонандаи Танзимкунандаи кандашавии барномавии Sony +Comment[tr]=KDE arayüzünü Sony Programlanabilir Kesilme Kontrolör Sürücüsüne ayarla +Comment[uk]=Налаштування інтерфейсу KDE до драйвера перепин Sony +Comment[zh_CN]=配置 KDE 界面使用索尼可编程中断控制器驱动程序 +Comment[zh_TW]=設定 Sony 可編程中斷控制器驅動程式的 KDE 介面 +Keywords=Sony, Vaio, kvaio, brightness, mute, Jog Dial +Keywords[ca]=Sony, Vaio, kvaio, brillantor, silenci, Jog Dial +Keywords[cs]=Sony,Vaio,kvaio,jas,ztlumení,Jog Dial +Keywords[cy]=Sony, Vaio, kvaio, gloywder, mud, Jog Dial +Keywords[da]=Sony, Vaio, kvaio, lysstyrke, stum, Jog Dial +Keywords[de]=Sony, Vaio, kvaio, brightness, mute, Jog Dial, stumm, hell, dunkel +Keywords[el]=Sony, Vaio, kvaio, φωτεινότητα, κλείσιμο ήχου, Jog Dial +Keywords[es]=Sony, Vaio, kvaio, brillo, mute, Jog Dial +Keywords[et]=Sony, Vaio, kvaio, heledus, tumm, Jog Dial +Keywords[eu]=Sony, Vaio, kvaio, distira, mutu, Jog Dial +Keywords[fa]=Sony،Vaio، kvaio، روشنایی، بدون صدا، Jog Dial +Keywords[fi]=Sony, Vaio, kvaio, kirkkaus, vaimenna, Jog Dial +Keywords[fr]=Sony, Vaio, kvaio, luminosité, sourdine, mute, Jog Dial +Keywords[ga]=Sony, Vaio, kvaio, gile, gan fuaim, Jog Dial +Keywords[hi]=सोनी,वायो,के-वायो,चमकीलापन,म्यूट,जॉग डायल +Keywords[hu]=Sony,Vaio,kvaio,fényerő,elnémítás,tárcsagomb +Keywords[it]=Sony,Vaio,kvaio,luminosità,muto,Jog Dial +Keywords[ja]=Sony, Vaio, kvaio, 明るさ, ミュート, ジョグダイアル +Keywords[mk]=Sony, Vaio, kvaio, brightness, mute, Jog Dial, Сони, осветленост, пригушување +Keywords[ms]= kecerahan,bisu,Sony, Vaio, kvaio, brightness, mute, Jog Dial +Keywords[nb]=Sony, Vaio, kvaio, lysstyrke, lydsperre, Jog Dial +Keywords[nds]=Sony, Vaio, kvaio, Helligkeit, stumm, Jog Dial +Keywords[ne]=सोनी, भाइयो, केभाइयो, चम्किलोपना, चुप लाग्नु, जोग डायल +Keywords[nl]=Sony,Vaio,kvaio,brightness,helderheid,mute,Jog Dial +Keywords[nn]=Sony,vaio,kvaio,lysstyrke,lydsperre,hjul +Keywords[pl]=Sony, Vaio, kvaio, jasność, Jog Dial,jog,jogdial +Keywords[pt]=Sony, Vaio, kvaio, brilho, sem som, Jog Dial +Keywords[pt_BR]=Sony, Vaio, kvaio,brilho, mudo, Jog Dial +Keywords[ro]=Sony,Vaio,kvaio,strălucire,fără sunet,jog dial +Keywords[ru]=Sony, Vaio, kvaio, brightness, mute, Jog Dial, яркость, звук +Keywords[sk]=Sony, Vaio, kvaio, jas, potichu, Jog Dial +Keywords[sl]=Sony, Vaio, kvaio, svetlost, tiho, Jog Dial +Keywords[sr]=Sony, Vaio, kvaio, brightness, mute, Jog Dial, светлина +Keywords[sr@Latn]=Sony, Vaio, kvaio, brightness, mute, Jog Dial, svetlina +Keywords[sv]=Sony, Vaio, kvaio, ljusstyrka, tyst, rullhjul +Keywords[ta]=சோனி, வையொ, வெளிச்சம்,சத்தமில்லாத,ஜோக் டயல் +Keywords[tg]=Sony, Vaio, kvaio, равшанӣ, хомӯшӣ, Jog Dial +Keywords[tr]=Sony, Vaio, kvaio, parlaklık, sessiz, gösterme itmesi +Keywords[uk]=Sony, Vaio, kvaio, яскравість, вимкнення звуку +Keywords[zh_CN]=Sony, Vaio, kvaio, brightness, mute, Jog Dial,索尼,亮度,静音 + +Categories=Qt;KDE;X-KDE-settings-system; diff --git a/kmilo/kmilo_kvaio/kcmkvaio/main.cpp b/kmilo/kmilo_kvaio/kcmkvaio/main.cpp new file mode 100644 index 0000000..ce27c94 --- /dev/null +++ b/kmilo/kmilo_kvaio/kcmkvaio/main.cpp @@ -0,0 +1,176 @@ +/* + * main.cpp + * + * Copyright (C) 2003 Mirko Boehm (mirko@kde.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "kcmkvaio_general.h" + +#include + +#include "main.h" +#include "main.moc" + +typedef KGenericFactory KVaioModuleFactory; +K_EXPORT_COMPONENT_FACTORY( kcm_kvaio, KVaioModuleFactory("kcmkvaio")) + +#define CONFIG_FILE "kmilodrc" + + +KVaioModule::KVaioModule(QWidget *parent, const char *name, const QStringList &) + : KCModule(KVaioModuleFactory::instance(), parent, name) +{ + KAboutData *about = + new KAboutData(I18N_NOOP("kcmkvaio"), + I18N_NOOP("KDE Control Module for Sony " + "Vaio Laptop Hardware"), + 0, 0, KAboutData::License_GPL, + "(c) 2003 Mirko Boehm"); + + about->addAuthor("Mirko Boehm", + I18N_NOOP("Original author"), + "mirko@kde.org"); + setAboutData( about ); + + QVBoxLayout *layout = new QVBoxLayout(this); + mKVaioGeneral = new KCMKVaioGeneral(this); + layout->addWidget( mKVaioGeneral ); + layout->addStretch(); + + mDriver = new KVaioDriverInterface(this); + mDriverAvailable = mDriver->connectToDriver(false); + mTimer = new QTimer(this); + mTimer->start(231); + + load(); + if (! mDriverAvailable) + { + mKVaioGeneral->tlOff->show(); + mKVaioGeneral->frameMain->setEnabled(false); + setButtons(buttons() & ~Default); + } else { + mKVaioGeneral->tlOff->hide(); + // mKVaioGeneral->frameMain->setEnabled (true); + } + + connect(mKVaioGeneral, SIGNAL(changed()), + SLOT(changed())); + connect(mTimer, SIGNAL(timeout()), SLOT(timeout())); + connect(mDriver, SIGNAL (vaioEvent(int)), SLOT (vaioEvent(int) ) ); +} + +void KVaioModule::save() +{ + if (! mDriverAvailable) return; + DCOPClient mClient; + + kdDebug() << "KVaioModule: saving." << endl; + KConfig config(CONFIG_FILE); + + config.setGroup("KVaio"); + + config.writeEntry("Report_Unknown_Events", + mKVaioGeneral->cbReportUnknownEvents->isChecked()); + config.writeEntry("PeriodicallyReportPowerStatus", + mKVaioGeneral->mCbPowerMsgs->isChecked() ); + config.writeEntry("PowerStatusOnBackButton", + mKVaioGeneral->mCbBackButtonMsg->isChecked() ); + config.sync(); + + if(mClient.attach()) + { + QByteArray data, replyData; + QCString replyType; + + if (!mClient.call("kded", "kmilod", "reconfigure()", + data, replyType, replyData)) + { + kdDebug() << "KVaio::showTextMsg: " + << "there was some error using DCOP." << endl; + } + } else { + kdDebug() << "KVaioModule: cannot attach to DCOP server, " + << "no automatic config update." << endl; + } +} + +void KVaioModule::load() +{ + load( false ); +} + +void KVaioModule::load(bool useDefaults) +{ + kdDebug() << "KVaioModule: loading." << endl; + KConfig config(CONFIG_FILE); + + config.setReadDefaults( useDefaults ); + + config.setGroup("KVaio"); + mKVaioGeneral->cbReportUnknownEvents->setChecked + (config.readBoolEntry("Report_Unknown_Events", false)); + mKVaioGeneral->mCbPowerMsgs->setChecked + (config.readBoolEntry("PeriodicallyReportPowerStatus", false) ); + mKVaioGeneral->mCbBackButtonMsg->setChecked + (config.readBoolEntry("PowerStatusOnBackButton", true) ); + + emit changed( useDefaults ); +} + +void KVaioModule::defaults() +{ + load( true ); +} + +void KVaioModule::timeout() +{ + bool bat1Avail = false, bat2Avail = false, acConnected = false; + int bat1Remaining = 0, bat1Max = 0, bat2Remaining = 0, bat2Max = 0; + + if(mDriver->getBatteryStatus(bat1Avail, bat1Remaining, bat1Max, + bat2Avail, bat2Remaining, bat2Max, + acConnected) ) + { + } + int remaining = (int)(100.0*(bat1Remaining+bat2Remaining) + / (bat1Max+bat2Max)); + mKVaioGeneral->mKPBattery->setValue(remaining); + mKVaioGeneral->kledBat1->setState(bat1Avail ? KLed::On : KLed::Off); + mKVaioGeneral->kledBat2->setState(bat2Avail ? KLed::On : KLed::Off); + mKVaioGeneral->kledAC->setState(acConnected ? KLed::On : KLed::Off); +} + +void KVaioModule::vaioEvent (int e) +{ + kdDebug () << "KVaioModule::vaioEvent: event: " << e << endl; +} + diff --git a/kmilo/kmilo_kvaio/kcmkvaio/main.h b/kmilo/kmilo_kvaio/kcmkvaio/main.h new file mode 100644 index 0000000..c19b648 --- /dev/null +++ b/kmilo/kmilo_kvaio/kcmkvaio/main.h @@ -0,0 +1,53 @@ +/* + * main.h + * + * Copyright (C) 2003 Mirko Boehm (mirko@kde.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef KCMKVAIO_MAIN_H +#define KCMKVAIO_MAIN_H + +#include +#include "../kvaiodriverinterface.h" + +class QTimer; +class KCMKVaioGeneral; + +class KVaioModule : public KCModule +{ + Q_OBJECT + +public: + KVaioModule(QWidget *parent, const char *name, const QStringList &); + + void save(); + void load(); + void load(bool useDefaults); + void defaults(); + +protected slots: + void timeout(); + void vaioEvent (int); +private: + KCMKVaioGeneral *mKVaioGeneral; + KVaioDriverInterface *mDriver; + QTimer *mTimer; + bool mDriverAvailable; +}; + +#endif // KCMKVAIO_MAIN_H diff --git a/kmilo/kmilo_kvaio/kmilo_kvaio.cpp b/kmilo/kmilo_kvaio/kmilo_kvaio.cpp new file mode 100644 index 0000000..6389759 --- /dev/null +++ b/kmilo/kmilo_kvaio/kmilo_kvaio.cpp @@ -0,0 +1,68 @@ +/* -*- C++ -*- + + This file implements the KVaio module for KMilo. + + $ Author: Mirko Boehm $ + $ Copyright: (C) 1996-2003, Mirko Boehm $ + $ Contact: mirko@kde.org + http://www.kde.org + http://www.hackerbuero.org $ + $ License: LGPL with the following explicit clarification: + This code may be linked against any version of the Qt toolkit + from Troll Tech, Norway. $ + + $Id$ + + * Portions of this code are + * (C) 2001-2002 Stelian Pop and + * (C) 2001-2002 Alcove . + * Thanks to Stelian for the implementation of the sonypi driver. +*/ + +#include + +#include "monitor.h" +#include "kmilo_kvaio.h" +#include "kvaio.h" +#include "kmilointerface.h" + +KMiloKVaio::KMiloKVaio(QObject *parent, const char *name, + const QStringList& args) + : Monitor(parent, name, args), + m_kvaio(0) +{ + _poll = false; + m_displayType = (Monitor::DisplayType)None ; +} + + +KMiloKVaio::~KMiloKVaio() { +} + + +bool KMiloKVaio::init() +{ + m_kvaio = new KVaio(this); + + return m_kvaio->driver()!=0; +} + + +KMilo::Monitor::DisplayType KMiloKVaio::poll() { +// Monitor::DisplayType rc = (Monitor::DisplayType)None; +// return rc; + return m_displayType; +} + + +int KMiloKVaio::progress() const { + return m_kvaio->progress(); +} + +void KMiloKVaio::reconfigure(KConfig* k) +{ + m_kvaio->loadConfiguration(k); +} + +K_EXPORT_COMPONENT_FACTORY(kmilo_kvaio, KGenericFactory("kmilo_kvaio")) + diff --git a/kmilo/kmilo_kvaio/kmilo_kvaio.desktop b/kmilo/kmilo_kvaio/kmilo_kvaio.desktop new file mode 100644 index 0000000..5539734 --- /dev/null +++ b/kmilo/kmilo_kvaio/kmilo_kvaio.desktop @@ -0,0 +1,106 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KMilo Plugin +X-KDE-ModuleType=Plugin +Name=Sony Vaio Plugin +Name[ar]=ملحق سونى فايوة +Name[br]=Lugent an hezoug Sony Vaio +Name[bs]=Sony Vaio dodatak +Name[ca]=Connector Sony Vaio +Name[cs]=Sony Vaio modul +Name[cy]=Ategyn Sony Vaio +Name[da]=Sony Vaio plugin +Name[el]=Πρόσθετο Sony Vaio +Name[es]=Extensión para Sony Vaio +Name[et]=Sony Vaio plugin +Name[eu]=Sony Vaio Plugina +Name[fa]=وصلۀ Sony Vaio +Name[fi]=Sony Vaio -liitännäinen +Name[fr]=Module externe pour les Vaio de Sony +Name[ga]=Breiseán Sony Vaio +Name[he]=תוסף ל-Sony Vaio +Name[hi]=सोनी वायो प्लगइन +Name[hu]=Sony Vaio bővítőmodul +Name[is]=Sony Vaio íforrit +Name[it]=Plugin per Sony Vaio +Name[ja]=Sony Vaio プラグイン +Name[ka]=Sony Vaio მოდული +Name[kk]=Sony Vaio модулі +Name[km]=កម្មវិធី​ជំនួយ Sony Vaio +Name[lt]=Sony Vaio priedas +Name[mk]=Приклучок за Sony Vaio +Name[nb]=Programtillegg for Sony Vaio +Name[nds]=Sony Vaio-Moduul +Name[ne]=सोनी भाइयो प्लगइन +Name[nl]=Sony Vaio-plugin +Name[nn]=Tilleggsprogram for Sony Vaio +Name[pa]=Sony Vaio ਪਲੱਗਿੰਨ +Name[pl]=Wtyczka Sony Vaio +Name[pt]='Plugin' para o Sony Vaio +Name[pt_BR]=Plugin do Sony Vaio +Name[ro]=Modul Sony Vaio +Name[ru]=Модуль Sony Vaio +Name[sk]=Modul pre Sony Vaio +Name[sl]=Vstavek za Sony Vaio +Name[sr]=Прикључак за Sony-јев Vaio +Name[sr@Latn]=Priključak za Sony-jev Vaio +Name[sv]=Sony Vaio-insticksprogram +Name[ta]=சோனி வையோ சொருகு சாதனம் +Name[tg]=Модули Sony Vaio +Name[tr]=Sony Vaio Eklentisi +Name[uk]=Втулок Sony Vaio +Name[uz]=Sony Vaio plagini +Name[uz@cyrillic]=Sony Vaio плагини +Name[wa]=Tchôke-divins Sony Vaio +Name[zh_CN]=索尼 Vaio 插件 +Name[zh_TW]=Sony Vaio 外掛程式 +Comment=KMilo Module for Sony Vaio Laptop support +Comment[ar]=وحدة KMilo لدعم حاسوب سونى فايو المحمول +Comment[bg]=Модул за поддръжка на KMilo за лаптопи Sony Vaio +Comment[bs]=KMilo modul za podršku za Sony Vaio laptope +Comment[ca]=Mòdul KMilo per funcionar amb portàtils Sony Vaio +Comment[cs]=KMilo modul pro podporu notebooků Sony Vaio +Comment[cy]=Cynhaliaeth Modiwl KMilo ar gyfer Gluniadur Sony Vaio +Comment[da]=KMilo Modul for understøttelse af Sony Vaio bærbare +Comment[de]=KMilo-Modul für Sony Vaio Notebook-Unterstützung +Comment[el]=Πρόσθετο KMilo για υποστήριξη του φορητού Sony Vaio +Comment[es]=Módulo KMilo para el soporte del portátil Sony Vaio +Comment[et]=KMilo moodul Sony Vaio sülearvuti toega +Comment[eu]=KMilo Moduloa Sony Vaio Magalekoen euskarriarentzako +Comment[fa]=پیمانۀ KMilo برای پشتیبانی رایانۀ کیفی Sony Vaio +Comment[fi]=KMilo-moduuli Sony Vaio -kannettavatuelle +Comment[fr]=Module KMilo pour la gestion des portables Vaio de Sony +Comment[ga]=Modúl KMilo a thacaíonn le Sony Vaio +Comment[he]=KMilo מודול לתמיכה במחשב הברכיים Vaio של Sony +Comment[hi]=सोनी वायो लेपटॉप समर्थन के लिए के-मिलो मॉड्यूल +Comment[hu]=KMilo beállítómodul Sony Vaio noteszgépek beállításához +Comment[is]=KMilo eining fyrir Sony Vaio kjöltutölvur +Comment[it]=Modulo di KMilo per il supporto dei portatili Sony Vaio +Comment[ja]=Sony Vaio ラップトップをサポートする KMilo モジュール +Comment[ka]=Sony Vaio ლეპტოპის მხარდამჭერი KMilo მოდული +Comment[kk]=Sony Vaio ноутбукті қолдау KMilo модулі +Comment[km]=ម៉ូឌុល KMilo សម្រាប់​ការគាំទ្រ​កុំព្យូទ័រ​យួរដៃ Sony Vaio +Comment[lt]=KMilo modulis Sony Vaio Laptop palaikymui +Comment[mk]=Модул од KMilo за поддршка за лаптопот Sony Vaio +Comment[nb]=KMilo modul for Sony Vaio bærbar maskin +Comment[nds]=KMilo-Moduul för Sony-Vaio-Klappreeknerünnerstütten +Comment[ne]=सोनी भाइयो ल्यापटप समर्थनका लागि केमिलो मोड्युल +Comment[nl]=KMilo-module met ondersteuning voor de Sony Vaio laptop +Comment[nn]=KMilo-modul for Sony Vaio bærbar maskin +Comment[pl]=Moduł KMilo do obsługi laptopów Sony Vaio +Comment[pt]=Módulo do KMilo para o suporte do portátil Vaio da Sony +Comment[pt_BR]= Módulo para o suporte ao Sony Vaio +Comment[ro]=Modul KMilo pentru suport laptop Sony Vaio +Comment[ru]=Модуль KMilo для ноутбуков Sony Vaio +Comment[sk]=Module pre podporu Sony Vaio pre KMilo +Comment[sl]=Modul KMilo za podporo prenosniku Sony Vaio +Comment[sr]=KMilo, модул за подршку Sony-јевог Vaio лаптопа +Comment[sr@Latn]=KMilo, modul za podršku Sony-jevog Vaio laptopa +Comment[sv]=Kmilo-modul för stöd av bärbar Sony Vaio-dator +Comment[ta]=சோனி வையோ மடிக் கணினி ஆதரவுக்கான கேமிலோ கூறு +Comment[tg]=Модули KMilo барои пуштибонии Компютери дастии Sony Vaio +Comment[tr]=Sony Vaio Dizüstüler için KMilo Modül desteği +Comment[uk]=Модуль KMilo, що додає підтримку лептопів Sony Vaio +Comment[zh_CN]=索尼 Vaio 便携电脑支持的 KMilo 模块 +Comment[zh_TW]=支援 Sony Vaio 筆記型電腦的 KMilo 模組 +X-KDE-Library=kmilo_kvaio diff --git a/kmilo/kmilo_kvaio/kmilo_kvaio.h b/kmilo/kmilo_kvaio/kmilo_kvaio.h new file mode 100644 index 0000000..fccd7e9 --- /dev/null +++ b/kmilo/kmilo_kvaio/kmilo_kvaio.h @@ -0,0 +1,66 @@ +/* -*- C++ -*- + + This file declares the KVaio module for KMilo. + + $ Author: Mirko Boehm $ + $ Copyright: (C) 1996-2003, Mirko Boehm $ + $ Contact: mirko@kde.org + http://www.kde.org + http://www.hackerbuero.org $ + $ License: LGPL with the following explicit clarification: + This code may be linked against any version of the Qt toolkit + from Troll Tech, Norway. $ + + $Id$ + + * Portions of this code are + * (C) 2001-2002 Stelian Pop and + * (C) 2001-2002 Alcove . + * Thanks to Stelian for the implementation of the sonypi driver. +*/ + +#ifndef _KMILO_KVAIO_H_ +#define _KMILO_KVAIO_H_ + +#include +#include +#include +#include + +#include "kmilod.h" +#include "monitor.h" +#include "kmilointerface.h" + +class KVaio; + +class KMiloKVaio : public KMilo::Monitor { +// Q_OBJECT + + public: + KMiloKVaio(QObject *parent, + const char *name, const QStringList&); + virtual ~KMiloKVaio(); + + virtual bool init(); + virtual DisplayType poll(); + virtual int progress() const; + + virtual void reconfigure(KConfig*); + + + bool showTextMsg(const QString& msg) { + _interface->displayText(msg); + return true; + } + bool showProgressMsg(const QString& msg, int progress) { + _interface->displayProgress(msg,progress); + return true; + } + + private: + KVaio *m_kvaio; + Monitor::DisplayType m_displayType; +}; + + +#endif diff --git a/kmilo/kmilo_kvaio/kvaio.cpp b/kmilo/kmilo_kvaio/kvaio.cpp new file mode 100644 index 0000000..8a02098 --- /dev/null +++ b/kmilo/kmilo_kvaio/kvaio.cpp @@ -0,0 +1,606 @@ +/* -*- C++ -*- + + This file implements the KVaio class. + + $ Author: Mirko Boehm $ + $ Copyright: (C) 1996-2003, Mirko Boehm $ + $ Contact: mirko@kde.org + http://www.kde.org + http://www.hackerbuero.org $ + $ License: LGPL with the following explicit clarification: + This code may be linked against any version of the Qt toolkit + from Troll Tech, Norway. $ + + $Id$ + + * Portions of this code are + * (C) 2001-2002 Stelian Pop and + * (C) 2001-2002 Alcove . + * Thanks to Stelian for the implementation of the sonypi driver. + + * Modified by Toan Nguyen + * to include support for + * Fn+F2,F3,F4 (Volume) + * Fn+F5,F6 (Brightness) + * Fn+F1 (blankscreen) + * Fn+F12 (suspend to disk) +*/ + +#include + +#include "kvaio.h" +#include "kmilointerface.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include +#include +#include +#include +#include +#include +#include + +#include "./sonypi.h" +} + + +KVaio::KVaio(KMiloKVaio *parent, const char* name) + : QObject(parent, name), + mDisp(0), + mTimer (new QTimer (this) ) +{ + myparent = parent; + + mDriver = new KVaioDriverInterface(this); + + if(!mDriver->connectToDriver()) + { + delete mDriver; mDriver = 0L; + kdDebug() << "KVaio: Cannot connect to driver." << endl; + } else { + kdDebug() << "KVaio: Connected to SonyPI driver." << endl; + connect(mDriver, SIGNAL(vaioEvent(int)), SLOT(slotVaioEvent(int))); + connect (mTimer, SIGNAL (timeout ()), SLOT (slotTimeout() ) ); + mTimer->start (10000, true); + } + + mDisp = XOpenDisplay(NULL); + if(!mDisp) + { + kdDebug() << "KVaio ctor: Failed to open display. Very strange." + << endl; + } + + if(!mClient.attach()) + { + kdDebug() << "KVaio ctor: cannot attach to DCOP server." << endl; + } + + KConfig config("kmilodrc"); + + loadConfiguration(&config); + + m_mute = false; + m_progress = 0; + m_minVolume = 0; + m_maxVolume = 100; + m_volume = 50; + + m_VolumeStep = 10; + + m_brightness = 128; + m_minBright = 0; + m_maxBright = 255; + m_BrightnessStep = 16; + + kmixClient = new DCOPRef("kmix", "Mixer0"); + kmixWindow = new DCOPRef("kmix", "kmix-mainwindow#1"); +// retrieveVolume(); +// retrieveMute(); + +} + +KVaio::~KVaio() +{ + kdDebug() << "KVaio dtor: shutting down." << endl; + if(mDriver!=0) + { + mDriver->disconnectFromDriver(); + } + if(mClient.isAttached()) + { + mClient.detach(); + } +} + +void KVaio::slotVaioEvent(int event) +{ + QString text; + QTextStream stream(text, IO_WriteOnly); + + switch(event) + { + case SONYPI_EVENT_FNKEY_RELEASED: + break; + case SONYPI_EVENT_FNKEY_F1: + blankScreen(); + break; + case SONYPI_EVENT_FNKEY_F2: + mute(); + break; + case SONYPI_EVENT_FNKEY_F3: + VolumeDown(m_VolumeStep); + break; + case SONYPI_EVENT_FNKEY_F4: + VolumeUp(m_VolumeStep); + break; + case SONYPI_EVENT_FNKEY_F5: + BrightnessDown(m_BrightnessStep); + break; + case SONYPI_EVENT_FNKEY_F6: + BrightnessUp(m_BrightnessStep); + break; + case SONYPI_EVENT_FNKEY_F12: + suspendToDisk(); + break; + case SONYPI_EVENT_MEMORYSTICK_INSERT: + showTextMsg( i18n ("Memory Stick inserted") ); + break; + case SONYPI_EVENT_MEMORYSTICK_EJECT: + showTextMsg( i18n ("Memory Stick ejected") ); + break; + case SONYPI_EVENT_BACK_PRESSED: + if (mShowPowerStatusOnBackButton) + { + showBatteryStatus (true); + } + break; + default: + stream << i18n("Unhandled event: ") << event; + if(mReportUnknownEvents) showTextMsg(text); + kdDebug() << "KVaio::slotVaioEvent: event not handled." + << endl; + } +} + +bool KVaio::showTextMsg(const QString& msg) +{ + return myparent->showTextMsg(msg); +} + + + +bool KVaio::showProgressMsg(const QString& msg, int value) +{ + m_progress = value; + return myparent->showProgressMsg(msg,value); +} + +void KVaio::blankScreen() +{ + bool blankonly; + + if (isKScreensaverAvailable()) { + + QByteArray data, replyData; + QDataStream arg(data, IO_WriteOnly); + QCString replyType; + + /* Set the screensave to BlankOnly mode */ + blankonly = true; + arg << blankonly; + mClient.call("kdesktop","KScreensaverIface","setBlankOnly(bool)", + data, replyType, replyData) ; + + /* Save the screen */ + if ( !mClient.call("kdesktop", "KScreensaverIface", "save()", + data, replyType, replyData) ) + { + kdDebug() << "KVaio::blankScreen: there was some error " + << "using DCOP." << endl; + } + + /* Set the screensave to its original mode */ + blankonly = false; + arg << blankonly; + mClient.call("kdesktop","KScreensaverIface","setBlankOnly(bool)", + data, replyType, replyData) ; + + } + +} + +void KVaio::suspendToDisk() +{ + QByteArray data, replyData; + QDataStream arg(data, IO_WriteOnly); + QCString replyType; + + mClient.call("kpowersave","KPowersaveIface","do_suspendToDisk()", + data, replyType, replyData) ; +} + + +bool KVaio::isKScreensaverAvailable() +{ + if(mClient.isAttached()) + { + // kdDebug() << "KVaio::showTextMsg: attached to DCOP server." << endl; + if(mClient.isApplicationRegistered("kdesktop")) + { + QCStringList objects; + + // kdDebug() << "KVaio::showTextMsg: kded is registered at dcop server." + // << endl; + objects = mClient.remoteObjects("kdesktop"); + if(objects.contains("KScreensaverIface")) + { + // kdDebug() << "KVaio::showTextMsg: kmilod is available at kded." + // << endl; + return true; + } else { + kdDebug() << "KVaio::isKScreensaverAvailable: " + << "KScreensaverIface is NOT available at kdesktop." << endl; + return false; + } + } else { + kdDebug() << "KVaio::isKScreensaverAvailable: " + << "kdesktop is NOT registered at dcop server." << endl; + return false; + } + } else { + kdDebug() << "KVaio::isKScreensaverAvailable: " + << "kdesktop is NOT registered at dcop server." << endl; + return false; + } +} + +bool KVaio::isKMiloDAvailable() +{ + if(mClient.isAttached()) + { + // kdDebug() << "KVaio::showTextMsg: attached to DCOP server." << endl; + if(mClient.isApplicationRegistered("kded")) + { + QCStringList objects; + + // kdDebug() << "KVaio::showTextMsg: kded is registered at dcop server." + // << endl; + objects = mClient.remoteObjects("kded"); + if(objects.contains("kmilod")) + { + // kdDebug() << "KVaio::showTextMsg: kmilod is available at kded." + // << endl; + return true; + } else { + kdDebug() << "KVaio::isKMiloDAvailable: " + << "kmilod is NOT available at kded." << endl; + return false; + } + } else { + kdDebug() << "KVaio::isKMiloDAvailable: " + << "kded is NOT registered at dcop server." << endl; + return false; + } + } else { + kdDebug() << "KVaio::isKMiloDAvailable: " + << "kded is NOT registered at dcop server." << endl; + return false; + } +} + +void KVaio::loadConfiguration(KConfig *k) +{ + k->setGroup("KVaio"); + + mReportUnknownEvents = + k->readBoolEntry("Report_Unknown_Events", false); + mReportPowerStatus = + k->readBoolEntry("PeriodicallyReportPowerStatus", false); + mShowPowerStatusOnBackButton = + k->readBoolEntry("PowerStatusOnBackButton", true); + + kdDebug() << "KVaio::loadConfiguration: " << endl + << " mReportUnknownEvents: " + << mReportUnknownEvents << endl + << " mReportPowerStatus: " + << mReportPowerStatus << endl + << "mShowPowerStatusOnBackButton: " + << mShowPowerStatusOnBackButton << endl; +} + +const KVaioDriverInterface* KVaio::driver() +{ + return mDriver; +} + +void KVaio::slotTimeout () +{ + showBatteryStatus (); + mTimer->start (4000, true); +} + +bool KVaio::showBatteryStatus ( bool force ) +{ + static bool acConnectedCache = false; + static int previousChargeCache = -1; + bool bat1Avail = false, bat2Avail = false, acConnected = false; + int bat1Remaining = 0, bat1Max = 0, bat2Remaining = 0, bat2Max = 0; + bool displayBatteryMsg = false; + bool displayACStatus = false; + + QString text, acMsg; + QTextStream stream(text, IO_WriteOnly); + + // ----- + // only display on startup if mReportPowerStatus is true: + if (mReportPowerStatus==false || !force) + { + return true; + } + + // query all necessary information: + (void) mDriver->getBatteryStatus(bat1Avail, bat1Remaining, bat1Max, + bat2Avail, bat2Remaining, bat2Max, + acConnected); + + int remaining; + if ( bat1Avail || bat2Avail ) + remaining = (int)(100.0*(bat1Remaining+bat2Remaining) + / (bat1Max+bat2Max)); + else + remaining = -1; // no battery available + + if (acConnectedCache != acConnected || force) + { + displayACStatus = true; + acConnectedCache = acConnected; + } + + displayBatteryMsg = ( previousChargeCache * 100 / remaining > 1000 ) + || ( previousChargeCache * 100 / remaining > 200 && remaining < 10 ) + || force; + + + if (displayBatteryMsg) + { + previousChargeCache = remaining; + } + + // ----- prepare text messages + if (displayACStatus || displayBatteryMsg) + { + + if (displayACStatus) + { + acMsg = acConnected ? i18n ("AC Connected") : i18n ("AC Disconnected"); + } + + switch (remaining) + { + case 100: + stream << i18n("Battery is Fully Charged. "); + break; + case 5: + case 4: + case 3: + case 2: + case 1: + stream << i18n("Caution: Battery is Almost Empty (%1% remaining).").arg(remaining); + break; + case 0: + stream << i18n("Alert: Battery is Empty!"); + break; + case -1: + stream << i18n("No Battery Inserted."); + break; + default: + stream << i18n("Remaining Battery Capacity: %1%").arg( remaining ); + }; + + // show a message if the battery status changed by more then 10% or on startup + if (displayACStatus) + { + stream << endl << acMsg; + } + + return showTextMsg (text); + } else { + return true; + } +} + +void KVaio::BrightnessUp(int step) +{ + m_brightness = mDriver->brightness(); + + m_brightness += step; + if(m_brightness > m_maxBright) { + m_brightness = m_maxBright; + } + + mDriver->setBrightness(m_brightness); + showProgressMsg( i18n("Brightness"), m_brightness*100/255); +} + +void KVaio::BrightnessDown(int step) +{ + m_brightness = mDriver->brightness(); + + m_brightness -= step; + if(m_brightness < m_minBright) { + m_brightness = m_minBright; + } + + mDriver->setBrightness(m_brightness); + showProgressMsg( i18n("Brightness"), m_brightness*100/255); +} + + +void KVaio::displayVolume() +{ +// _interface->displayProgress(i18n("Volume"), m_volume); + + showProgressMsg(i18n("Volume"), m_volume); + // If we got this far, the DCOP communication with kmix works, + // so we don't have to test the result. + kmixClient->send("setMasterVolume", m_volume); + + // if mute then unmute + if (m_mute) + { + m_mute = false; + kmixClient->send("setMasterMute", m_mute); + } +} + + +bool KVaio::retrieveVolume() { + bool kmix_error = false; + + DCOPReply reply = kmixClient->call("masterVolume"); + if (reply.isValid()) + m_volume = reply; + else + kmix_error = true; + + if (kmix_error) // maybe the error occurred because kmix wasn't running + { +// _interface->displayText + showTextMsg(i18n("Starting KMix...")); + if (kapp->startServiceByDesktopName("kmix")==0) // trying to start kmix + { + // trying again + reply = kmixClient->call("masterVolume"); + if (reply.isValid()) + { + m_volume = reply; + kmix_error = false; + kmixWindow->send("hide"); + } + } + } + + if (kmix_error) + { + kdDebug() << "KMilo: GenericMonitor could not access kmix/Mixer0 via dcop" + << endl; + //_interface->displayText + showTextMsg(i18n("It seems that KMix is not running.")); + + return false; + } else { + return true; + } +} + +void KVaio::VolumeUp(int step) +{ + if (!retrieveVolume()) + return; + + // FIXME if the mixer doesn't support steps of the specified size it + // could get stuck at one position + m_volume += step; + if (m_volume > m_maxVolume) + m_volume = m_maxVolume; + + displayVolume(); +} + +void KVaio::VolumeDown(int step) +{ + if (!retrieveVolume()) + return; + + m_volume -= step; + if (m_volume < m_minVolume) + m_volume = m_minVolume; + + displayVolume(); +} + +bool KVaio::retrieveMute() +{ + bool kmix_error = false; + + DCOPReply reply = kmixClient->call("masterMute"); + if (reply.isValid()) + m_volume = reply; + else + kmix_error = true; + + if (kmix_error) + { + // maybe the error occurred because kmix wasn't running + //_interface->displayText + showTextMsg(i18n("Starting KMix...")); + if (kapp->startServiceByDesktopName("kmix")==0) // trying to start kmix + { + // trying again + reply = kmixClient->call("masterMute"); + if (reply.isValid()) + { + m_mute = reply; + kmix_error = false; + kmixWindow->send("hide"); + } + } else + { + kmixWindow->send("hide"); + kmix_error = true; + } + } + + if (kmix_error) + { + kdDebug() << "KMilo: GenericMonitor could not access kmix/Mixer0 via dcop" + << endl; + //_interface->displayText + showTextMsg(i18n("It seems that KMix is not running.")); + + return false; + } else { + return true; + } +} + +void KVaio::mute() +{ + if (!retrieveMute()) + return; + + m_mute = !m_mute; + + int newVolume; + QString muteText; + if (m_mute) + { + m_oldVolume = m_volume; + newVolume = 0; + muteText = i18n("Mute on"); + } else { + newVolume = m_oldVolume; + muteText = i18n("Mute off"); + } + + kmixClient->send("setMasterMute", m_mute); + + //_interface->displayText(muteText); + showTextMsg(muteText); + +} + + +#include "kvaio.moc" diff --git a/kmilo/kmilo_kvaio/kvaio.h b/kmilo/kmilo_kvaio/kvaio.h new file mode 100644 index 0000000..c16f27e --- /dev/null +++ b/kmilo/kmilo_kvaio/kvaio.h @@ -0,0 +1,113 @@ +/* -*- C++ -*- + + This file declares the KVaio class. + + $ Author: Mirko Boehm $ + $ Copyright: (C) 1996-2003, Mirko Boehm $ + $ Contact: mirko@kde.org + http://www.kde.org + http://www.hackerbuero.org $ + $ License: LGPL with the following explicit clarification: + This code may be linked against any version of the Qt toolkit + from Troll Tech, Norway. $ + + $Id$ + + * Portions of this code are + * (C) 2001-2002 Stelian Pop and + * (C) 2001-2002 Alcove . + * Thanks to Stelian for the implementation of the sonypi driver. +*/ + +#ifndef _KVAIO_H +#define _KVAIO_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include "kvaiodriverinterface.h" +#include "monitor.h" +#include "kmilo_kvaio.h" + +extern "C" { +#include +//#include +} + +class KVaio; +class KMiloKVaio; + +/** + * @short KVaio class + * This class provides an interface between the Vaio driver and the + * respective application (either the kmilod module or a single + * application). + * This class provides the application of the events created by the + * KVaioDriverInterface class. + * @author Mirko Boehm + * @version 0.2 + */ +class KVaio : public QObject +{ + Q_OBJECT +public: +// KVaio(QObject *parent = 0, const char *name =0); + KVaio(KMiloKVaio *parent = 0, const char *name =0); + + virtual ~KVaio(); + const KVaioDriverInterface *driver(); + void loadConfiguration(KConfig *); + const int progress() { return m_progress; } + +protected: + KVaioDriverInterface *mDriver; + Display *mDisp; + DCOPClient mClient; + bool isKScreensaverAvailable(); + bool isKMiloDAvailable(); + bool showTextMsg(const QString& msg); + bool showProgressMsg(const QString& msg, int progress); + bool showBatteryStatus ( bool force = false); +protected slots: + void slotVaioEvent(int); + void slotTimeout(); +public slots: + void blankScreen(); + void suspendToDisk(); + void BrightnessUp(int step); + void BrightnessDown(int step); + void VolumeUp(int step); + void VolumeDown(int step); + void mute(); +private: + bool retrieveMute(); + bool retrieveVolume(); + void displayVolume(); + + KMiloKVaio *myparent; + + DCOPRef *kmixClient, *kmixWindow; + + int m_progress; + int m_volume, m_oldVolume, m_brightness; + bool m_mute; + + int m_maxVolume, m_minVolume; + int m_maxBright, m_minBright; + + int m_VolumeStep; + int m_BrightnessStep; + + bool mReportUnknownEvents; + bool mReportPowerStatus; + bool mShowPowerStatusOnBackButton; + QTimer *mTimer; +}; + +#endif // _KVAIO_H diff --git a/kmilo/kmilo_kvaio/kvaiodriverinterface.cpp b/kmilo/kmilo_kvaio/kvaiodriverinterface.cpp new file mode 100644 index 0000000..32da70a --- /dev/null +++ b/kmilo/kmilo_kvaio/kvaiodriverinterface.cpp @@ -0,0 +1,221 @@ +/* -*- C++ -*- + + This file implements the KVaioDriverInterface class. + It provides an event-oriented wrapper for the kernel sonypi driver. + + $ Author: Mirko Boehm $ + $ Copyright: (C) 1996-2003, Mirko Boehm $ + $ Contact: mirko@kde.org + http://www.kde.org + http://www.hackerbuero.org $ + $ License: LGPL with the following explicit clarification: + This code may be linked against any version of the Qt toolkit + from Troll Tech, Norway. $ + + $Id$ + + * Portions of this code are + * (C) 2001-2002 Stelian Pop and + * (C) 2001-2002 Alcove . + * Thanks to Stelian for the implementation of the sonypi driver. +*/ + +#include "kvaiodriverinterface.h" + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#include "./sonypi.h" +} + +#include +#include + +// Taken from Stelian Pop's spicctrl utility: + +/* Have our own definition of ioctls... */ + +/* get/set brightness */ +#define SONYPI_IOCGBRT _IOR('v', 0, __u8) +#define SONYPI_IOCSBRT _IOW('v', 0, __u8) + +/* get battery full capacity/remaining capacity */ +#define SONYPI_IOCGBAT1CAP _IOR('v', 2, __u16) +#define SONYPI_IOCGBAT1REM _IOR('v', 3, __u16) +#define SONYPI_IOCGBAT2CAP _IOR('v', 4, __u16) +#define SONYPI_IOCGBAT2REM _IOR('v', 5, __u16) + +/* get battery flags: battery1/battery2/ac adapter present */ +#define SONYPI_BFLAGS_B1 0x01 +#define SONYPI_BFLAGS_B2 0x02 +#define SONYPI_BFLAGS_AC 0x04 +#define SONYPI_IOCGBATFLAGS _IOR('v', 7, __u8) + +/* get/set bluetooth subsystem state on/off */ +#define SONYPI_IOCGBLUE _IOR('v', 8, __u8) +#define SONYPI_IOCSBLUE _IOW('v', 9, __u8) + +KVaioDriverInterface::KVaioDriverInterface(QObject *parent) + : QObject(parent), + mFd(0), + mNotifier(0) +{ +} + +bool KVaioDriverInterface::connectToDriver(bool listen) +{ + const char* DriverFile = "/dev/sonypi"; + + mFd = open(DriverFile, O_RDONLY); + + // mFd = open(DriverFile, O_RDWR); + + if(mFd == -1) + { + kdDebug() << "KVaio: Failed to open /dev/sonypi: " + << strerror(errno) << "." << endl; + return false; + } + + fcntl(mFd, F_SETFL, fcntl(mFd, F_GETFL) | O_ASYNC); + + if(listen) + { + mNotifier = new QSocketNotifier(mFd, QSocketNotifier::Read, this); + connect(mNotifier, SIGNAL(activated(int)), SLOT(socketActivated(int))); + } + return true; +} + +void KVaioDriverInterface::disconnectFromDriver() +{ + delete mNotifier; + mNotifier = 0; + + if(mFd!=0) + { + close(mFd); + mFd = 0; + } +} + +void KVaioDriverInterface::socketActivated(int) +{ + unsigned char events[8]; + int count; + + do { + count = read(mFd, &events, sizeof(events)); + for(int index = 0; index= 0) + { + return value; + } else { + return -1; + } + +} + +void KVaioDriverInterface::setBrightness(int value) +{ + static unsigned char cache; // to avoid unnecessary updates + int result; + unsigned char value8 = 0; + + if(value<0) value=0; + if(value>255) value=255; + + value8 = __u8(value); + + if(value8 != cache) + { + result = ioctl(mFd, SONYPI_IOCSBRT, &value8); + + if(result<0) + { + kdDebug() << "KVaioDriverInterface::setBrightness: ioctl failed." + << endl; + } + cache = value8; + } +} + +bool KVaioDriverInterface::getBatteryStatus( + bool& bat1Avail, int& bat1Remaining, int& bat1Max, + bool& bat2Avail, int& bat2Remaining, int& bat2Max, + bool& acConnected) +{ + unsigned char batFlags = 0; + + bool retval = true; + + if(ioctl(mFd, SONYPI_IOCGBATFLAGS, &batFlags)<0) + { + retval = false; + } else { + __u16 rem1 = 0, rem2 = 0, cap1 = 0, cap2 = 0; + + bat1Avail = batFlags & SONYPI_BFLAGS_B1; + bat2Avail = batFlags & SONYPI_BFLAGS_B2; + acConnected = batFlags & SONYPI_BFLAGS_AC; + +// kdDebug() << "KVaioDriverInterface::getBatteryStatus: battery 1: " +// << (bat1Avail ? "available" : "not available") << endl +// << " battery 2: " +// << (bat2Avail ? "available" : "not available") << endl +// << " AC adapter: " +// << (acConnected ? "connected" : "connected") +// << "." << endl; + + if(bat1Avail + && ioctl(mFd, SONYPI_IOCGBAT1CAP, &cap1) >= 0 + && ioctl(mFd, SONYPI_IOCGBAT1REM, &rem1) >= 0) + { + bat1Max = cap1; + bat1Remaining = rem1; + } else { + bat1Remaining = 0; + bat1Max = 0; + retval = false; + } + + if(bat2Avail + && ioctl(mFd, SONYPI_IOCGBAT2CAP, &cap2) >= 0 + && ioctl(mFd, SONYPI_IOCGBAT2REM, &rem2) >= 0) + { + bat2Max = cap2; + bat2Remaining = rem2; + } else { + bat2Remaining = 0; + bat2Max = 0; + retval = false; + } + } + + return retval; +} + +#include "kvaiodriverinterface.moc" + diff --git a/kmilo/kmilo_kvaio/kvaiodriverinterface.h b/kmilo/kmilo_kvaio/kvaiodriverinterface.h new file mode 100644 index 0000000..55c32b6 --- /dev/null +++ b/kmilo/kmilo_kvaio/kvaiodriverinterface.h @@ -0,0 +1,62 @@ +/* -*- C++ -*- + + This file declares the KVaioDrierInterface class. + It provides an event-oriented wrapper for the kernel sonypi driver. + + $ Author: Mirko Boehm $ + $ Copyright: (C) 1996-2003, Mirko Boehm $ + $ Contact: mirko@kde.org + http://www.kde.org + http://www.hackerbuero.org $ + $ License: LGPL with the following explicit clarification: + This code may be linked against any version of the Qt toolkit + from Troll Tech, Norway. $ + + $Id$ +*/ + +#ifndef KVAIO_DRIVERINTERFACE_H +#define KVAIO_DRIVERINTERFACE_H + +#include + +class QTimer; + +extern "C" +{ +#include + +#include "./sonypi.h" +} + +class QSocketNotifier; + +class KVaioDriverInterface : public QObject +{ + Q_OBJECT +public: + KVaioDriverInterface(QObject *parent=0); + bool connectToDriver(bool listen = true); + void disconnectFromDriver(); + /** Return the current display brightness, a value between 0 and + 255. Returns -1 if the setting cannot be retrieved. */ + int brightness(); + /** Get the battery status. */ + bool getBatteryStatus(bool& bat1Avail, int& bat1Remaining, int& bat1Max, + bool& bat2Avail, int& bat2Remaining, int& bat2Max, + bool& acConnected); +public slots: + /** Set the display brightness. 0<= value <=255. */ + void setBrightness(int); +protected: + int mFd; + fd_set mRfds; + QSocketNotifier *mNotifier; +signals: + void vaioEvent(int); + // void brightnessChanged(int); +protected slots: + void socketActivated(int); +}; + +#endif // KVAIO_DRIVERINTERFACE_H diff --git a/kmilo/kmilo_kvaio/sonypi.h b/kmilo/kmilo_kvaio/sonypi.h new file mode 100644 index 0000000..43cfc80 --- /dev/null +++ b/kmilo/kmilo_kvaio/sonypi.h @@ -0,0 +1,158 @@ +/* + * Sony Programmable I/O Control Device driver for VAIO + * + * Copyright (C) 2001-2005 Stelian Pop + * + * Copyright (C) 2005 Narayanan R S + + * Copyright (C) 2001-2002 Alcve + * + * Copyright (C) 2001 Michael Ashley + * + * Copyright (C) 2001 Junichi Morita + * + * Copyright (C) 2000 Takaya Kinjo + * + * Copyright (C) 2000 Andrew Tridgell + * + * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _SONYPI_H_ +#define _SONYPI_H_ + +#include + +/* events the user application reading /dev/sonypi can use */ + +#define SONYPI_EVENT_JOGDIAL_DOWN 1 +#define SONYPI_EVENT_JOGDIAL_UP 2 +#define SONYPI_EVENT_JOGDIAL_DOWN_PRESSED 3 +#define SONYPI_EVENT_JOGDIAL_UP_PRESSED 4 +#define SONYPI_EVENT_JOGDIAL_PRESSED 5 +#define SONYPI_EVENT_JOGDIAL_RELEASED 6 /* obsolete */ +#define SONYPI_EVENT_CAPTURE_PRESSED 7 +#define SONYPI_EVENT_CAPTURE_RELEASED 8 /* obsolete */ +#define SONYPI_EVENT_CAPTURE_PARTIALPRESSED 9 +#define SONYPI_EVENT_CAPTURE_PARTIALRELEASED 10 +#define SONYPI_EVENT_FNKEY_ESC 11 +#define SONYPI_EVENT_FNKEY_F1 12 +#define SONYPI_EVENT_FNKEY_F2 13 +#define SONYPI_EVENT_FNKEY_F3 14 +#define SONYPI_EVENT_FNKEY_F4 15 +#define SONYPI_EVENT_FNKEY_F5 16 +#define SONYPI_EVENT_FNKEY_F6 17 +#define SONYPI_EVENT_FNKEY_F7 18 +#define SONYPI_EVENT_FNKEY_F8 19 +#define SONYPI_EVENT_FNKEY_F9 20 +#define SONYPI_EVENT_FNKEY_F10 21 +#define SONYPI_EVENT_FNKEY_F11 22 +#define SONYPI_EVENT_FNKEY_F12 23 +#define SONYPI_EVENT_FNKEY_1 24 +#define SONYPI_EVENT_FNKEY_2 25 +#define SONYPI_EVENT_FNKEY_D 26 +#define SONYPI_EVENT_FNKEY_E 27 +#define SONYPI_EVENT_FNKEY_F 28 +#define SONYPI_EVENT_FNKEY_S 29 +#define SONYPI_EVENT_FNKEY_B 30 +#define SONYPI_EVENT_BLUETOOTH_PRESSED 31 +#define SONYPI_EVENT_PKEY_P1 32 +#define SONYPI_EVENT_PKEY_P2 33 +#define SONYPI_EVENT_PKEY_P3 34 +#define SONYPI_EVENT_BACK_PRESSED 35 +#define SONYPI_EVENT_LID_CLOSED 36 +#define SONYPI_EVENT_LID_OPENED 37 +#define SONYPI_EVENT_BLUETOOTH_ON 38 +#define SONYPI_EVENT_BLUETOOTH_OFF 39 +#define SONYPI_EVENT_HELP_PRESSED 40 +#define SONYPI_EVENT_FNKEY_ONLY 41 +#define SONYPI_EVENT_JOGDIAL_FAST_DOWN 42 +#define SONYPI_EVENT_JOGDIAL_FAST_UP 43 +#define SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED 44 +#define SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED 45 +#define SONYPI_EVENT_JOGDIAL_VFAST_DOWN 46 +#define SONYPI_EVENT_JOGDIAL_VFAST_UP 47 +#define SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED 48 +#define SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED 49 +#define SONYPI_EVENT_ZOOM_PRESSED 50 +#define SONYPI_EVENT_THUMBPHRASE_PRESSED 51 +#define SONYPI_EVENT_MEYE_FACE 52 +#define SONYPI_EVENT_MEYE_OPPOSITE 53 +#define SONYPI_EVENT_MEMORYSTICK_INSERT 54 +#define SONYPI_EVENT_MEMORYSTICK_EJECT 55 +#define SONYPI_EVENT_ANYBUTTON_RELEASED 56 +#define SONYPI_EVENT_BATTERY_INSERT 57 +#define SONYPI_EVENT_BATTERY_REMOVE 58 +#define SONYPI_EVENT_FNKEY_RELEASED 59 + +/* get/set brightness */ +#define SONYPI_IOCGBRT _IOR('v', 0, __u8) +#define SONYPI_IOCSBRT _IOW('v', 0, __u8) + +/* get battery full capacity/remaining capacity */ +#define SONYPI_IOCGBAT1CAP _IOR('v', 2, __u16) +#define SONYPI_IOCGBAT1REM _IOR('v', 3, __u16) +#define SONYPI_IOCGBAT2CAP _IOR('v', 4, __u16) +#define SONYPI_IOCGBAT2REM _IOR('v', 5, __u16) + +/* get battery flags: battery1/battery2/ac adapter present */ +#define SONYPI_BFLAGS_B1 0x01 +#define SONYPI_BFLAGS_B2 0x02 +#define SONYPI_BFLAGS_AC 0x04 +#define SONYPI_IOCGBATFLAGS _IOR('v', 7, __u8) + +/* get/set bluetooth subsystem state on/off */ +#define SONYPI_IOCGBLUE _IOR('v', 8, __u8) +#define SONYPI_IOCSBLUE _IOW('v', 9, __u8) + +/* get/set fan state on/off */ +#define SONYPI_IOCGFAN _IOR('v', 10, __u8) +#define SONYPI_IOCSFAN _IOW('v', 11, __u8) + +/* get temperature (C) */ +#define SONYPI_IOCGTEMP _IOR('v', 12, __u8) + +#ifdef __KERNEL__ + +/* used only for communication between v4l and sonypi */ + +#define SONYPI_COMMAND_GETCAMERA 1 /* obsolete */ +#define SONYPI_COMMAND_SETCAMERA 2 +#define SONYPI_COMMAND_GETCAMERABRIGHTNESS 3 /* obsolete */ +#define SONYPI_COMMAND_SETCAMERABRIGHTNESS 4 +#define SONYPI_COMMAND_GETCAMERACONTRAST 5 /* obsolete */ +#define SONYPI_COMMAND_SETCAMERACONTRAST 6 +#define SONYPI_COMMAND_GETCAMERAHUE 7 /* obsolete */ +#define SONYPI_COMMAND_SETCAMERAHUE 8 +#define SONYPI_COMMAND_GETCAMERACOLOR 9 /* obsolete */ +#define SONYPI_COMMAND_SETCAMERACOLOR 10 +#define SONYPI_COMMAND_GETCAMERASHARPNESS 11 /* obsolete */ +#define SONYPI_COMMAND_SETCAMERASHARPNESS 12 +#define SONYPI_COMMAND_GETCAMERAPICTURE 13 /* obsolete */ +#define SONYPI_COMMAND_SETCAMERAPICTURE 14 +#define SONYPI_COMMAND_GETCAMERAAGC 15 /* obsolete */ +#define SONYPI_COMMAND_SETCAMERAAGC 16 +#define SONYPI_COMMAND_GETCAMERADIRECTION 17 /* obsolete */ +#define SONYPI_COMMAND_GETCAMERAROMVERSION 18 /* obsolete */ +#define SONYPI_COMMAND_GETCAMERAREVISION 19 /* obsolete */ + +int sonypi_camera_command(int command, u8 value); + +#endif /* __KERNEL__ */ + +#endif /* _SONYPI_H_ */ diff --git a/kmilo/kmilod/Makefile.am b/kmilo/kmilod/Makefile.am new file mode 100644 index 0000000..72662db --- /dev/null +++ b/kmilo/kmilod/Makefile.am @@ -0,0 +1,43 @@ +# This file is part of the KDE project +# Copyright (C) 2003 George Staikos + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +INCLUDES=$(all_includes) + +kde_module_LTLIBRARIES = kded_kmilod.la +kded_kmilod_la_LDFLAGS = -module -avoid-version $(all_libraries) +kded_kmilod_la_LIBADD = $(LIB_KIO) libkmilo.la +kded_kmilod_la_SOURCES = kmilod.cpp kmilod.skel defaultskin.cpp \ + defaultwidget.ui kmilointerface.cpp + +lib_LTLIBRARIES = libkmilo.la +libkmilo_la_SOURCES = monitor.cpp displayskin.cpp +libkmilo_la_LDFLAGS = -version-info 1:0:0 -no-undefined $(all_libraries) +libkmilo_la_LIBADD = $(LIB_QT) + +METASOURCES = AUTO + +noinst_HEADERS = kmilod.h monitor.h displayskin.h defaultskin.h + +services_DATA = kmilod.desktop +servicesdir = $(kde_servicesdir)/kded + +servicetypes_DATA = kmilopluginsvc.desktop +servicetypesdir = $(kde_servicetypesdir)/kmilo + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kmilod.pot diff --git a/kmilo/kmilod/defaultskin.cpp b/kmilo/kmilod/defaultskin.cpp new file mode 100644 index 0000000..f0324de --- /dev/null +++ b/kmilo/kmilod/defaultskin.cpp @@ -0,0 +1,107 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "defaultwidget.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "defaultskin.h" + + +DefaultSkin::DefaultSkin() { + connect(&_timer, SIGNAL(timeout()), this, SLOT(timeout())); + + _widget = new DefaultWidget(0, "Screen Indicator", Qt::WX11BypassWM); + _widget->setFocusPolicy(QWidget::NoFocus); + + KWin::setOnAllDesktops(_widget->winId(), true); + KWin::setState( _widget->winId(), NET::StaysOnTop | NET::Sticky + | NET::SkipTaskbar | NET::SkipPager ); + KWin::setType(_widget->winId(), NET::Override); + + _widget->hide(); +} + + +DefaultSkin::~DefaultSkin() { + delete _widget; + _widget = 0; +} + + +void DefaultSkin::clear() { + _timer.stop(); + _widget->hide(); +} + + +void DefaultSkin::show() { +#if KDE_IS_VERSION(3,1,90) + QRect r = KGlobalSettings::splashScreenDesktopGeometry(); +#else + QRect r = QApplication::desktop()->geometry(); +#endif + // _label->resize(_label->minimumSizeHint()); + // _widget->resize(_label->minimumSizeHint()); + _widget->move(r.center() - + QPoint(_widget->width()/2, _widget->height()/2)); + _widget->show(); + _timer.start(750, true); +} + + +void DefaultSkin::displayText(const QString& text, const QPixmap& customPixmap) { + Q_UNUSED(customPixmap) + _timer.stop(); + _widget->_widgetStack->raiseWidget(0); + _widget->_textOnly->setText(text); + show(); +} + + +void DefaultSkin::displayProgress(const QString& text, int percent, const QPixmap& customPixmap) { + Q_UNUSED(customPixmap) + _timer.stop(); + _widget->_progressText->setText(text); + _widget->_progress->setProgress(percent); + _widget->_widgetStack->raiseWidget(1); + show(); +} + + +void DefaultSkin::timeout() { + clear(); +} + + +#include "defaultskin.moc" + diff --git a/kmilo/kmilod/defaultskin.h b/kmilo/kmilod/defaultskin.h new file mode 100644 index 0000000..0e01f23 --- /dev/null +++ b/kmilo/kmilod/defaultskin.h @@ -0,0 +1,56 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _DEFAULTSKIN_H_ +#define _DEFAULTSKIN_H_ + +#include +#include +#include +#include "displayskin.h" + +class DefaultWidget; + +class DefaultSkin : public QObject, public KMilo::DisplaySkin { + Q_OBJECT + public: + DefaultSkin(); + virtual ~DefaultSkin(); + + virtual void clear(); + + virtual void displayText(const QString& text, const QPixmap& customPixmap=QPixmap()); + virtual void displayProgress(const QString& text, + int percent, const QPixmap& customPixmap=QPixmap()); + + private slots: + void timeout(); + + private: + void show(); + + DefaultWidget *_widget; + QTimer _timer; +}; + + +#endif diff --git a/kmilo/kmilod/defaultwidget.ui b/kmilo/kmilod/defaultwidget.ui new file mode 100644 index 0000000..b4809fe --- /dev/null +++ b/kmilo/kmilod/defaultwidget.ui @@ -0,0 +1,195 @@ + +DefaultWidget +Default widget for the default display for kmilod +Released under the terms of the GNU GPL. +George Staikos <staikos@kde.org + + + DefaultWidget + + + + 0 + 0 + 566 + 180 + + + + + 214 + 213 + 212 + + + + + unnamed + + + + _widgetStack + + + + 214 + 213 + 212 + + + + StyledPanel + + + Sunken + + + + page + + + 0 + + + + unnamed + + + + _textOnly + + + + 26 + 69 + 198 + + + + + 214 + 213 + 212 + + + + + 28 + 1 + + + + + + + AlignCenter + + + + + + + page + + + 1 + + + + unnamed + + + + spacer1 + + + Horizontal + + + Expanding + + + + 81 + 31 + + + + + + spacer1_2 + + + Horizontal + + + Expanding + + + + 81 + 31 + + + + + + _progress + + + + 7 + 0 + 1 + 0 + + + + + 214 + 213 + 212 + + + + false + + + + + _progressText + + + + 26 + 69 + 198 + + + + + 214 + 213 + 212 + + + + + 28 + 1 + + + + + + + AlignCenter + + + + + + + + + diff --git a/kmilo/kmilod/displayskin.cpp b/kmilo/kmilod/displayskin.cpp new file mode 100644 index 0000000..f0fd422 --- /dev/null +++ b/kmilo/kmilod/displayskin.cpp @@ -0,0 +1,34 @@ +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "displayskin.h" + +namespace KMilo { + +DisplaySkin::DisplaySkin() { +} + +DisplaySkin::~DisplaySkin() { +} + +} + diff --git a/kmilo/kmilod/displayskin.h b/kmilo/kmilod/displayskin.h new file mode 100644 index 0000000..4e74e0c --- /dev/null +++ b/kmilo/kmilod/displayskin.h @@ -0,0 +1,47 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _DISPLAYSKIN_H_ +#define _DISPLAYSKIN_H_ + +#include + +#include +#include + +namespace KMilo { + +class KDE_EXPORT DisplaySkin { + public: + DisplaySkin(); + virtual ~DisplaySkin(); + + virtual void clear() = 0; + + virtual void displayText(const QString& text,const QPixmap& customPixmap=QPixmap()) = 0; + virtual void displayProgress(const QString& text, + int percent, const QPixmap& customPixmap=QPixmap()) = 0; +}; + +} + +#endif diff --git a/kmilo/kmilod/kmilod.cpp b/kmilo/kmilod/kmilod.cpp new file mode 100644 index 0000000..98203b1 --- /dev/null +++ b/kmilo/kmilod/kmilod.cpp @@ -0,0 +1,227 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "kmilod.h" +#include "monitor.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "kmilointerface.h" +#include "defaultskin.h" + +using namespace KMilo; + +extern "C" { + KDE_EXPORT KDEDModule *create_kmilod(const QCString &name) { + return new KMiloD(name); + } +} + + +KMiloD::KMiloD(const QCString &name) : KDEDModule(name), _interval(100) +{ + _monitors.setAutoDelete(true); + _miface = new KMiloInterface(this); + + // Create the display skin object + _display = new DefaultSkin; + + bool shouldPoll = false; + + // Load the modules + KService::List plugs = KServiceType::offers("KMilo Plugin"); + for (KService::List::ConstIterator it = plugs.begin(); + it != plugs.end(); ++it) { + KService::Ptr service = *it; + KMilo::Monitor *m = KParts::ComponentFactory::createInstanceFromService(service, 0, service->desktopEntryName().latin1()); + if (m) { + m->setInterface(_miface); + if (m->init()) { + _monitors.append(m); + kdDebug() << "KMilo loaded module " + << service->property("Name").toString() + << endl; + shouldPoll = shouldPoll || m->shouldPoll(); + } else { + delete m; + } + } + } + + // Start the timer + QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(doTimer())); + if (shouldPoll) { + _timer.start(_interval); + } +} + + +KMiloD::~KMiloD() +{ + _timer.stop(); + + // Modules are automatically cleaned up when this is done. It has + // to be done before delete _display to avoid a race though. + _monitors.clear(); + + delete _display; + _display = 0L; + + delete _miface; + _miface = 0L; +} + + +void KMiloD::setEnabled(bool enabled) { + if (enabled) { + enable(); + } else { + disable(); + } +} + + +void KMiloD::enable() { + if (!_monitors.isEmpty()) { + _timer.start(_interval, false); + } +} + + +void KMiloD::disable() { + _timer.stop(); +} + + +bool KMiloD::enabled() const { + return _timer.isActive(); +} + + +int KMiloD::pollMilliSeconds() const { + return _interval; +} + + +bool KMiloD::setPollMilliSeconds(int ms) { + if (ms > 1000 || ms < 0) { + return false; + } + + if (!_monitors.isEmpty()) { + _timer.start(_interval, false); + } + + _interval = ms; + +return true; +} + + +void KMiloD::doTimer() { + // Iterate through all the modules we have and poll + for (KMilo::Monitor *m = _monitors.first(); m; m = _monitors.next()) { + if (!m->shouldPoll()) { + continue; + } + + KMilo::Monitor::DisplayType dt = m->poll(); + switch (dt) { + case KMilo::Monitor::Volume: + displayProgress(i18n("Volume"), m->progress()); + break; + case KMilo::Monitor::Brightness: + displayProgress(i18n("Brightness"), m->progress()); + break; + case KMilo::Monitor::Mute: + displayText(i18n("Muted")); + break; + case KMilo::Monitor::Tap: + displayText(m->message()); + break; + case KMilo::Monitor::Sleep: + displayText(m->message()); + break; + case KMilo::Monitor::None: + // Do nothing + break; + case KMilo::Monitor::Error: + { + // On error, remove the monitor and continue + KMilo::Monitor *n = _monitors.next(); + _monitors.remove(m); // deletes m + m = n; + } + break; + default: + kdWarning() << "Error in KMiloD. Please report." << endl; + break; + } + } +} + + +void KMiloD::displayText(const QString& text) { + _display->displayText(text, QPixmap()); +} + + +void KMiloD::displayText(const QString& text, const QPixmap& customPixmap) { + _display->displayText(text, customPixmap); +} + + +void KMiloD::displayProgress(const QString& text, int progress) { + _display->displayProgress(text, progress, QPixmap()); +} + +void KMiloD::displayProgress(const QString& text, int progress, const QPixmap& customPixmap ) { + _display->displayProgress(text, progress, customPixmap); +} + +void KMiloD::reconfigure() +{ + // load the kmilo configuration file: + KConfig config("kmilodrc"); + + KMilo::Monitor *monitor; + + for(monitor = _monitors.first(); monitor; monitor = _monitors.next()) + { + monitor->reconfigure(&config); + } +} + +#include "kmilod.moc" + diff --git a/kmilo/kmilod/kmilod.desktop b/kmilo/kmilod/kmilod.desktop new file mode 100644 index 0000000..d31dacb --- /dev/null +++ b/kmilo/kmilod/kmilod.desktop @@ -0,0 +1,59 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KDEDModule +X-KDE-ModuleType=Library +X-KDE-Library=kmilod +X-KDE-FactoryName=kmilod +X-KDE-Kded-autoload=true +X-KDE-Kded-load-on-demand=false +Name=KMilo +Name[de]=KMilo Sondertasten +Name[hi]=के-मिलो +Name[ne]=केमिलो +Name[sv]=Kmilo +Name[ta]= கேமிலோ +Comment=KDE special key notifier +Comment[ar]=مبلغ كدى للمفاتيح الخاصة +Comment[bg]=Известяване при натискане на специалните клавиши на някои модели лаптопи +Comment[bs]=KDE obavještenje o posebnim tipkama +Comment[ca]=Notificador de tecles especials de KDE +Comment[cs]=Hlášení speciálních kláves +Comment[da]=KDE Speciel tast bekendtgørelse +Comment[de]=Unterstützung für Sonder- und Multimediatasten in KDE +Comment[el]=Ειδοποιητής ειδικών πλήκτρων του KDE +Comment[eo]=KDE-specialklavatentigilo +Comment[es]=Notificador de teclas especiales de KDE +Comment[et]=KDE eriklahvide märkija +Comment[eu]=KDE tekla berezien jakinarazlea +Comment[fa]=اخطار دهندۀ ویژۀ کلید KDE +Comment[fi]=KDE:n erikoisnäppäinhuomauttaja +Comment[fr]=Notificateur de touche spéciale pour KDE +Comment[hu]=KDE-s kezelőprogram a speciális billentyűkhöz +Comment[is]=KDE sérhnappatólið +Comment[it]=Gestione KDE dei tasti speciali +Comment[ja]=KDE の特殊キー通知 +Comment[kk]=KDE-ның арнаулы пернелерді қолдауы +Comment[km]=កម្មវិធី​ជូនដំណឹង​គ្រាប់ចុច KDE ពិសេស +Comment[lt]=KDE specialiųjų raktų pranešiklis +Comment[mk]=Известувач за спец. копчиња во KDE +Comment[nb]=Beskjedgiver KDE spesialtaster +Comment[nds]=KDE-Sünnertastenmellen +Comment[ne]=KDE विशेष कुञ्जी सूचनाकर्ता +Comment[nl]=KDE-notificatie van speciale toetsen +Comment[nn]=KDE-verktøy for spesialtastar +Comment[pa]=KDE ਖਾਸ ਸਵਿੱਚ ਸੂਚਕ +Comment[pl]=Obsługa klawiszy specjalnych +Comment[pt]=Notificação de teclas especiais do KDE +Comment[pt_BR]=Notificador de tecla especial do KDE +Comment[ro]=Notificare taste speciale pentru KDE +Comment[ru]=Поддержка специальных клавиш +Comment[sk]=KDE upozornenie na špeciálne klávesy +Comment[sl]=Opomnik posebnih ključev v KDE +Comment[sr]=KDE-ов обаваштавач о посебним тастерима +Comment[sr@Latn]=KDE-ov obavaštavač o posebnim tasterima +Comment[sv]=Underrättelse om KDE specialtangent +Comment[ta]= கேடிஇ சிறப்பு விசை குறிப்பான் +Comment[tr]=KDE özel tuş bildirici +Comment[uk]=Сповіщувач про натискання спеціальних клавіш для KDE +Comment[zh_CN]=KDE 特殊按键通知程序 +Comment[zh_TW]=KDE 特殊鍵通知 diff --git a/kmilo/kmilod/kmilod.h b/kmilo/kmilod/kmilod.h new file mode 100644 index 0000000..d97027b --- /dev/null +++ b/kmilo/kmilod/kmilod.h @@ -0,0 +1,72 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef _KMILOD_H_ +#define _KMILOD_H_ + +#include +#include +#include +#include +#include "monitor.h" +#include "displayskin.h" + +namespace KMilo { + +class KMiloInterface; + +class KMiloD : public KDEDModule { + Q_OBJECT + K_DCOP + public: + KMiloD(const QCString &name); + virtual ~KMiloD(); + + k_dcop: + virtual void setEnabled(bool enabled); + virtual void enable(); + virtual void disable(); + virtual bool enabled() const; + virtual int pollMilliSeconds() const; + virtual bool setPollMilliSeconds(int ms); + + virtual void displayText(const QString& text); + virtual void displayText(const QString& text, const QPixmap& customPixmap); + virtual void displayProgress(const QString& text, int progress, const QPixmap& customPixmap); + virtual void displayProgress(const QString& text, int progress); + + virtual void reconfigure(); + + private slots: + virtual void doTimer(); + + private: + QTimer _timer; + int _interval; + QPtrList _monitors; + DisplaySkin *_display; + KMiloInterface *_miface; +}; + +} + +#endif diff --git a/kmilo/kmilod/kmilointerface.cpp b/kmilo/kmilod/kmilointerface.cpp new file mode 100644 index 0000000..21a6430 --- /dev/null +++ b/kmilo/kmilod/kmilointerface.cpp @@ -0,0 +1,26 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "kmilointerface.h" +#include "kmilointerface.moc" + diff --git a/kmilo/kmilod/kmilointerface.h b/kmilo/kmilod/kmilointerface.h new file mode 100644 index 0000000..d1edbb9 --- /dev/null +++ b/kmilo/kmilod/kmilointerface.h @@ -0,0 +1,57 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef _KMILOI_H_ +#define _KMILOI_H_ + +#include +#include +#include "kmilod.h" + +namespace KMilo { + +// FIXME: make put the methods into .cpp file when the header is installed. +class KMiloInterface : public QObject { + Q_OBJECT + public: + KMiloInterface(KMiloD *p) : QObject() { _p = p; } + virtual ~KMiloInterface() {} + + public slots: + int pollMilliSeconds() const { return _p->pollMilliSeconds(); } + bool setPollMilliSeconds(int ms) { return _p->setPollMilliSeconds(ms); } + + void displayText(const QString& text) { _p->displayText(text); } + void displayText(const QString& text, const QPixmap& customPixmap) { _p->displayText(text, customPixmap); } + + void displayProgress(const QString& text, int progress, const QPixmap& customPixmap) { _p->displayProgress(text, progress, customPixmap); } + void displayProgress(const QString& text, int progress) { _p->displayProgress(text, progress); } + + void reconfigure() { _p->reconfigure(); } + + private: + KMiloD *_p; +}; + +} + +#endif diff --git a/kmilo/kmilod/kmilopluginsvc.desktop b/kmilo/kmilod/kmilopluginsvc.desktop new file mode 100644 index 0000000..bccb599 --- /dev/null +++ b/kmilo/kmilod/kmilopluginsvc.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=KMilo Plugin + +[PropertyDef::X-KMilo-Plugin-Author] +Type=QString +[PropertyDef::X-KMilo-Default-Enabled] +Type=bool + diff --git a/kmilo/kmilod/monitor.cpp b/kmilo/kmilod/monitor.cpp new file mode 100644 index 0000000..f427ce4 --- /dev/null +++ b/kmilo/kmilod/monitor.cpp @@ -0,0 +1,44 @@ +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "monitor.h" + +KMilo::Monitor::Monitor(QObject *parent, const char *name, const QStringList&) +: QObject(parent, name) { + _poll = true; +} + +KMilo::Monitor::~Monitor() { +} + +void KMilo::Monitor::reconfigure(KConfig*) +{ +} + +KMilo::Monitor::DisplayType KMilo::Monitor::poll() { return None; } + +int KMilo::Monitor::progress() const { return 42; } + +QString KMilo::Monitor::message() const { return QString::null; } +QPixmap KMilo::Monitor::customPixmap() const { return QPixmap(); } +bool KMilo::Monitor::init() { return true; } + diff --git a/kmilo/kmilod/monitor.h b/kmilo/kmilod/monitor.h new file mode 100644 index 0000000..ee1581c --- /dev/null +++ b/kmilo/kmilod/monitor.h @@ -0,0 +1,98 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _MONITOR_H_ +#define _MONITOR_H_ + +#include +#include +#include +#include + +#include + +class KConfig; + +namespace KMilo { +class KMiloInterface; + +class KDE_EXPORT Monitor : public QObject { + public: + Monitor(QObject *parent, const char *name, const QStringList&); + virtual ~Monitor(); + + /** + * Called by kmilod to initialise this plugin. The plugin + * must return true if its hardware is present and it should + * be loaded. If it returns false, it will be unloaded. + */ + virtual bool init(); + + enum DisplayType { None, //! + Error, //! Error + Volume, //! Volume level changed + Mute, //! Volume has been muted + Brightness, //! Brighteness of the screen has changed + Tap, //! Mousttracker tap mode has changed + Sleep //! laptop will sleep in progress() seconds + }; + + /** + * This is called by KMiloD when it polls. Must return + * the type of event that has occurred, or None. + */ + virtual DisplayType poll(); + + /** + * If poll() returns stating that a value has changed, this + * will be called by kmilod to determine the value (0..100) + * for the slider in the display, if necessary. + */ + virtual int progress() const; + + /** + * Message displayed for DisplayType's that are not int + * measurable ( DisplayType::Tap for example ) + */ + virtual QString message() const; + + /** + * Custom pixmap that can be displayed be the themes + * when displaying the DisplayType. + */ + virtual QPixmap customPixmap() const; + + bool shouldPoll() const { return _poll; } + + virtual void reconfigure(KConfig*); + + protected: + bool _poll; // set to false to disable polling. + friend class KMiloD; + void setInterface(KMiloInterface *i) { _interface = i; } + + KMiloInterface *_interface; +}; + +} + +#endif diff --git a/kmilo/powerbook/Makefile.am b/kmilo/powerbook/Makefile.am new file mode 100644 index 0000000..5c3f467 --- /dev/null +++ b/kmilo/powerbook/Makefile.am @@ -0,0 +1,34 @@ +# This file is part of the KDE project +# Copyright (C) 2003 George Staikos + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +INCLUDES=-I$(srcdir)/../kmilod $(all_includes) + +kde_module_LTLIBRARIES = kmilo_powerbook.la + +kmilo_powerbook_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kmilo_powerbook_la_LIBADD = ../kmilod/libkmilo.la $(LIB_KIO) $(KEYBOARD_LIBS) +kmilo_powerbook_la_SOURCES = pb_monitor.cpp +METASOURCES = AUTO + +noinst_HEADERS = pb_monitor.h + +services_DATA = kmilo_powerbook.desktop +servicesdir = $(kde_servicesdir)/kmilo + +messages: + $(XGETTEXT) $(kmilo_powerbook_la_SOURCES) -o $(podir)/kmilo_powerbook.pot diff --git a/kmilo/powerbook/kmilo_powerbook.desktop b/kmilo/powerbook/kmilo_powerbook.desktop new file mode 100644 index 0000000..842d276 --- /dev/null +++ b/kmilo/powerbook/kmilo_powerbook.desktop @@ -0,0 +1,105 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KMilo Plugin +X-KDE-ModuleType=Plugin +Name=Apple (R) PowerBook (R) Plugin +Name[ar]=ملحق Apple (R) PowerBook (R)ة +Name[br]=Lugent Apple (R) PowerBook (R) +Name[bs]=Apple (R) PowerBook (R) dodatak +Name[ca]=Connector Apple (R) PowerBook (R) +Name[cs]=Apple (R) PowerBook (R) modul +Name[cy]=Ategyn Apple (R) PowerBook (R) +Name[da]=Apple (R) PowerBook (R) plugin +Name[el]=Πρόσθετο Apple (R) PowerBook (R) +Name[es]=Extensión para Apple ® PowerBook ® +Name[et]=Apple (R) PowerBook (R) plugin +Name[eu]=Apple (R) PowerBook (R) Plugina +Name[fa]=Apple (R) PowerBook (R) وصلۀ +Name[fi]=Apple (R) PowerBook (R) -liitännäinen +Name[fr]=Module externe Apple (R) PowerBook (R) +Name[ga]=Breiseán Apple® PowerBook® +Name[he]=תוסף למחשבי Apple (R) PowerBook (R) +Name[hi]=एप्पल (R) पावरबुक (R) प्लगइन +Name[hu]=Apple (R) PowerBook (R) bővítőmodul +Name[is]=Apple (R) PowerBook (R) íforrit +Name[it]=Plugin per Apple (R) PowerBook (R) +Name[ja]=Apple (R) PowerBook (R) プラグイン +Name[ka]=Apple (R) PowerBook (R) მოდული +Name[kk]=Apple (R) PowerBook (R) модулі +Name[km]=កម្មវិធី​ជំនួយ Apple (R) PowerBook (R) +Name[lt]=Apple (R) PowerBook (R) priedas +Name[mk]=Приклучок за Apple (R) PowerBook (R) +Name[nb]=Programtillegg for Apple (R) PowerBook (R) +Name[nds]=Apple(R) PowerBook(R)-Moduul +Name[ne]=एप्पल (R) पावरबुक (R) प्लगइन +Name[nl]=Apple (R) PowerBook (R)-Plugin +Name[nn]=Tilleggsprogram for Apple ® PowerBook ® +Name[pa]=Apple (R) PowerBook (R) ਪਲੱਗਿੰਨ +Name[pl]=Wtyczka Apple (R) PowerBook (R) +Name[pt]='Plugin' para Apple (R) PowerBook (R) +Name[pt_BR]=Plug-in para Apple (R) PowerBook (R) +Name[ro]=Modul Apple (R) PowerBook (R) +Name[ru]=Модуль Apple® PowerBook® +Name[sk]=Modul pre Apple (R) PowerBook (R) +Name[sl]=Vstavek za Apple (R) PowerBook (R) +Name[sr]=Прикључак за Apple-ов PowerBook +Name[sr@Latn]=Priključak za Apple-ov PowerBook +Name[sv]=Apple ® PowerBook ®-insticksprogram +Name[ta]=ஆப்பிள் (R) பவர்புக் (R) சொருகுப்பொருள் +Name[tg]=Модули Apple (R) PowerBook (R) +Name[tr]=Apple (R) PowerBook (R) Eklentisi +Name[uk]=Втулок Apple (R) PowerBook (R) +Name[uz]=Apple (R) PowerBook (R) plagini +Name[uz@cyrillic]=Apple (R) PowerBook (R) плагини +Name[zh_CN]=Apple(R) PowerBook(R) 插件 +Name[zh_TW]=Apple (R) PowerBook (R) 外掛程式 +Comment=This plugin enables support for special keys on Apple (R) PowerBook (R) laptops via pbbuttonsd. +Comment[ar]=تمكّن الدعم لمفاتيح حاسوب Apple (R) PowerBook (R) المحمول الخاصة عن طريق pbbuttonsd. +Comment[bg]=Тази приставка позволява поддръжката на специалните клавиши на Apple (R) PowerBook (R) laptops. +Comment[bs]=Ovaj dodatak (plugin) omogućuje podršku za posebne tipke na Apple (R) PowerBook (R) laptopima koristeći pbbuttonsd. +Comment[ca]=Aquest connector activa el funcionament per a tecles especials dels Apple (R) PowerBooks (R) via pbbuttonsd. +Comment[cs]=Tento modul umožňuje používat zvláštní klávesy notebooků Apple (R) PowerBook (R) přes pbbuttonsd. +Comment[cy]=Galluoga'r ategyn yma gynhaliaeth ar gyfer bysyll arbennig ar luniaduron Apple (R) PowerBook (R) drwy pbbuttonsd. +Comment[da]=Dette plugin aktivere støtte for specielle taster på Apple (R) PowerBook (R) bærbare via pbbuttonsd. +Comment[de]=Dieses Plugin schaltet die Unterstützung für Sondertasten des Apple (R) Powerbooks (R) via pbbuttonsd ein. +Comment[el]=Αυτό το πρόσθετο ενεργοποιεί την υποστήριξη για ειδικά πλήκτρα στα φορητά Apple (R) PowerBook (R) μέσω του pbbuttonsd. +Comment[es]=Esta extensión activa el soporte de las teclas especiales en los portátiles Apple ® PowerBook ® mediante pbbuttonsd. +Comment[et]=See plugin võimaldab pbbuttonsd vahendusel kasutada eriklahve Apple (R) PowerBook (R) sülearvutil. +Comment[eu]=Plugin honek tekla berezientzako euskarria gaitzen du Apple (R) PowerBook (R) magalekoetan pbbuttonsd bitartez. +Comment[fa]=این وصله، برای کلیدهای ویژۀ روی رایانه‌های کیفی Apple (R) PowerBook (R) via pbbuttonsd پشتیبانی را فعال می‌کند. +Comment[fi]=Tänmä liitännäinen mahdollistaa tuen Apple (R) PowerBook (R) kannettavien erikoisnäppäimille pbbuttonsd-ohjelman kautta. +Comment[fr]=Ce module active la gestion des touches spéciales des Apple (R)PowerBook (R) via pbbuttonsd. +Comment[ga]=Tacaíonn an breiseán seo le cnaipí speisialta ar ríomhairí glúine Apple® PowerBook® trí pbbuttonsd. +Comment[he]=התוסף הזה מאפשר תמיכה במקשים מיוחדים על מחשבים הברכיים של Apple (R) PowerBook (R) +Comment[hi]=यह प्लगइन एपल (R) पावर-बुक (R) लैपटॉप पर pbbuttonsd के द्वारा विशिष्ट कुंजी समर्थन सक्षम करता है +Comment[hu]=Ez a bővítőmodul lehetővé teszi az extra billentyűk használatát Apple (R) PowerBook (R) noteszgépeken (a pbbuttonsd szolgáltatáson keresztül). +Comment[is]=Þetta íforrit gerir þér kleyft að nota sérhnappana á Apple (R) PowerBook (R) með pbbuttonsd þjóninum. +Comment[it]=Questo plugin abilita il supporto per i tasti speciali sui portatili Apple (R) PowerBook (R) tramite pbbuttonsd. +Comment[ja]=このプラグインは pbbuttonsd を通して Apple (R) PowerBook (R) ラップトップの特殊キーをサポートします +Comment[ka]=.ეს მოდული რთავს Apple (R) PowerBook (R) ლეპტოპის სპეციალური კლავიშების მხარდაჭერას pbbuttonsd-ის მეშვეობით. +Comment[kk]=Бұл модуль Apple (R) PowerBook (R) ноутбуктерінде pbbuttonsd арқылы арнаулы пернелерді қолдау үшін. +Comment[km]=កម្មវិធី​ជំនួយនេះបើក​ការគាំទ្រ​សម្រាប់​គ្រាប់ចុច​ពិសេសនៅ​លើកុំព្យូទ័រ​យួរដៃ Apple (R) PowerBook (R) តាម​រយៈ pbbuttonsd ។ +Comment[lt]=Šis priedas įgalina specialiųjų raktų Apple (R) PowerBook (R) nešiojamuose kompiuteriuose palaikymą per pbbuttonsd. +Comment[mk]=Овој приклучок дава поддршка за специјалните копчиња на лаптопите Apple (R) PowerBook (R) преку pbbuttonsd. +Comment[nb]=Dette programtilleggmet muliggjør støtte for spesielle taster på Apple (R) PowerBook (R) bærbare maskiner via pbbuttonsd. +Comment[nds]=Dit Moduul maakt de Sünnertasten-Ünnerstütten för PowerBook(R)-Klappreekners vun Apple(R) via pbbuttonsd an. +Comment[ne]=यो प्लगइनले pbbuttonsd द्वारा एप्पल (R) पावरबुक (R) ल्यापटपका विशेष कुञ्जीका लागि समर्थन सक्षम पार्दछ । +Comment[nl]=Maakt het mogelijk speciale toetsen op Apple (R) PowerBook (R) laptops te gebruiken via pbbuttonsd. +Comment[nn]=Dette programtillegget gjer at du kan bruka spesialtastane på Apple® PowerBook® gjennom pbbuttonsd. +Comment[pl]=Ta wtyczka umożliwia obsługę klawiszy specjalnych na laptopach Apple (R) PowerBook (R) za pomocą pbbuttonsd. +Comment[pt]=Este 'plugin' activa o suporte para as teclas especiais nos portáteis Apple (R) PowerBook (R) através do 'pbbuttonsd'. +Comment[pt_BR]=Este plug-in habilita suporte para teclas especiais nos Apple (R) PowerBooks (R) via pbbuttonsd. +Comment[ro]=Acest modul activează suportul pentru tastele speciale din laptop-urile Apple (R) PowerBook (R), utilizînd "pbbuttonsd". +Comment[ru]=Этот модуль поддерживает специальные клавиши на ноутбуках Apple® PowerBook® через pbbuttonsd. +Comment[sk]=Tento modul obsahuje podporu špeciálnych kláves pre Apple (R) PowerBook (R) pomocou pbbuttonsd. +Comment[sl]=Ta vstavek vam omogoča podboro posebnim ključem na prenosnikih Apple (R) PowerBook (R) preko pbbuttonsd. +Comment[sr]=Овај прикључак омогућава подршку за специјалне тастере на Apple-овим PowerBook лаптопима преко pbbuttonsd. +Comment[sr@Latn]=Ovaj priključak omogućava podršku za specijalne tastere na Apple-ovim PowerBook laptopima preko pbbuttonsd. +Comment[sv]=Det här insticksprogrammet aktiverar stöd för speciella tangenter för Apple ® PowerBook ® via pbbuttonsd. +Comment[ta]=ஆப்பிள் (R) பவர்புக் (R) மடிக் கணினி மூலமாக பிபிபட்டன்எஸ்டி போன்றவைக்கு இந்த சொருகு பொருள் ஆதரிக்கிறது. +Comment[tg]=Ин модул пуштибонии калидҳои махсусро дар компютери дастии Apple (R) PowerBook (R) ба воситаи pbbuttonsd дармегиронад. +Comment[tr]=Bu plugin pbbuttonsd aracılığı ile Apple(R) PowerBook(R) dizüstüler için özel tuş desteğini açar. +Comment[uk]=Цей втулок дозволяє користуватися спеціальними клавішами на лептопах Apple (R) PowerBook (R) за допомогою pbbuttonsd. +Comment[zh_CN]=此插件启用 Apple(R) PowerBook(R) 便携电脑上的特殊按键。 +Comment[zh_TW]=這個外掛程式透過 pbbuttonsd 開啟 Apple(R) PowerBook(R) 筆記型電腦的特殊鍵支援。 +X-KDE-Library=kmilo_powerbook diff --git a/kmilo/powerbook/pb_monitor.cpp b/kmilo/powerbook/pb_monitor.cpp new file mode 100644 index 0000000..6279854 --- /dev/null +++ b/kmilo/powerbook/pb_monitor.cpp @@ -0,0 +1,127 @@ +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "pb_monitor.h" + +#include +#include + +#include + +extern "C" { +#include +} + +namespace KMilo { + +PowerBookMonitor::PowerBookMonitor(QObject *parent, const char *name, const QStringList& args) +: Monitor(parent, name, args) { + _serverPort = -1; + _clientPort = -1; + _progress = 0; +} + + +PowerBookMonitor::~PowerBookMonitor() { +struct pbb_message msg; + if (_serverPort >= 0) { + msg.code = UNREGISTERCLIENT; + msg.value = _clientPort; + put_message(_serverPort, &msg); + } + + if (_clientPort >= 0) { + remove_msgport(_clientPort); + } +} + + +bool PowerBookMonitor::init() { + _serverPort = find_msgport(SERVERPORTKEY); + if (_serverPort < 0) { + return false; + } + + _clientPort = create_msgport(getpid()); + if (_clientPort < 0) { + _serverPort = -1; + return false; + } + + // Register + struct pbb_message msg; + msg.code = REGISTERCLIENT; + msg.value = _clientPort; + if (put_message(_serverPort, &msg) < 0) { + remove_msgport(_clientPort); + _clientPort = -1; + _serverPort = -1; + return false; + } + +return true; +} + + +Monitor::DisplayType PowerBookMonitor::poll() { +Monitor::DisplayType rc = None; +struct pbb_message msg; + + if (_serverPort < 0 || _clientPort < 0) + return Error; + + // Drain the queue, send the last message + while (0 == get_message(_clientPort, 0, &msg)) { + switch (msg.code) { + case DISPLAYVOLUME: + rc = Monitor::Volume; + _progress = msg.value; + break; + case DISPLAYMUTE: + rc = Monitor::Mute; + _progress = msg.value; + break; + case DISPLAYBRIGHTNESS: + rc = Monitor::Brightness; + _progress = msg.value*100/15; + break; + case REGFAILED: + case CLIENTEXIT: + rc = Monitor::Error; + break; + default: + break; + } + } + +return rc; +} + + +int PowerBookMonitor::progress() const { + return _progress; +} + +}; + +K_EXPORT_COMPONENT_FACTORY(kmilo_powerbook, KGenericFactory("kmilo_powerbook")) + diff --git a/kmilo/powerbook/pb_monitor.h b/kmilo/powerbook/pb_monitor.h new file mode 100644 index 0000000..6d2736d --- /dev/null +++ b/kmilo/powerbook/pb_monitor.h @@ -0,0 +1,42 @@ +/* + This file is part of the KDE project + + Copyright (c) 2003 George Staikos + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef _PBMONITOR_H_ +#define _PBMONITOR_H_ + +#include "monitor.h" + +class PowerBookMonitor : public KMilo::Monitor { + public: + PowerBookMonitor(QObject *parent, const char *name, const QStringList&); + virtual ~PowerBookMonitor(); + + virtual bool init(); + virtual DisplayType poll(); + virtual int progress() const; + + private: + int _clientPort; + int _serverPort; + int _progress; +}; + +#endif diff --git a/kmilo/powerbook2/Makefile.am b/kmilo/powerbook2/Makefile.am new file mode 100644 index 0000000..5c3f467 --- /dev/null +++ b/kmilo/powerbook2/Makefile.am @@ -0,0 +1,34 @@ +# This file is part of the KDE project +# Copyright (C) 2003 George Staikos + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +INCLUDES=-I$(srcdir)/../kmilod $(all_includes) + +kde_module_LTLIBRARIES = kmilo_powerbook.la + +kmilo_powerbook_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kmilo_powerbook_la_LIBADD = ../kmilod/libkmilo.la $(LIB_KIO) $(KEYBOARD_LIBS) +kmilo_powerbook_la_SOURCES = pb_monitor.cpp +METASOURCES = AUTO + +noinst_HEADERS = pb_monitor.h + +services_DATA = kmilo_powerbook.desktop +servicesdir = $(kde_servicesdir)/kmilo + +messages: + $(XGETTEXT) $(kmilo_powerbook_la_SOURCES) -o $(podir)/kmilo_powerbook.pot diff --git a/kmilo/powerbook2/kmilo_powerbook.desktop b/kmilo/powerbook2/kmilo_powerbook.desktop new file mode 100644 index 0000000..9aff481 --- /dev/null +++ b/kmilo/powerbook2/kmilo_powerbook.desktop @@ -0,0 +1,106 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KMilo Plugin +X-KDE-ModuleType=Plugin +Name=Apple PowerBook Plugin +Name[ar]=ملحق Apple PowerBook +Name[br]=Lugent Apple PowerBook +Name[bs]=Apple PowerBook dodatak +Name[ca]=Connector Apple PowerBook +Name[cs]=Apple PowerBook modul +Name[cy]=Ategyn Apple PowerBook +Name[el]=Πρόσθετο Apple PowerBook +Name[es]=Extensión del PowerBook de Apple +Name[et]=Apple PowerBooki plugin +Name[eu]=Apple PowerBook Plugina +Name[fa]=Apple PowerBook وصلۀ +Name[fi]=Apple PowerBook -liitännäinen +Name[fr]=Module externe Apple PowerBook +Name[ga]=Breiseán Apple® PowerBook® +Name[he]=תוסף ל-Apple PowerBook +Name[hi]=एपल पावर-बुक प्लगइन +Name[hu]=Apple PowerBook bővítőmodul +Name[is]=Apple PowerBook íforrit +Name[it]=Plugin per Apple PowerBook +Name[ja]=Apple PowerBook プラグイン +Name[ka]=Apple PowerBook მოდული +Name[kk]=Apple PowerBook модулі +Name[km]=កម្មវិធីជំនួយ Apple PowerBook +Name[lt]=Apple PowerBook priedas +Name[mk]=Приклучок за Apple PowerBook +Name[ms]= Plug masuk Apple PowerBook +Name[nb]=Programtillegg for Apple PowerBook +Name[nds]=Apple PowerBook-Moduul +Name[ne]=एप्पल पावरबुक प्लगइन +Name[nl]=Apple PowerBook-plugin +Name[nn]=Programtillegg for Apple PowerBook +Name[pa]=Apple PowerBook ਪਲੱਗਿੰਨ +Name[pl]=Wtyczka Apple PowerBook +Name[pt]='Plugin' para Apple PowerBook +Name[pt_BR]=Plug-in para Apple PowerBook +Name[ro]=Modul Apple PowerBook +Name[ru]=Модуль Apple PowerBook +Name[sk]=Module pre Applet PowerBook +Name[sl]=Vstavek za Apple PowerBook +Name[sr]=Прикључак за Apple-ов PowerBook +Name[sr@Latn]=Priključak za Apple-ov PowerBook +Name[sv]=Apple PowerBook-insticksprogram +Name[ta]=ஆப்பிள் பவர்புக் சொருகுப்பொருள் +Name[tg]=Модули Apple PowerBook +Name[tr]=Apple PowerBook Eklentisi +Name[uk]=Втулок Apple PowerBook +Name[uz]=Apple PowerBook plagini +Name[uz@cyrillic]=Apple PowerBook плагини +Name[zh_CN]=Apple PowerBook 插件 +Name[zh_TW]=Apple Powerbook 外掛程式 +Comment=This plugin enabled support for special keys on Apple PowerBooks via pbbuttonsd. +Comment[ar]=تمكّن الدعم لمفاتيح حاسوب Apple PowerBook المحمول الخاصة عن طريق pbbuttonsd. +Comment[bg]=Тази приставка позволява поддръжката на специалните клавиши на Apple PowerBooks. +Comment[bs]=Ovaj dodatak (plugin) omogućuje podršku za posebne tipke na Apple PowerBooks laptopima koristeći pbbuttonsd. +Comment[ca]=Aquest connector activa el funcionament per a tecles especials dels Apple PowerBooks via pbbuttonsd. +Comment[cs]=Tento modul umožňuje používat zvláštní klávesy notebooků Apple PowerBook přes pbbuttonsd. +Comment[cy]=Galluoga'r ategyn yma gynhaliaeth ar gyfer bysyll arbennig ar yr Apple PowerBook drwy pbbuttonsd. +Comment[da]=Dette plugin aktivere støtte for specielle taster på Apple PowerBooks via pbbuttonsd. +Comment[de]=Dieses Plugin schaltet die Unterstützung für Sondertasten des Apple Powerbooks via pbbuttonsd ein. +Comment[el]=Αυτό το πρόσθετο ενεργοποιεί την υποστήριξη για ειδικά πλήκτρα στα Apple PowerBooks μέσω του pbbuttonsd. +Comment[es]=Esta extensión activa el soporte de las teclas especiales en los PowerBooks de Apple mediante «pbbuttonsd». +Comment[et]=See plugin võimaldab pbbuttonsd vahendusel kasutada eriklahve Apple PowerBooksil +Comment[eu]=Plugin honek tekla berezientzako euskarria gaitu du Apple PowerBook magalekoetan pbbuttonsd bitartez. +Comment[fa]=این وصله، برای کلیدهای ویژۀ Apple PowerBooks via pbbuttonsd، پشتیبانی را فعال می‌کند. +Comment[fi]=Tämä sovelma mahdollisti tuen Apple Powerbook kannettavien erikoisnäppäimille pbbuttonsd-ohjelman kautta. +Comment[fr]=Ce module active la gestion des touches spéciales des Apple PowerBook via pbbuttonsd. +Comment[ga]=Tacaíonn an breiseán seo le cnaipí speisialta ar ríomhairí glúine Apple® PowerBook® trí pbbuttonsd. +Comment[he]=התוסף הזה מאפשר תמיכה במקשים מיוחדים על מחשבים הברכיים של Apple PowerBook +Comment[hi]=यह प्लगइन एपल पावर-बुक पर pbbuttonsd के द्वारा विशिष्ट कुंजी समर्थन सक्षम करता है +Comment[hu]=Az Apple PowerBook noteszgépek speciális kezelőelemeinek beállítása (a pbbuttonsd szolgáltatáson keresztül) +Comment[is]=Þetta íforrit gerir þér kleyft að nota sérhnappana á Apple PowerBook með pbbuttonsd þjóninum. +Comment[it]=Questo plugin abilita il supporto per i tasti speciali sui portatili Apple PowerBook tramite pbbuttonsd. +Comment[ja]=このプラグインは pbbuttonsd を通して Apple PowerBook の特殊キーをサポートします +Comment[ka]= ეს მოდული რთავს Apple PowerBooks-ის სპეციალური კლავიშების მხარდაჭერას pbbuttonsd-ის მეშვეობით. +Comment[kk]=Бұл модуль Apple PowerBook ноутбуктерінде pbbuttonsd арқылы арнаулы пернелерді қолдау үшін. +Comment[km]=កម្មវិធី​ជំនួយ​នេះបើក​ការគាំទ្រ​សម្រាប់​គ្រាប់ចុច​ពិសេសនៅលើ Apple PowerBooks តាមរយៈ pbbuttonsd ។ +Comment[lt]=Šis priedas įgalina specialiųjų raktų Apple PowerBook nešiojamuose kompiuteriuose palaikymą per pbbuttonsd. +Comment[mk]=Овој приклучок дава поддршка за специјалните копчиња на Apple PowerBooks преку pbbuttonsd. +Comment[ms]=Plug masuk membolehkan sokongan untuk kekunci khas Apple PowerBooks menerusi pbbuttonsd. +Comment[nb]=Dette programtillegget muliggjør støtte for spesille taster på Apple PowerBooks via pbbuttonsd. +Comment[nds]=Dit Moduul maakt de Sünnertasten-Ünnerstütten för Apple-PowerBooks via pbbuttonsd an. +Comment[ne]=यो प्लगइनले pbbuttonsd द्वारा एप्पल पावरबुक विशेष कुञ्जीका लागि समर्थन सक्षम पार्दछ । +Comment[nl]=Maakt het mogelijk speciale toetsen op Apple (R) PowerBook (R) laptops te gebruiken via pbbuttonsd. +Comment[nn]=Dette programtillegget gjer at du kan bruka spesialtastane på Apple PowerBook gjennom pbbuttonsd. +Comment[pl]=Ta wtyczka umożliwia obsługę klawiszy specjalnych na laptopach Apple PowerBook za pomocą pbbuttonsd. +Comment[pt]=Este 'plugin' activa o suporte para as teclas especiais nos portáteis Apple PowerBook através do 'pbbuttonsd'. +Comment[pt_BR]=Este plug-in habilita suporte para teclas especiais nos Apple PowerBooks via pbbuttonsd. +Comment[ro]=Acest modul activează suportul pentru tastele speciale din laptop-urile Apple PowerBook, utilizînd "pbbuttonsd". +Comment[ru]=Этот модуль поддерживает специальные клавиши на Apple PowerBooks через pbbuttonsd. +Comment[sk]=Tento modul obsahuje podporu špeciálnych kláves pre Apple (R) PowerBook (R) pomocou pbbuttonsd. +Comment[sl]=Ta vstavek vam omogoča podboro posebnim ključem na prenosnikih Apple PowerBook preko pbbuttonsd. +Comment[sr]=Овај прикључак омогућава подршку за специјалне тастере на Apple-овим PowerBook-овима преко pbbuttonsd. +Comment[sr@Latn]=Ovaj priključak omogućava podršku za specijalne tastere na Apple-ovim PowerBook-ovima preko pbbuttonsd. +Comment[sv]=Det här insticksprogrammet aktiverar stöd för speciella tangenter för Apple PowerBook via pbbuttonsd. +Comment[ta]=ஆப்பிள் பவர்புக்ஸ் மூலமாக பிபிபட்டன்எஸ்டிக்கு இந்த சொருகுப் பொருள் ஆதரவளிக்கிறது +Comment[tg]=Ин модул пуштибонии калидҳои махсусро дар компютери дастии Apple PowerBooks ба воситаи pbbuttonsd дармегиронад. +Comment[tr]=Bu plugin pbbuttonsd aracılığı ile Apple PowerBook dizüstüler için özel tuş desteğini açar. +Comment[uk]=Цей втулок дозволив користуватися спеціальними клавішами на лептопах Apple PowerBook за допомогою pbbuttonsd. +Comment[zh_CN]=此插件启用 Apple PowerBook 电源按钮的特殊按键支持。 +Comment[zh_TW]=這個外掛程式透過 pbbuttonsd 開啟 Apple Powerbooks 特殊鍵支援。 +X-KDE-Library=kmilo_powerbook diff --git a/kmilo/powerbook2/pb_monitor.cpp b/kmilo/powerbook2/pb_monitor.cpp new file mode 100644 index 0000000..84c72d5 --- /dev/null +++ b/kmilo/powerbook2/pb_monitor.cpp @@ -0,0 +1,165 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 Zack Rusin + Pretty much ripped of from : + George Staikos :) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "pb_monitor.h" + +#include +#include + +#include +#include + +extern "C" { +//Hack because of the fact that pbb author is using C++ keywords in the code +//among which is "template"... +#undef template +#include + +// TAG_BRIGHTNESS was renamed to TAG_LCDBRIGHTNESS in pbbuttons +// 0.6.1-2 +#ifndef TAG_LCDBRIGHTNESS +#define TAG_LCDBRIGHTNESS TAG_BRIGHTNESS +#endif +} + +#define BUFFERLEN 200 +const QString tpmodes[] = { I18N_NOOP("No Tap"), I18N_NOOP("Tap"), I18N_NOOP("Drag"), I18N_NOOP("Lock") }; + +namespace KMilo { + +PowerBookMonitor::PowerBookMonitor(QObject *parent, const char *name, + const QStringList& args) + : Monitor(parent, name, args), + m_progress( 0 ) +{ + init_libpbb(); +} + +PowerBookMonitor::~PowerBookMonitor() +{ + ipc_exit(); +} + + +bool PowerBookMonitor::init() +{ +// pbbuttons 0.6.7 or newer +#ifdef CLIENT_REGISTER + return ( ipc_init( "kmilo", LIBMODE_CLIENT, CLIENT_REGISTER ) == 0 ); +#else + return ( ipc_init( LIBMODE_CLIENT, 1 ) == 0 ); +#endif +} + + +Monitor::DisplayType PowerBookMonitor::poll() +{ + Monitor::DisplayType rc = None; + // Drain the queue, send the last message + struct tagitem* tag = readMessage(); + m_message = QString::null; + while ( tag && tag->tag != TAG_END ) { + switch ( tag->tag ) { + case TAG_VOLUME: + rc = Monitor::Volume; + m_progress = (int)tag->data; + break; + case TAG_MUTE: + rc = Monitor::Mute; + m_progress = (int)tag->data; + break; + case TAG_LCDBRIGHTNESS: + rc = Monitor::Brightness; + m_progress = ((int)tag->data)*100/15; + break; + case TAG_TPMODE: + { + rc = Monitor::Tap; + QString marg = tpmodes[ tag->data & 3 ]; + m_message = i18n( "Operating mode set to: %1." ).arg( marg ); + } + break; + default: + break; + } + ++tag; + } + + if ( m_sleep ) { + rc = Monitor::Sleep; + } + + return rc; +} + + +int PowerBookMonitor::progress() const +{ + return m_progress; +} + +QString PowerBookMonitor::message() const +{ + return m_message; +} + +struct tagitem* PowerBookMonitor::readMessage() +{ + char buffer[BUFFERLEN]; + m_sleep = false; + if ( (ipc_receive(buffer, BUFFERLEN)) >=0 ) { + if ( buffer ) { + struct pbbmessage *msg = reinterpret_cast( buffer ); + switch ( msg->action ) { + case REGFAILED: + kdDebug()<<"PBB registration failed"<taglist; + break; + case WARNING: + if ( msg->taglist->data == 0 ) { + m_message = i18n( "The computer will sleep now." ); + } else { + m_message = i18n( "The computer will sleep in %n second.", + "The computer will sleep in %n seconds.", + msg->taglist->data ); + } + m_sleep = true; + kdDebug()<<"PBB Warning"<("kmilo_powerbook")) + diff --git a/kmilo/powerbook2/pb_monitor.h b/kmilo/powerbook2/pb_monitor.h new file mode 100644 index 0000000..a6bf651 --- /dev/null +++ b/kmilo/powerbook2/pb_monitor.h @@ -0,0 +1,55 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*- +/* + This file is part of the KDE project + + Copyright (c) 2003 Zack Rusin + Pretty much ripped of from : + George Staikos :) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef _PBMONITOR_H_ +#define _PBMONITOR_H_ + +#include "monitor.h" + +struct tagitem; + +namespace KMilo { + +class PowerBookMonitor : public KMilo::Monitor +{ +public: + PowerBookMonitor(QObject *parent, const char *name, const QStringList&); + virtual ~PowerBookMonitor(); + + virtual bool init(); + virtual DisplayType poll(); + virtual int progress() const; + virtual QString message() const; + +private: + struct tagitem* readMessage(); +private: + int m_progress; + QString m_message; + bool m_sleep; +}; + +} + +#endif diff --git a/kmilo/thinkpad/Makefile.am b/kmilo/thinkpad/Makefile.am new file mode 100644 index 0000000..e82c26b --- /dev/null +++ b/kmilo/thinkpad/Makefile.am @@ -0,0 +1,36 @@ +# This file is part of the KDE project +# Copyright (C) 2003 George Staikos + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +SUBDIRS = . kcmthinkpad + +INCLUDES=-I$(srcdir)/../kmilod $(all_includes) + +kde_module_LTLIBRARIES = kmilo_thinkpad.la + +kmilo_thinkpad_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kmilo_thinkpad_la_LIBADD = ../kmilod/libkmilo.la $(LIB_KIO) +kmilo_thinkpad_la_SOURCES = thinkpad.cpp +METASOURCES = AUTO + +noinst_HEADERS = thinkpad.h + +services_DATA = kmilo_thinkpad.desktop +servicesdir = $(kde_servicesdir)/kmilo + +messages: + $(XGETTEXT) $(kmilo_thinkpad_la_SOURCES) -o $(podir)/kmilo_thinkpad.pot diff --git a/kmilo/thinkpad/README b/kmilo/thinkpad/README new file mode 100644 index 0000000..56b5da0 --- /dev/null +++ b/kmilo/thinkpad/README @@ -0,0 +1,61 @@ +Thinkpad Buttons KMilo Plugin + +Jonathan Riddell jr@jriddell.org, January 2004 + +A port of tpb ( http://www.nongnu.org/tpb/ ) to KMilo. + +KMilo is a service for kded, the KDE daemon. KMilo is new to KDE 3.2. +It allows plugins which interact with the special buttons found on +some keyboards and laptops. + +This KMilo plugin reads the nvram used in IBM Thinkpads. You need the +Linux nvram module ('insmod nvram') and to create a device node +('mknod /dev/nvram c 10 144'). + +Thinkpad R30/R31 models do not have a hardware volume control and so +require software volume control. Other models need software volume +control only if you want a volume change step different from the +builtin value (14). This required write access to nvram ('chmod 666 +/dev/nvram') and could potentially damage the machine. + +A KControl Centre module is included to configure the values including +whether this service is run or not (by default it is not). + +INSTALL: + +Download kdeutils source for kde 3.2 or newer. Then compile as +usual starting from the kdeutils directory: + + make -f Makefile.cvs + ./configure + cd kmilo + make + sudo make install + +Restarting kded is probably needed: + + kdekillall kded + kded + +HISTORY: + +05 January 2004, Initial release, most things working + +21 January 2004, Bug fix, stop it crashing if starting without kmix + runningdisplay rounded min and max volume levels, pda icon for + KControl module + +24 January 2004, Stopped it start kmix on kded startup even when set not to run + +28 January 2004, Added to KDE CVS + +TODO: + + - Need a better icon for the KControl module + - Test on machines other than my R31, which only has volume, + brightness buttons, light and 'Thinkpad' buttons + - Add options for the 'Thinkpad' and other action buttons to do something (e.g. bring up Konqueror) + For this sort of thing we really want integration with KHotKeys but I'm not sure how + + + diff --git a/kmilo/thinkpad/kcmthinkpad/Makefile.am b/kmilo/thinkpad/kcmthinkpad/Makefile.am new file mode 100644 index 0000000..4e70c40 --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/Makefile.am @@ -0,0 +1,15 @@ +kde_module_LTLIBRARIES = kcm_thinkpad.la + +kcm_thinkpad_la_SOURCES = kcmthinkpad_general.ui main.cpp + +kcm_thinkpad_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kcm_thinkpad_la_LIBADD = $(LIB_KIO) + +INCLUDES= $(all_includes) -DKDE_BINDIR="\"$(bindir)\"" + +kcm_thinkpad_la_METASOURCES = AUTO + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcmthinkpad.pot + +xdg_apps_DATA = thinkpad.desktop diff --git a/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui b/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui new file mode 100644 index 0000000..771b7bf --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui @@ -0,0 +1,307 @@ + +KCMThinkpadGeneral + + + KCMThinkpadGeneral + + + + 0 + 0 + 559 + 548 + + + + KVaio: General Options + + + + unnamed + + + + tlOff + + + NoFrame + + + Plain + + + Could not read /dev/nvram. If you have an IBM Thinkpad load the nvram Linux module <em>insmod nvram</em> and create the node <em>mknod /dev/nvram c 10 144</em> then make the device readable <em>chmod 664 /dev/nvram</em> or writable <em>chmod 666 /dev/nvram</em>.<p> nvram must be writable for software volume control required for R30/R31 models and for using a custom volume change step. + + + + + bgGeneral + + + Thinkpad Button Options + + + + unnamed + + + + mCbRun + + + Run Thinkpad Buttons KMilo plugin + + + + + mCbSoftwareVolume + + + Change volume in software (required by R30/R31) + + + + + layout27 + + + + unnamed + + + + textLabel2_5 + + + Command for Mail button: + + + + + textLabel2_6 + + + Command for FN-Zoom button: + + + + + commandExecHome + + + + 3 + 5 + 1 + 0 + + + + + + textLabel2_4 + + + Command for Search button: + + + + + commandExec + + + + 3 + 5 + 1 + 0 + + + + + + volumeStepLabel + + + + 1 + 5 + 0 + 0 + + + + NoFrame + + + Plain + + + Volume step (out of 100): + + + + + commandExecZoom + + + + 3 + 5 + 1 + 0 + + + + + + textLabel2_3 + + + Command for Home button: + + + + + mSpinboxVolumeStep + + + + 3 + 5 + 1 + 0 + + + + 30 + + + 1 + + + + + commandExecSearch + + + + 3 + 5 + 1 + 0 + + + + + + textLabel2 + + + Command for Thinkpad button: + + + + + commandExecMail + + + + 3 + 5 + 1 + 0 + + + + + + + + + + + + + + mCbRun + toggled(bool) + KCMThinkpadGeneral + slotChanged() + + + mCbSoftwareVolume + toggled(bool) + KCMThinkpadGeneral + slotChanged() + + + mSpinboxVolumeStep + valueChanged(int) + KCMThinkpadGeneral + slotChanged() + + + commandExec + textChanged(const QString&) + KCMThinkpadGeneral + slotChanged() + + + commandExecHome + textChanged(const QString&) + KCMThinkpadGeneral + slotChanged() + + + commandExecMail + textChanged(const QString&) + KCMThinkpadGeneral + slotChanged() + + + commandExecSearch + textChanged(const QString&) + KCMThinkpadGeneral + slotChanged() + + + commandExecZoom + textChanged(const QString&) + KCMThinkpadGeneral + slotChanged() + + + + mCbRun + mCbSoftwareVolume + mSpinboxVolumeStep + commandExec + commandExecHome + commandExecSearch + commandExecMail + + + kcmthinkpad_general.ui.h + + + changed(); + + + slotChanged() + + + + + kurlrequester.h + kpushbutton.h + kurlrequester.h + kpushbutton.h + kurlrequester.h + kpushbutton.h + kurlrequester.h + kpushbutton.h + kurlrequester.h + kpushbutton.h + + diff --git a/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui.h b/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui.h new file mode 100644 index 0000000..6ccc675 --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/kcmthinkpad_general.ui.h @@ -0,0 +1,36 @@ +/* + * kcmthinkpad_general.uih + * + * Copyright (C) 2004 Jonathan Riddell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ +#include + +void KCMThinkpadGeneral::slotChanged() { + emit(changed()); +} + + + diff --git a/kmilo/thinkpad/kcmthinkpad/main.cpp b/kmilo/thinkpad/kcmthinkpad/main.cpp new file mode 100644 index 0000000..1b8b4bd --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/main.cpp @@ -0,0 +1,189 @@ +/* + * main.cpp + * + * Copyright (C) 2004 Jonathan Riddell + * + * Based on kcm_kvaio + * Copyright (C) 2003 Mirko Boehm (mirko@kde.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_FREEBSD +#include +#include +#endif + +#include "kcmthinkpad_general.h" + +#include + +#include "main.h" +#include "main.moc" + +typedef KGenericFactory KCMThinkpadModuleFactory; +K_EXPORT_COMPONENT_FACTORY( kcm_thinkpad, KCMThinkpadModuleFactory("kcmthinkpad")) + +#define CONFIG_FILE "kmilodrc" + +KCMThinkpadModule::KCMThinkpadModule(QWidget* parent, const char* name, const QStringList&) + : KCModule(KCMThinkpadModuleFactory::instance(), parent, name) { + KAboutData* about = + new KAboutData(I18N_NOOP("kcmthinkpad"), + I18N_NOOP("KDE Control Module for IBM Thinkpad " + "Laptop Hardware"), + 0, 0, KAboutData::License_GPL, + "(c) 2004 Jonathan Riddell"); + + about->addAuthor("Jonathan Riddell", + I18N_NOOP("Original author"), + "jr@jriddell.org"); + setAboutData( about ); + + QVBoxLayout* layout = new QVBoxLayout(this); + m_KCMThinkpadGeneral = new KCMThinkpadGeneral(this); + layout->addWidget( m_KCMThinkpadGeneral ); + layout->addStretch(); + + load(); + + //try and open /dev/nvram + m_nvramReadable = false; + m_nvramWriteable = false; + +#ifdef Q_OS_FREEBSD + // Look if the sysctl tree of acpi_ibm is in place + u_int n = 0; + size_t len = sizeof(n); + if (m_nvramReadable = ( sysctlbyname("dev.acpi_ibm.0.volume", &n, &len, NULL, 0) != -1 )) + m_nvramWriteable = ( sysctlbyname("dev.acpi_ibm.0.volume", NULL, NULL, &n, len) != -1 ); + + if (!m_nvramReadable) { + setButtons(buttons() & ~Default); + m_KCMThinkpadGeneral->bgGeneral->setEnabled(false); + m_KCMThinkpadGeneral->tlOff->setText(i18n("In order to use the Thinkpad Buttons KMilo Plugin, " + "you have to load the acpi_ibm(4) driver.")); + } else if (!m_nvramWriteable) { + m_KCMThinkpadGeneral->tlOff->setText(i18n("Could not write to dev.acpi_ibm.0.volume. " + "Using software volume, required for " + "R30/R31 models, or using a custom volume " + "change step is disabled.")); +#else + QFile nvramFile(m_nvramFile); + if ( nvramFile.open(IO_ReadOnly) ) { + m_nvramReadable = true; + nvramFile.close(); + } + if ( nvramFile.open(IO_WriteOnly) ) { + m_nvramWriteable = true; + nvramFile.close(); + } + + if (!m_nvramReadable) { + setButtons(buttons() & ~Default); + m_KCMThinkpadGeneral->bgGeneral->setEnabled(false); + } else if (!m_nvramWriteable) { + m_KCMThinkpadGeneral->tlOff->setText(i18n("Could not write to %1. " + "To use the software volume, required for " + "R30/R31 models and to use a custom volume " + "change step, set the nvram device to world " + "writeable: chmod 666 " + "/dev/nvram").arg(m_nvramFile)); +#endif + } else { + m_KCMThinkpadGeneral->tlOff->setText(i18n("Thinkpad Buttons KMilo Plugin Ready For Configuration")); + } + + connect( m_KCMThinkpadGeneral, SIGNAL(changed()), SLOT(changed())); + +} + +void KCMThinkpadModule::save() { + if (!m_nvramReadable) { + return; + } + DCOPClient client; + + KConfig config(CONFIG_FILE); + config.setGroup("thinkpad"); + + config.writeEntry("run", m_KCMThinkpadGeneral->mCbRun->isChecked()); + config.writeEntry("softwareVolume", m_KCMThinkpadGeneral->mCbSoftwareVolume->isChecked()); + config.writeEntry("volumeStep", m_KCMThinkpadGeneral->mSpinboxVolumeStep->value()); + config.writeEntry("buttonThinkpad", m_KCMThinkpadGeneral->commandExec->url()); + config.writeEntry("buttonHome", m_KCMThinkpadGeneral->commandExecHome->url()); + config.writeEntry("buttonSearch", m_KCMThinkpadGeneral->commandExecSearch->url()); + config.writeEntry("buttonMail", m_KCMThinkpadGeneral->commandExecMail->url()); + config.writeEntry("buttonZoom", m_KCMThinkpadGeneral->commandExecZoom->url()); + config.sync(); + + if (client.attach()) { + QByteArray data, replyData; + QCString replyType; + + if (!client.call("kded", "kmilod", "reconfigure()", data, replyType, replyData)) { + kdDebug() << "KCMThinkpad::showTextMsg: " + << "there was an error using DCOP on kmilod::reconfigure()." << endl; + } + } else { + kdDebug() << "KCMThinkpadModule: cannot attach to DCOP server, " + << "no automatic config update." << endl; + } +} + +void KCMThinkpadModule::load() { + load( false ); +} + +void KCMThinkpadModule::load(bool useDefaults) { + KConfig config(CONFIG_FILE); + + config.setReadDefaults( useDefaults ); + + config.setGroup("thinkpad"); + + m_KCMThinkpadGeneral->mCbRun->setChecked(config.readBoolEntry("run", false)); + m_KCMThinkpadGeneral->mCbSoftwareVolume->setChecked(config.readBoolEntry("softwareVolume", true)); + m_KCMThinkpadGeneral->mSpinboxVolumeStep->setValue(config.readNumEntry("volumeStep", 14)); + m_KCMThinkpadGeneral->commandExec->setURL(config.readEntry("buttonThinkpad", KDE_BINDIR "/konsole")); + m_KCMThinkpadGeneral->commandExecHome->setURL(config.readEntry("buttonHome", KDE_BINDIR "/konqueror")); + m_KCMThinkpadGeneral->commandExecSearch->setURL(config.readEntry("buttonSearch", KDE_BINDIR "/kfind")); + m_KCMThinkpadGeneral->commandExecMail->setURL(config.readEntry("buttonMail", KDE_BINDIR "/kmail")); + m_KCMThinkpadGeneral->commandExecZoom->setURL(config.readEntry("buttonZoom", KDE_BINDIR "/ksnapshot")); + m_nvramFile = config.readEntry("nvram", "/dev/nvram"); + + emit changed( useDefaults ); +} + +void KCMThinkpadModule::defaults() { + load( true ); +} + diff --git a/kmilo/thinkpad/kcmthinkpad/main.h b/kmilo/thinkpad/kcmthinkpad/main.h new file mode 100644 index 0000000..53534ed --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/main.h @@ -0,0 +1,49 @@ +/* + * main.h + * + * Copyright (C) 2004 Jonathan Riddell + * + * Based on kcm_kvaio + * Copyright (C) 2003 Mirko Boehm (mirko@kde.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef KCMTHINKPAD_MAIN_H +#define KCMTHINKPAD_MAIN_H + +#include + +class KCMThinkPadGeneral; + +class KCMThinkpadModule : public KCModule { + Q_OBJECT + + public: + KCMThinkpadModule(QWidget* parent, const char* name, const QStringList&); + + void save(); + void load(); + void load(bool useDefaults); + void defaults(); + private: + KCMThinkpadGeneral* m_KCMThinkpadGeneral; + QString m_nvramFile; + bool m_nvramReadable; + bool m_nvramWriteable; +}; + +#endif diff --git a/kmilo/thinkpad/kcmthinkpad/thinkpad.desktop b/kmilo/thinkpad/kcmthinkpad/thinkpad.desktop new file mode 100644 index 0000000..720a69f --- /dev/null +++ b/kmilo/thinkpad/kcmthinkpad/thinkpad.desktop @@ -0,0 +1,145 @@ +[Desktop Entry] +Type=Application +Exec=kcmshell thinkpad +Icon=laptop +DocPath=kcontrol/thinkpad/index.html + +X-KDE-Library=thinkpad +X-KDE-ParentApp=kcontrol + +Name=IBM Thinkpad Laptop +Name[ar]=حاسوب IBM Thinkpad المحمول +Name[bg]=Лаптоп IBM Thinkpad +Name[br]=Hezoug IBM Thinkpad +Name[bs]=IBM Thinkpad laptop +Name[ca]=Portàtil IBM Thinkpad +Name[cy]=Gliniadur IBM Thinkpad +Name[da]=IBM Thinkpad bærbar +Name[de]=IBM Thinkpad Notebook +Name[el]=Φορητός υπολογιστής IBM Thinkpad +Name[es]=Portátil IBM Thinkpad +Name[et]=IBM Thinkpadi sülearvuti +Name[eu]=IBM Thinkpad Magalekoa +Name[fa]=IBM Thinkpad رایانۀ کیفی +Name[fi]=IBM Thinkpad -kannettava +Name[fr]=Portable Thinkpad d'IBM +Name[ga]=Ríomhaire Glúine IBM Thinkpad +Name[he]=מחשב ברכיים מסוג IBM Thinkpad +Name[hu]=IBM Thinkpad noteszgép +Name[is]=IBM ferðavél +Name[it]=Portatile IBM Thinkpad +Name[ja]=IBM シンクパッド ラップトップ +Name[kk]=IBM Thinkpad ноутбугі +Name[km]=កុំព្យូទ័រ​យួរដៃ IBM Thinkpad +Name[mk]=Лаптоп IBM Thinkpad +Name[nb]=IBM Thinkpad Bærbar PC +Name[nds]=IBM Thinkpad-Klappreekner +Name[ne]=IBM थिङ्कप्याड ल्यापटप +Name[nn]=IBM Thinkpad-bærbar +Name[pa]=IBM Thinkpad ਲੈਪਟਾਪ +Name[pl]=Laptop IBM Thinkpad +Name[pt]=Portátil IBM Thinkpad +Name[pt_BR]=Laptop IBM Thinkpad +Name[ro]=Laptop IBM Thinkpad +Name[ru]=Ноутбук IBM Thinkpad +Name[sk]=IBM Thinkpad +Name[sl]=Prenosnik IBM Thinkpad +Name[sr]=IBM-ов Thinkpad лаптоп +Name[sr@Latn]=IBM-ov Thinkpad laptop +Name[sv]=IBM Thinkpad bärbar dator +Name[ta]=ஐபிஎம் திங்க்பாட் மடிக்கணினி +Name[tr]=IBM Thinkpad Dizüstü +Name[uk]=Лептоп IBM Thinkpad +Name[uz]=IBM Thinkpad laptopi +Name[uz@cyrillic]=IBM Thinkpad лаптопи +Name[zh_CN]=ThinkPad 便携电脑 +Name[zh_TW]=IBM Thinkpad 筆記型電腦 +Comment=Configure the KDE Interface to the IBM Thinkpad Special Controls +Comment[ar]=إعداد واجهة كدى لمُتَحكّمات IBM Thinkpad الخاصة +Comment[bg]=Настройване на IBM Thinkpad +Comment[bs]=Podesite KDE interfejs za IBM Thinkpad posebne kontrole +Comment[ca]=Configura la interfície entre KDE i els controls especials de IBM Thinkpad +Comment[cs]=Nastavení KDE rozhraní ovládání notebooků IBM Thinkpad +Comment[cy]=Ffurfweddu'r Rhyngwyneb KDE i'r Rheolau Arbennig IBM Thinkpad +Comment[da]=Indstil KDE's grænseflade til IBM Thinkpads specielle kontroller +Comment[de]=KDE Schnittstelle zu den Sonderfunktionen von IBM Thinkpads einrichten +Comment[el]=Ρυθμίστε το περιβάλλον χρήσης του KDE για τα ειδικά χειριστήρια του IBM Thinkpad +Comment[es]=Configurar la interfaz de KDE para los controles especiales del IBM Thinkpad +Comment[et]=KDE liides IBM Thinkpadi eriklahvide seadistamiseks +Comment[eu]=IBM Thinkpad-en Aginte Berezientzako KDE Interfazea Konfiguratu +Comment[fa]=پیکربندی واسط KDEدر کلیدهای مهار ویژۀ IBM Thinkpad +Comment[fi]=Aseta KDE:n liityntää IBM Thinkpadin ohjelmoitavalle keskeytysajurille +Comment[fr]=Configuration de l'interface KDE pour le paramètrage des Thinkpad d'IBM +Comment[ga]=Cumraigh comhéadan KDE do Rialtáin Speisialta IBM Thinkpad +Comment[he]=הגדר את המנשק של KDE להתאים למקשים המיוחדים של IBM Thinkpad +Comment[hu]=Az IBM Thinkpad noteszgépek speciális kezelőelemeinek beállítása +Comment[is]=Stilla viðmót KDE á IBM Thinkpad stýringuna +Comment[it]=Configura l'interfaccia KDE ai controlli speciali dei Thinkpad IBM +Comment[ja]=IBM シンクパッド特殊コントロールの KDE インターフェースを設定 +Comment[ka]= KDE ინტერფეისის IBM Thinkpad-ის სპეციალური კონტროლებისთვის კონფიგურაცია +Comment[kk]=IBM Thinkpad арнаулы тетіктерінің KDE интерфейсін баптау +Comment[km]=កំណត់​រចនា​សម្ព័ន្ធ​ចំណុច​ប្រទាក់ KDE ទៅ​ការត្រួតពិនិត្យ IBM Thinkpad ពិសេស +Comment[lt]=IBM Thinkpad ypatingiems valdymo moduliams KDE sąsaja +Comment[mk]=Го конфигурира интерфејсот на KDE за спец. контроли на IBM Thinkpad +Comment[nb]=Sett opp KDE-grensesnitt til IBM Thinkpad spesial kontroller +Comment[nds]=KDE-Koppelsteedinstellen för de IBM Thinkpad-Sünnerfunkschonenkuntrull +Comment[ne]=IBM थिङ्कप्याड विशेष नियन्त्रणका लागि KDE इन्टरफेस कन्फिगर गर्नुहोस् +Comment[nl]=Voor het instellen van KDE's communicatie met de IBM Thinkpad Special Controls +Comment[nn]=Set opp KDE-grensesnittet til spesialfunksjonar på IBM Thinkpad +Comment[pa]=IBM ਥਿੰਕਪੈਂਡ ਕੰਟਰੋਲਾਂ ਲਈ KDE ਇੰਟਰਫੇਸ ਸੰਰਚਨਾ +Comment[pl]=Konfiguracja specjalnych funkcji IBM Thinkpad +Comment[pt]=Configurar a Interface para o KDE dos Comandos Especiais do IBM Thinkpad +Comment[pt_BR]=Configura a Interface do KDE para os Controles Especiais do IBM Thinkpad +Comment[ro]=Configurează interfaţa KDE către laptop-uri IBM Thinkpad +Comment[ru]=Настройка интерфейса KDE для специальных клавиш ноутбука IBM Thinkpad +Comment[sk]=Nastavenie rozhrania KDE k špeciálnym ovládacím prvkom notebooku IBM Thinkpad +Comment[sl]=Nastavite vmesnik KDE za posebne kontrole IBM Thinkpada +Comment[sr]=Подесите KDE-ов интерфејс за посебне контроле IBM-ових Thinkpad-ова +Comment[sr@Latn]=Podesite KDE-ov interfejs za posebne kontrole IBM-ovih Thinkpad-ova +Comment[sv]=Anpassa KDE:s gränssnitt till IBM Thinkpads specialstyrning +Comment[ta]=ஐபிஎம் திங்க்பேட் விசேஷ கட்டுப்பாட்டிற்கு கேடிஇ இடைமுகத்தை வடிவமை +Comment[tr]=KDE Arayüzünü Sony IBM Thinkpad Özel Denetimlerine Ayarla +Comment[uk]=Налаштування інтерфейсу KDE до спеціальних функцій IBM Thinkpad +Comment[zh_CN]=配置 KDE 界面使用 ThinkPad 特殊控制 +Comment[zh_TW]=設定 IBM Thinkpad 特殊控制的 KDE 介面 +Keywords=IBM, Thinkpad, brightness, mute, Jog Dial +Keywords[bs]=IBM, Thinkpad, brightness, mute, Jog Dial, svjetlost +Keywords[ca]=IBM, Thinkpad, brillantor, silenci, Jog Dial +Keywords[cs]=IBM,Thinkpad,jas,ztlumení,Jog Dial +Keywords[cy]=IBM,Thinkpad,gloywder, mud, Jog Dial +Keywords[da]=IBM. Thinkpad, lysstyrke, stum, Jog Dial +Keywords[de]=IBM, Thinkpad, Helligkeit, Abschalten, Jog Dial +Keywords[el]=IBM, Thinkpad, φωτεινότητα, κλείσιμο ήχου, Jog Dial +Keywords[es]=IBM, Thinkpad, brillo, mute, Jog Dial +Keywords[et]=IDM, Thinkpad, heledus, tumm, Jog Dial +Keywords[eu]=IBM, Thinkpad, distira, mutu, Jog Dial +Keywords[fa]=IBM، Thinkpad، روشنایی، بدون صدا، Jog Dial +Keywords[fi]=IBM, Thinkpad, kirkkaus, vaimenna, Jog Dial +Keywords[fr]=IBM, Thinkpad, luminosité, sourdine, mute, Jog Dial +Keywords[ga]=IBM, Thinkpad, gile, gan fuaim, Jog Dial +Keywords[hu]=IBM,Thinkpad,fényerő,elnémítás,tárcsagomb +Keywords[it]=IBM,Thinkpad,luminosità,muto,Jog Dial +Keywords[ja]=IBM, シンクパッド, 明るさ, ミュート, ジョグダイアル +Keywords[mk]=IBM, Thinkpad, brightness, mute, Jog Dial, осветленост, пригушување +Keywords[nb]=IBM, Thinkpad, lysstyrke, dempet, Jog Dial +Keywords[nds]=IBM, Thinkpad, Helligkeit, stumm, Jog Dial +Keywords[ne]=IBM, थिङ्कप्याड, चम्किलोपना, चुप लाग्नु, जोग डायल +Keywords[nl]=IBM, Thinkpad, brightness, mute, Jog Dial, Helderheid, dempen +Keywords[nn]=IBM,Thinkpad,lysstyrke,demping,snurrehjul +Keywords[pa]=IBM, Thinkpad, brightness, mute, Jog Dial, ਲੈਪਟਾਪ +Keywords[pl]=IBM, Thinkpad, jasność, wycisz, Jog Dial +Keywords[pt]=IBM, Thinkpad, brilho, sem som, Jog Dial +Keywords[pt_BR]=IBM,Thinkpad,brilho, mudo, Jog Dial +Keywords[ro]=IBM,Thinkpad,strălucire,fără sunet,jog dial +Keywords[ru]=IBM, Thinkpad, brightness, mute, Jog Dial, яркость, звук +Keywords[sk]=IBM, Thinkpad,jas,potichu +Keywords[sl]=IBM, Thinkpad, svetlost, tiho, Jog Dial +Keywords[sr]=Sony, Vaio, kvaio, brightness, mute, Jog Dial, светлина +Keywords[sr@Latn]=Sony, Vaio, kvaio, brightness, mute, Jog Dial, svetlina +Keywords[sv]=IBM, Thinkpad, ljusstyrka, tyst, rullhjul +Keywords[ta]=ஐபிஎம், திங்க்பேட்,ஒளித்தன்மை,ஓசையற்ற,ஜோக் டையல் +Keywords[tr]=IBM, Thinkpad, parlaklık, sessiz, gösterme itmesi +Keywords[uk]=IBM, Thinkpad, яскравість, вимкнення звуку, Jog Dial +Keywords[zh_CN]=IBM, Lenovo, Thinkpad, brightness, mute, Jog Dial,亮度,静音,联想,导航键 + +Categories=Qt;KDE;X-KDE-settings-system; diff --git a/kmilo/thinkpad/kmilo_thinkpad.desktop b/kmilo/thinkpad/kmilo_thinkpad.desktop new file mode 100644 index 0000000..1d957c4 --- /dev/null +++ b/kmilo/thinkpad/kmilo_thinkpad.desktop @@ -0,0 +1,101 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KMilo Plugin +X-KDE-ModuleType=Plugin +Name=Thinkpad Plugin +Name[ar]=ملحق Thinkpad +Name[br]=Lugent Thinkpad +Name[bs]=Thinkpad dodatak +Name[ca]=Connector Thinkpad +Name[cs]=Thinkpad modul +Name[cy]=Ategyn Thinkpad +Name[de]=Thinkpad-Plugin +Name[el]=Πρόσθετο Thinkpad +Name[eo]=Thinkpad-kromaĵo +Name[es]=Extensión para Thinkpad +Name[et]=Thinkpadi plugin +Name[eu]=Thikpad Plugina +Name[fa]=Thinkpad وصلۀ +Name[fi]=Thinkpad-liitännäinen +Name[fr]=Module externe pour les Thinkpad +Name[ga]=Breiseán Thinkpad +Name[he]=תוסף ל-Thinkpad +Name[hu]=Thinkpad bővítőmodul +Name[is]=Thinkpad íforrit +Name[it]=Plugin Thinkpad +Name[ja]=シンクパッド プラグイン +Name[ka]=Thinkpad-ის მოდული +Name[kk]=Thinkpad модулі +Name[km]=កម្មវិធី​ជំនួយ Thinkpad Plugin +Name[lt]=Thinkpad priedas +Name[mk]=Приклучок за Thinkpad +Name[nb]=Thinkpad tilleggs program +Name[nds]=Thinkpad-Moduul +Name[ne]=थिङ्कप्याड प्लगइन +Name[nn]=Programtillegg for Thinkpad +Name[pa]=Thinkpad ਪਲੱਗਿੰਨ +Name[pl]=Wtyczka Thinkpad +Name[pt]='Plugin' para Thinkpad +Name[pt_BR]=Plugin do Thinkpad +Name[ro]=Modul Thinkpad +Name[ru]=Модуль Thinkpad +Name[sk]=Modul pre Thinkpad +Name[sl]=Vstavek za Thinkpad +Name[sr]=Прикључак за Thinkpad +Name[sr@Latn]=Priključak za Thinkpad +Name[sv]=Thinkpad-insticksprogram +Name[ta]=திங்க்பேட் செருகி +Name[tr]=Thinkpad Eklentisi +Name[uk]=Втулок Thinkpad +Name[uz]=Thinkpad plagini +Name[uz@cyrillic]=Thinkpad плагини +Name[zh_CN]=Thinkpad 插件 +Name[zh_TW]=Thinkpad 外掛程式 +Comment=Enables support for special Thinkpad keys +Comment[ar]=تمكّن الدعم لمفاتيح Thinkpad الخاصة +Comment[bg]=Тази приставка позволява поддръжката на специалните клавиши на IBM Thinkpad +Comment[bs]=Omogućuje podršku za posebne tipke na Thinkpadu +Comment[ca]=Habilita el funcionament per a tecles especials de Thinkpad +Comment[cs]=Umožňuje podporu speciálních kláves Thinkpadu +Comment[cy]=Yn galluogi cynhaliaeth ar gyfer bysyll arbennig Thinkpad +Comment[da]=Aktiverer støtte for specielle Thinkpad taster +Comment[de]=Dieses Plugin aktiviert die Unterstützung für Sondertasten von Thinkpad-Tastaturen +Comment[el]=Ενεργοποιεί την υποστήριξη για ειδικά πλήκτρα του Thinkpad +Comment[es]=Activa el soporte de las teclas especiales del Thinkpad +Comment[et]=See plugin võimaldab kasutada Thinkpadi eriklahve. +Comment[eu]=Thinkpad-en tekla berezientzako euskarria gaitzen du +Comment[fa]=فعال‌سازی پشتیبانی برای کلیدهای ویژۀ Thinkpad . +Comment[fi]=Tämä liitännäinen mahdollistaa erikoisnäppäinten tuen IBM Thinkpad kannettaville tietokoneille. +Comment[fr]=Ce module active la gestion des touches spéciales des Thinkpad. +Comment[ga]=Tacaigh le heochracha speisialta Thinkpad +Comment[he]=מאפשר תמיכה במקשים מיוחדים של Thinkpad +Comment[hu]=Ez a bővítőmodul lehetővé teszi az IBM Thinkpad noteszgépek speciális billentyűinek használatát +Comment[is]=Virkjar stuðning fyrir sérhnappa Thinkpad véla +Comment[it]=Abilita il supporto per i tasti speciali Thinkpad +Comment[ja]=シンクパッドの特殊キーをサポートします +Comment[ka]=რთავს Thinkpad-ის სპეციალური კლავიშების მხარდაჭერას +Comment[kk]=Thinkpad-тың арнаулы пернелерін қолдауы +Comment[km]=បើក​ការគាំទ្រ​សម្រាប់​គ្រាប់ចុច Thinkpad ពិសេស +Comment[lt]=įgalina ypatingų Thinkpad raktų paramą +Comment[mk]=Овозможува поддршка за спец. копчиња на Thinkpad +Comment[nb]=Dette programtillegget muliggjør støtte for spesielle taster på alle tastatur og bærbare maskiner +Comment[nds]=Maakt de Sünnertasten-Ünnerstütten för Thinkpads an +Comment[ne]=विशेष थिङ्कप्याड कुञ्जीका लागि समर्थन सक्षम पार्दछ +Comment[nl]=Activeert de ondersteuning voor spciale Thinkpad-toetsen +Comment[nn]=Dette programtillegget gjer det mogleg å bruka spesialtastar på Thinkpad +Comment[pl]=Włącza obsługę specjalnych klawiszy Thinkpada +Comment[pt]=Activa o suporte a teclas especiais do Thinkpad +Comment[pt_BR]=Habilita suporte para teclas especiais no Thinkpad +Comment[ro]=Activează suportul pentru tastele speciale Thinkpad +Comment[ru]=Этот модуль поддерживает специальные клавиши Thinkpad +Comment[sk]=Zapína podporu pre špeciálne klávesy notebookov Thinkpad +Comment[sl]=Omogoči podporo posebnim tipkam Thinkpada +Comment[sr]=Подршку за посебне Thinkpad-ове тастере +Comment[sr@Latn]=Podršku za posebne Thinkpad-ove tastere +Comment[sv]=Aktiverar stöd för speciella Thinkpad-tangenter +Comment[ta]=விசேஷ திங்க்பேட் விசைகளுக்கான ஆதரவை செயல்படுத்துகிறது +Comment[tr]=Özel Thinkpad tuşları için desteği etkinleştirir +Comment[uk]=Уможливлює підтримку спеціальних клавіш для Thinkpad. +Comment[zh_CN]=此插件启用各种键盘和便携电脑的特殊按键 +Comment[zh_TW]=開啟特殊 Thinkpad 按鍵支援 +X-KDE-Library=kmilo_thinkpad diff --git a/kmilo/thinkpad/thinkpad.cpp b/kmilo/thinkpad/thinkpad.cpp new file mode 100644 index 0000000..74770cf --- /dev/null +++ b/kmilo/thinkpad/thinkpad.cpp @@ -0,0 +1,556 @@ +/* + This file is part of the KDE project + + Copyright (c) 2004 Jonathan Riddell + + Based on Demo kmilo service by George Staikos + Copyright (c) 2003 George Staikos + + And tpb by Markus Braun + Copyright (C) 2002,2003 Markus Braun + + FreeBSD support by Markus Brueffer + Copyright (C) 2005 Markus Brueffer + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include +#include +#include "kmilointerface.h" + +#ifdef Q_OS_FREEBSD +#include +#endif + +#include "thinkpad.h" + +namespace KMilo { + +ThinkPadMonitor::ThinkPadMonitor(QObject* parent, const char* name, const QStringList& args): Monitor(parent, name, args) { + m_progress = 0; + m_volume = 50; //set in retrieveVolume() +} + +ThinkPadMonitor::~ThinkPadMonitor() { +} + +bool ThinkPadMonitor::init() { + + KConfig config("kmilodrc"); + reconfigure(&config); + + if (m_run) { + clearStruct(thinkpad_state); + clearStruct(last_thinkpad_state); + if ( getNvramState(&thinkpad_state) == false ) { + return false; + } + + if (m_softwareVolume || m_volumeStep != defaultVolumeStep) { + kmixClient = new DCOPRef("kmix", "Mixer0"); + kmixWindow = new DCOPRef("kmix", "kmix-mainwindow#1"); + retrieveVolume(); + setNvramVolume(); + } + } + + return m_run; +} + +Monitor::DisplayType ThinkPadMonitor::poll() { + + // save last state and get new one + memcpy(&last_thinkpad_state, &thinkpad_state, sizeof(thinkpad_state_struct)); + getNvramState(&thinkpad_state); + + Monitor::DisplayType pollResult = None; + + // determine the state of the mute button + if (thinkpad_state.mute_toggle != last_thinkpad_state.mute_toggle || + (thinkpad_state.volume_toggle != last_thinkpad_state.volume_toggle + && last_thinkpad_state.mute_toggle == 1)) { + + showToggleMessage(i18n("Mute on"), i18n("Mute off"), thinkpad_state.mute_toggle == 1); + if (m_softwareVolume || m_volumeStep != defaultVolumeStep) { + kmixClient->send("setMasterMute", thinkpad_state.mute_toggle == 1); + } + } + + // determine the state of the Thinkpad button + if (thinkpad_state.thinkpad_toggle != last_thinkpad_state.thinkpad_toggle && + thinkpad_state.hibernate_toggle == last_thinkpad_state.hibernate_toggle) { + _interface->displayText(i18n("Thinkpad Button Pressed")); + + KURL url(m_buttonThinkpad); + (void) new KRun(url, 0, true, true); + } + + // determine the state of ThinkLight + if (thinkpad_state.thinklight_toggle != last_thinkpad_state.thinklight_toggle) { + showToggleMessage(i18n("ThinkLight is on"), i18n("ThinkLight is off"), thinkpad_state.thinklight_toggle == 1); + } + + // determine the state of the volume buttons + if (thinkpad_state.volume_level != last_thinkpad_state.volume_level) { + + pollResult = Volume; + + if (m_volumeStep == defaultVolumeStep && m_softwareVolume == false) { + //no need to write to nvram or set volume in software + m_progress = thinkpad_state.volume_level * 100 / defaultVolumeStep; + } else { + if (thinkpad_state.volume_level > last_thinkpad_state.volume_level) { + m_progress = m_volume + m_volumeStep; + } else { + m_progress = m_volume - m_volumeStep; + } + setVolume(m_progress); + } + + } + + // determine the state of the brightness buttons + if (thinkpad_state.brightness_level != last_thinkpad_state.brightness_level) { + pollResult = Brightness; + m_progress = thinkpad_state.brightness_level * 100 / 7; + } + + // Buttons below here are untested because they do not exist on my R31 + + // determine the state of zoom + if (thinkpad_state.zoom_toggle != last_thinkpad_state.zoom_toggle) { + // showToggleMessage(i18n("Zoom is on"), i18n("Zoom is off"), thinkpad_state.zoom_toggle == 1); + + // Use as button since an Zooming is implemented + _interface->displayText(i18n("Zoom button pressed")); + + KURL url(m_buttonZoom); + (void) new KRun(url, 0, true, true); + } + + // determine the state of the home button + if (thinkpad_state.home_toggle != last_thinkpad_state.home_toggle && + thinkpad_state.hibernate_toggle == last_thinkpad_state.hibernate_toggle) { + _interface->displayText(i18n("Home button pressed")); + KURL url(m_buttonHome); + (void) new KRun(url, 0, true, true); + } + + // determine the state of the search button + if (thinkpad_state.search_toggle != last_thinkpad_state.search_toggle && + thinkpad_state.hibernate_toggle == last_thinkpad_state.hibernate_toggle) { + _interface->displayText(i18n("Search button pressed")); + KURL url(m_buttonSearch); + (void) new KRun(url, 0, true, true); + } + + // determine the state of the mail button + if (thinkpad_state.mail_toggle != last_thinkpad_state.mail_toggle && + thinkpad_state.hibernate_toggle == last_thinkpad_state.hibernate_toggle) { + _interface->displayText(i18n("Mail button pressed")); + KURL url(m_buttonMail); + (void) new KRun(url, 0, true, true); + } + + // determine the state of display + if (thinkpad_state.display_toggle != last_thinkpad_state.display_toggle && + thinkpad_state.hibernate_toggle == last_thinkpad_state.hibernate_toggle) { + + // Some thinkpads have no hardware support to switch lcd/crt. They also + // don't reflect the current state in thinkpad_state.display_state. So, if + // thinkpad_state.display_toggle changes, but thinkpad_state.display_state does + // not change, simulate the display state. + + unsigned int display_state = 1; + if (thinkpad_state.display_state == last_thinkpad_state.display_state) { + display_state = display_state % 3 + 1; + } else { + display_state = thinkpad_state.display_state; + } + + switch (display_state & 0x03) { + case 0x1: + _interface->displayText(i18n("Display changed: LCD on, CRT off")); + break; + + case 0x2: + _interface->displayText(i18n("Display changed: LCD off, CRT on")); + break; + + case 0x3: + _interface->displayText(i18n("Display changed: LCD on, CRT on")); + break; + } + } + + // determine the state of hv expansion + if (thinkpad_state.expand_toggle != last_thinkpad_state.expand_toggle) { + showToggleMessage(i18n("HV Expansion is on"), i18n("HV Expansion is off"), (thinkpad_state.expand_toggle & 0x01) == 1); + } + + // determine power management mode AC + if (thinkpad_state.powermgt_ac != last_thinkpad_state.powermgt_ac) { + switch(thinkpad_state.powermgt_ac) { + case 0x4: + _interface->displayText(i18n("Power management mode AC changed: PM AC high")); + break; + + case 0x2: + _interface->displayText(i18n("Power management mode AC changed: PM AC auto")); + break; + + case 0x1: + _interface->displayText(i18n("Power management mode AC changed: PM AC manual")); + break; + + default: + _interface->displayText(i18n("Power management mode AC changed: PM AC unknown")); + break; + } + } + + // determine power management mode battery + if (thinkpad_state.powermgt_battery != last_thinkpad_state.powermgt_battery) { + switch(thinkpad_state.powermgt_battery) { + case 0x4: + _interface->displayText(i18n("Power management mode battery changed: PM battery high")); + break; + + case 0x2: + _interface->displayText(i18n("Power management mode battery changed: PM battery auto")); + break; + + case 0x1: + _interface->displayText(i18n("Power management mode battery changed: PM battery manual")); + break; + + default: + _interface->displayText(i18n("Power management mode battery changed: PM battery unknown")); + break; + } + } + + // determine the state of wireless lan + if (thinkpad_state.wireless_toggle != last_thinkpad_state.wireless_toggle) { + showToggleMessage(i18n("Wireless LAN is enabled"), i18n("Wireless LAN is disabled"), thinkpad_state.wireless_toggle == 1); + } + + // determine the state of bluetooth + if (thinkpad_state.bluetooth_toggle != last_thinkpad_state.bluetooth_toggle) { + showToggleMessage(i18n("Bluetooth is enabled"), i18n("Bluetooth is disabled"), thinkpad_state.bluetooth_toggle == 1); + } + + return pollResult; +} + + +int ThinkPadMonitor::progress() const { + return m_progress; +} + +QString ThinkPadMonitor::message() const { + //unused + //return i18n("yer maw!"); + return ""; +} + +bool ThinkPadMonitor::getNvramState(thinkpad_state_struct* thinkpad_state) { +#ifndef Q_OS_FREEBSD + int file; + unsigned char buffer[114]; + + // open nvram for reading + // must use open/close because seek is not supported by nvram + if ((file=open(m_nvramFile.latin1(), O_RDONLY|O_NONBLOCK)) == -1) { + kdError() << "Unable to open device: " << m_nvramFile << endl; + return false; + } + + // read nvram + if (read(file, buffer, sizeof(buffer)) != sizeof(buffer)) { + kdError() << "Unable to read from device: " << m_nvramFile << endl; + return false; + } + + // close nvram device + if (close(file) == -1) { + kdError() << "Unable to close device %s: " << m_nvramFile << endl; + return false; + } + + thinkpad_state->thinkpad_toggle + = (thinkpad_state->thinkpad_toggle & ~0x01) | (( buffer[0x57] & 0x08) >> 3); + thinkpad_state->zoom_toggle + = (thinkpad_state->zoom_toggle & ~0x01) | ((~buffer[0x57] & 0x20) >> 5); + thinkpad_state->display_toggle + = (thinkpad_state->display_toggle & ~0x01) | (( buffer[0x57] & 0x40) >> 6); + thinkpad_state->home_toggle + = (thinkpad_state->home_toggle & ~0x01) | (( buffer[0x56] & 0x01) ); + thinkpad_state->search_toggle + = (thinkpad_state->search_toggle & ~0x01) | (( buffer[0x56] & 0x02) >> 1); + thinkpad_state->mail_toggle + = (thinkpad_state->mail_toggle & ~0x01) | (( buffer[0x56] & 0x04) >> 2); + thinkpad_state->thinklight_toggle + = (thinkpad_state->thinklight_toggle & ~0x01) | (( buffer[0x58] & 0x10) >> 4); + thinkpad_state->hibernate_toggle + = (thinkpad_state->hibernate_toggle & ~0x01) | (( buffer[0x58] & 0x01) ); + thinkpad_state->display_state + = (( buffer[0x59] & 0x03) ); + thinkpad_state->expand_toggle + = (thinkpad_state->expand_toggle & ~0x01) | (( buffer[0x59] & 0x10) >> 4); + thinkpad_state->brightness_level + = (( buffer[0x5E] & 0x07) ); + thinkpad_state->brightness_toggle + = (thinkpad_state->brightness_toggle & ~0x01) | (( buffer[0x5E] & 0x20) >> 5); + thinkpad_state->volume_level + = (( buffer[0x60] & 0x0f) ); + thinkpad_state->volume_toggle + = (thinkpad_state->volume_toggle & ~0x01) | (( buffer[0x60] & 0x80) >> 7); + thinkpad_state->mute_toggle + = (thinkpad_state->mute_toggle & ~0x01) | (( buffer[0x60] & 0x40) >> 6); + thinkpad_state->powermgt_ac + = (( buffer[0x39] & 0x07) ); + thinkpad_state->powermgt_battery + = (( buffer[0x39] & 0x38) >> 3); +#else + u_int n = 0; + size_t len = sizeof(n); + + if ( sysctlbyname("dev.acpi_ibm.0.hotkey", &n, &len, NULL, 0) == -1 ) { + kdError() << "Unable to read sysctl: dev.acpi_ibm.0.hotkey" << endl; + return false; + } + + thinkpad_state->thinkpad_toggle + = (thinkpad_state->thinkpad_toggle & ~0x01) | (( n & (1<<3)) >> 3); + thinkpad_state->zoom_toggle + = (thinkpad_state->zoom_toggle & ~0x01) | (( n & (1<<4)) >> 4); + thinkpad_state->display_toggle + = (thinkpad_state->display_toggle & ~0x01) | (( n & (1<<6)) >> 6); + thinkpad_state->home_toggle + = (thinkpad_state->home_toggle & ~0x01) | (( n & (1<<0)) ); + thinkpad_state->search_toggle + = (thinkpad_state->search_toggle & ~0x01) | (( n & (1<<1)) >> 1); + thinkpad_state->mail_toggle + = (thinkpad_state->mail_toggle & ~0x01) | (( n & (1<<2)) >> 2); + thinkpad_state->hibernate_toggle + = (thinkpad_state->hibernate_toggle & ~0x01) | (( n & (1<<7)) >> 7); + thinkpad_state->expand_toggle + = (thinkpad_state->expand_toggle & ~0x01) | (( n & (1<<9)) >> 9); + thinkpad_state->brightness_toggle + = (thinkpad_state->brightness_toggle & ~0x01) | (( n & (1<<10)) >> 10); + thinkpad_state->volume_toggle + = (thinkpad_state->volume_toggle & ~0x01) | (( n & (1<<11)) >> 11); + + // Don't fail if the thinklight sysctl is not present. It is generated dynamically + if ( sysctlbyname("dev.acpi_ibm.0.thinklight", &n, &len, NULL, 0) != -1 ) + thinkpad_state->thinklight_toggle = n; + else + kdWarning() << "Unable to read sysctl: dev.acpi_ibm.0.thinklight" << endl; + + if ( sysctlbyname("dev.acpi_ibm.0.lcd_brightness", &n, &len, NULL, 0) == -1 ) { + kdError() << "Unable to read sysctl: dev.acpi_ibm.0.lcd_brightness" << endl; + return false; + } + thinkpad_state->brightness_level = n; + + if ( sysctlbyname("dev.acpi_ibm.0.volume", &n, &len, NULL, 0) == -1 ) { + kdError() << "Unable to read sysctl: dev.acpi_ibm.0.volume" << endl; + return false; + } + thinkpad_state->volume_level = n; + + if ( sysctlbyname("dev.acpi_ibm.0.mute", &n, &len, NULL, 0) == -1 ) { + kdError() << "Unable to read sysctl: dev.acpi_ibm.0.mute" << endl; + return false; + } + thinkpad_state->mute_toggle = n; + + // Don't fail if wlan or bluetooth sysctls are not present. They are generated dynamically + if ( sysctlbyname("dev.acpi_ibm.0.wlan", &n, &len, NULL, 0) != -1 ) + thinkpad_state->wireless_toggle = n; + else + kdWarning() << "Unable to read sysctl: dev.acpi_ibm.0.wlan" << endl; + + if ( sysctlbyname("dev.acpi_ibm.0.bluetooth", &n, &len, NULL, 0) != -1 ) + thinkpad_state->bluetooth_toggle = n; + else + kdWarning() << "Unable to read sysctl: dev.acpi_ibm.0.bluetooth" << endl; +#endif + return true; +} + +void ThinkPadMonitor::clearStruct(thinkpad_state_struct& thinkpad_state) { + thinkpad_state.thinkpad_toggle = 0; + thinkpad_state.zoom_toggle = 0; + thinkpad_state.display_toggle = 0; + thinkpad_state.home_toggle = 0; + thinkpad_state.search_toggle = 0; + thinkpad_state.mail_toggle = 0; + thinkpad_state.favorites_toggle = 0; + thinkpad_state.reload_toggle = 0; + thinkpad_state.abort_toggle = 0; + thinkpad_state.backward_toggle = 0; + thinkpad_state.forward_toggle = 0; + thinkpad_state.fn_toggle = 0; + thinkpad_state.thinklight_toggle = 0; + thinkpad_state.hibernate_toggle = 0; + thinkpad_state.display_state = 0; + thinkpad_state.expand_toggle = 0; + thinkpad_state.brightness_level = 0; + thinkpad_state.brightness_toggle = 0; + thinkpad_state.volume_level = 0; + thinkpad_state.volume_toggle = 0; + thinkpad_state.mute_toggle = 0; + thinkpad_state.ac_state = 0; + thinkpad_state.powermgt_ac = 0; + thinkpad_state.powermgt_battery = 0; + thinkpad_state.wireless_toggle = 0; + thinkpad_state.bluetooth_toggle = 0; +} + +void ThinkPadMonitor::showToggleMessage(QString onMessage, QString offMessage, bool state) { + QString message; + if (state) { + message = onMessage; + } else { + message = offMessage; + } + _interface->displayText(message); +} + +void ThinkPadMonitor::reconfigure(KConfig* config) { + config->setGroup("thinkpad"); + + m_nvramFile = config->readEntry("nvram", "/dev/nvram"); + m_softwareVolume = config->readBoolEntry("softwareVolume", true); + m_run = config->readBoolEntry("run", false); + m_volumeStep = config->readNumEntry("volumeStep", defaultVolumeStep); + m_buttonThinkpad = config->readEntry("buttonThinkpad", "/usr/bin/konsole"); + m_buttonHome = config->readEntry("buttonHome", "/usr/bin/konqueror"); + m_buttonSearch = config->readEntry("buttonSearch", "/usr/bin/kfind"); + m_buttonMail = config->readEntry("buttonMail", "/usr/bin/kmail"); + m_buttonZoom = config->readEntry("buttonZoom", "/usr/bin/ksnapshot"); +} + +bool ThinkPadMonitor::retrieveVolume() { + bool kmix_error = false; + + DCOPReply reply = kmixClient->call("masterVolume"); + if (reply.isValid()) { + m_volume = reply; + } else { + kmix_error = true; + } + + if (kmix_error) { // maybe the error occurred because kmix wasn't running + if (kapp->startServiceByDesktopName("kmix")==0) { // trying to start kmix + // trying again + reply = kmixClient->call("masterVolume"); + if (reply.isValid()) { + m_volume = reply; + kmix_error = false; + kmixWindow->send("hide"); + } + } + } + + if (kmix_error) { + kdError() << "KMilo: ThinkPadMonitor could not access kmix/Mixer0 via dcop" << endl; + return false; + } else { + return true; + } +} + +void ThinkPadMonitor::setVolume(int volume) { + if (!retrieveVolume()) { + return; + } + + if (volume > 100) { + m_volume = 100; + } else if (volume < 0) { + m_volume = 0; + } else { + m_volume = volume; + } + kmixClient->send("setMasterVolume", m_volume); + + //write back to nvram but only if volume steps is not default + if (m_volumeStep != defaultVolumeStep) { + setNvramVolume(); + } + m_progress = m_volume; +} + +void ThinkPadMonitor::setNvramVolume() { +#ifndef Q_OS_FREEBSD + int file; + char buffer; + + //open nvram + if ((file = open(m_nvramFile.latin1(), O_RDWR|O_NONBLOCK)) == -1) { + kdError() << "Unable to open device " << m_nvramFile << endl; + return; + } + + // jump to volume section + if (lseek(file, 0x60, SEEK_SET) == -1 ) { + kdError() << "Unable to seek device " << m_nvramFile << endl; + return; + } + + // read nvram + if (read(file, &buffer, sizeof(buffer)) != sizeof(buffer)) { + kdError() << "Unable to read from device " << m_nvramFile << endl; + return; + } + + // set volume_level to the value we write back to nvram + // taken from tpb, unfortunatly I'm not sure why it works + thinkpad_state.volume_level = 0x07; + buffer &= 0xf0; + buffer |= thinkpad_state.volume_level; + + // jump to volume section + if (lseek(file, 0x60, SEEK_SET) == -1 ) { + kdError() << "Unable to seek device " << m_nvramFile << endl; + return; + } + + // write std value for volume + if (write(file, &buffer, sizeof(buffer)) != sizeof(buffer)) { + kdError() << "Unable to write to device " << m_nvramFile << endl; + return; + } + + close(file); +#else + u_int n = thinkpad_state.volume_level; + + if (sysctlbyname("dev.acpi_ibm.0.volume", NULL, NULL, &n, sizeof(n))) + kdError() << "Unable to write sysctl: dev.acpi_ibm.0.volume" << endl; +#endif +} + +} + +K_EXPORT_COMPONENT_FACTORY(kmilo_thinkpad, KGenericFactory("kmilo_thinkpad")) diff --git a/kmilo/thinkpad/thinkpad.h b/kmilo/thinkpad/thinkpad.h new file mode 100644 index 0000000..f195b2e --- /dev/null +++ b/kmilo/thinkpad/thinkpad.h @@ -0,0 +1,208 @@ +/* + This file is part of the KDE project + + Copyright (c) 2004 Jonathan Riddell + + Based on Demo kmilo service by George Staikos + Copyright (c) 2003 George Staikos + + And tpb by Markus Braun http://www.nongnu.org/tpb/ + Copyright (C) 2002,2003 Markus Braun + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef _THINKPAD_H_ +#define _THINKPAD_H_ + +#include +#include + +#include +#include + +#include "monitor.h" + +namespace KMilo { + + +const int defaultVolumeStep = 14; + +// all nvram toggle values are stored in bit 0 +// all xevents toggle values are stored in bit 1 +// xevent and apm toggles are not used, kept for compatibility with tpb +typedef struct { + unsigned int thinkpad_toggle; // ThinkPad button + unsigned int zoom_toggle; // zoom toggle + unsigned int display_toggle; // display toggle + unsigned int home_toggle; // Home button + unsigned int search_toggle; // Search button + unsigned int mail_toggle; // Mail button + unsigned int favorites_toggle; // Favorites button (xevent) + unsigned int reload_toggle; // Reload button (xevent) + unsigned int abort_toggle; // Abort button (xevent) + unsigned int backward_toggle; // Backward button (xevent) + unsigned int forward_toggle; // Forward button (xevent) + unsigned int fn_toggle; // Fn button (xevent) + unsigned int thinklight_toggle; // ThinkLight + unsigned int hibernate_toggle; // hibernation/suspend toggle + unsigned int display_state; // display state + unsigned int expand_toggle; // hv expansion state + unsigned int brightness_level; // brightness level + unsigned int brightness_toggle; // brightness toggle + unsigned int volume_level; // volume level + unsigned int volume_toggle; // volume toggle + unsigned int mute_toggle; // mute toggle + unsigned int ac_state; // ac connected (apm) + unsigned int powermgt_ac; // power management mode ac + unsigned int powermgt_battery; // power management mode battery + unsigned int wireless_toggle; // wireless lan toggle + unsigned int bluetooth_toggle; // bluetooth toggle +} thinkpad_state_struct; + +/** + * KMilo plugin for IBM Thinkpads + * Requires read access of nvram: insmod nvram; mknod /dev/nvram c 10 144; chmod 664 /dev/nvram + * + * Models R31 and R30 do not have hardware mixers, other models + * probably want a smaller volume change than thinkpad's default, for + * this you need write access to nvram: chmod 666 /dev/nvram + */ +class ThinkPadMonitor : public Monitor { + public: + ThinkPadMonitor(QObject *parent, const char *name, const QStringList&); + virtual ~ThinkPadMonitor(); + + /** + * Reimplemented from KMilo::Monitor. + * Loads configuration, clears struct, sets volume if necessary. + */ + virtual bool init(); + + /** + * Reimplemented from KMilo::Monitor. + * Called by KMilo, this checks the nvram and acts on any changes + */ + virtual DisplayType poll(); + + /** + * Reimplemented from KMilo::Monitor. + * Called by KMilo if poll() returns a volume or brightness change. + * Returns the new volume or brightness percentage. + */ + virtual int progress() const; + + /** + * Reimplemented from KMilo::Monitor. + * Not used, we just set the message ourselves using _interface->displayText() + */ + virtual QString message() const; + protected: + /** + * Reimplemented from KMilo::Monitor. + * Loads configuration from kmilorc + */ + virtual void reconfigure(KConfig*); + private: + /** + * get the current state from the nvram + */ + bool getNvramState(thinkpad_state_struct* thinkpad_state); + + /** + * get the current state from the nvram + */ + void setNvramVolume(); + + /** + * set all values of thinkpad_state to zero + */ + void clearStruct(thinkpad_state_struct& thinkpad_state); + + /** + * Displays paramater message followed by 'on' or + * 'off' depending on state + */ + void showToggleMessage(QString onMessage, QString offMessage, bool state); + + /** + * Returned by progress() + */ + int m_progress; + + /** + * The file to read data from, default is /dev/nvram + */ + QString m_nvramFile; + + /** + * Some thinkpads change volume in hardware, others we + * have to do it ourselves + */ + bool m_softwareVolume; + + /** + * Config variable determines if this kmilo service is run or not + */ + bool m_run; + + /** + * Amount to change volume by each time, default is 14 + * (as builtin to thinkpads) + */ + int m_volumeStep; + + /** + * Thinkpad button + */ + QString m_buttonThinkpad; + + /** + * Home button + */ + QString m_buttonHome; + + /** + * Search button + */ + QString m_buttonSearch; + + /** + * Mail button + */ + QString m_buttonMail; + + /** + * Zoom button + */ + QString m_buttonZoom; + + /** + * Used for changing the volume if m_softwareVolume is true + */ + void setVolume(int volume); + DCOPRef* kmixClient; + DCOPRef* kmixWindow; + bool retrieveVolume(); + int m_volume, m_oldVolume; + + thinkpad_state_struct thinkpad_state; + thinkpad_state_struct last_thinkpad_state; +}; + +} //close namespace + +#endif diff --git a/kregexpeditor/Comments b/kregexpeditor/Comments new file mode 100644 index 0000000..71f4470 --- /dev/null +++ b/kregexpeditor/Comments @@ -0,0 +1,4 @@ +(1) If I do not resize the widget to be reparented then it will take up all + the size of its new parent, and the parent will never receive a + repaint event, and will thus never get a chance to resize its new child + to a proper size (This is namely done in repaintEvent() ). diff --git a/kregexpeditor/KMultiFormListBox/Makefile.am b/kregexpeditor/KMultiFormListBox/Makefile.am new file mode 100644 index 0000000..5ee885f --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/Makefile.am @@ -0,0 +1,15 @@ +AM_CPPFLAGS = -DQT_NO_CAST_ASCII +noinst_LTLIBRARIES = libkmultiformlistbox.la + +INCLUDES= -I$(srcdir)/../KWidgetStreamer $(all_includes) + +include_HEADERS = kmultiformlistboxentry.h kmultiformlistbox.h \ + kmultiformlistboxfactory.h +noinst_HEADERS = ccp.h indexWindow.h kmultiformlistbox-multivisible.h \ + kmultiformlistbox-windowed.h widgetwindow.h windowlistboxitem.h +libkmultiformlistbox_la_SOURCES = ccp.cpp kmultiformlistboxentry.cpp \ + kmultiformlistbox.cpp kmultiformlistbox-multivisible.cpp \ + kmultiformlistboxfactory.cpp indexWindow.cpp \ + kmultiformlistbox-windowed.cpp widgetwindow.cpp windowlistboxitem.cpp + +METASOURCES = AUTO diff --git a/kregexpeditor/KMultiFormListBox/TODO b/kregexpeditor/KMultiFormListBox/TODO new file mode 100644 index 0000000..0c20864 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/TODO @@ -0,0 +1 @@ +- cut/copy/paste should place/read data from the system clipboard. diff --git a/kregexpeditor/KMultiFormListBox/ccp.cpp b/kregexpeditor/KMultiFormListBox/ccp.cpp new file mode 100644 index 0000000..d64a3b2 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/ccp.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +//--------------------- +// ccp = Cut-Copy-Paste +//--------------------- + +#include "kmultiformlistbox-multivisible.h" +#include "ccp.h" +#include +#include +#ifdef QT_ONLY + #include "compat.h" +#else + #include +#endif + +CCP::CCP(KMultiFormListBoxMultiVisible *ee_, KMultiFormListBoxEntry *eee_) : QObject() { + ee = ee_; + eee = eee_; + install(eee); +} + +void CCP::install(QObject *elm) +{ + elm->installEventFilter(this); + const QObjectList *children = elm->children(); + if (children) { + QObjectListIt it = QObjectListIt(*children); + + while (QObject *child=it.current()) { + if (child->inherits("KMultiFormListBoxMultiVisible")) { + // Stop if the widget is an KMultiFormListBox, as this widget has its own cut/copy/paste + } + else { + install(child); + } + ++it; + } + } +} + +// This function post the Cut/Copy/Paste menu +bool CCP::eventFilter(QObject *, QEvent *event) +{ + if (event->type() != QEvent::MouseButtonPress || + ((QMouseEvent *) event)->button() != RightButton || + ((QMouseEvent *) event)->state() != QEvent::ControlButton) { + return false; + } + + QPoint pos = ((QMouseEvent *) event)->globalPos(); + + QPopupMenu *menu = new QPopupMenu(); + menu->insertItem(i18n("Cut"),1); + menu->insertItem(i18n("Copy"),2); + menu->insertItem(i18n("Paste"),3); + menu->insertItem(i18n("Insert Blank"),4); + + int res=menu->exec(pos); + switch (res) { + case 1: ee->cut(eee); break; + case 2: ee->copy(eee); break; + case 3: ee->paste(eee); break; + case 4: ee->addElement(eee); break; + } + return true; +} + diff --git a/kregexpeditor/KMultiFormListBox/ccp.h b/kregexpeditor/KMultiFormListBox/ccp.h new file mode 100644 index 0000000..41857a5 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/ccp.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __ccp +#define __ccp + + +/** + Helper class for @ref KMultiFormListBoxMultiVisible which is used to install EventFilters. + + When the user presses CTRL + right mouse button then a menu should + appear which offers him cut and paste capabilities for the entries in + the KMultiFormListBoxMultiVisible. + + To obtain this an event filter must be install for each subwidget of the + KMultiFormListBoxMultiVisible. This event filter must catch the right mouse press event and + post the menu. This requires a widget which has the method @ref + eventFilter defined. We have this helper class exactly for this purpose. + + For each @ref KMultiFormListBoxEntry in the @ref KMultiFormListBoxMultiVisible widget an instance of + this class is associated. + + CCP stand for Cut Copy and Paste + + @internal +**/ +class CCP :public QObject { + +private: + friend class KMultiFormListBoxMultiVisible; + /** + * Constructor is private so only the class @ref KMultiFormListBoxMultiVisible may create an + * instance of this widget. + **/ + CCP(KMultiFormListBoxMultiVisible *,KMultiFormListBoxEntry *); + + void install(QObject *); + bool eventFilter(QObject *, QEvent *); + + // Instance variables. + + KMultiFormListBoxMultiVisible *ee; + KMultiFormListBoxEntry *eee; +}; + +#endif /* ccp */ + diff --git a/kregexpeditor/KMultiFormListBox/idx.xbm b/kregexpeditor/KMultiFormListBox/idx.xbm new file mode 100644 index 0000000..e51baee --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/idx.xbm @@ -0,0 +1,5 @@ +#define idx_width 16 +#define idx_height 12 +static char idx_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x04, 0x02, 0x04, 0x02, 0xc4, 0x8a, + 0x24, 0x53, 0x14, 0x22, 0x14, 0x22, 0x24, 0x53, 0xce, 0x8a, 0x00, 0x00}; diff --git a/kregexpeditor/KMultiFormListBox/indexWindow.cpp b/kregexpeditor/KMultiFormListBox/indexWindow.cpp new file mode 100644 index 0000000..362d012 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/indexWindow.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include "indexWindow.moc" +#endif + +#include "indexWindow.h" +#include +#include + +indexWindow::indexWindow() : QWidget(0,"", WStyle_Customize | WType_Popup) +{ + lb = new QListBox(this); + connect(lb,SIGNAL(selected(int)), this, SLOT(lbSelected(int))); + QHBoxLayout *lay = new QHBoxLayout(this); + lay->addWidget(lb); + lbFinish = false; +} + +void indexWindow::lbSelected(int index) +{ + lbFinish = true; + hide(); + lbFinish = false; + finish(index); +} + +void indexWindow::finish(int index) +{ + itemSelected = index; + qApp->exit_loop(); +} + + +void indexWindow::insertItem(QString txt) +{ + lb->insertItem(txt); +} + +void indexWindow::hideEvent(QHideEvent *h) +{ + QWidget::hideEvent(h); + if (!lbFinish) + finish(-1); +} + + +int indexWindow::exec(const QPoint & /*start*/, int /*width*/) +{ + // This code is not xinerama safe, on the other hand this part of the widget + // is not used in KRegExpEditor. This is part of a widget which has + // never been completed, but which is used partly by KRegExpEditor. + // 23 Feb. 2003 11:28 -- Jesper K. Pedersen +/* + // calculate the height of all the elements together. + // I need to do it this way, as sizeHint doesn't report the correct size + // and itemHeight doesn't neither. + int elm_h = lb->item(0)->height(lb) * lb->count(); + elm_h += 2*lb->frameWidth(); + + QWidget *desktop = QApplication::desktop(); + int desktop_h = desktop->height(); + int rest_h = desktop_h - start.y(); + int below_h = QMAX(rest_h, 200); + + int start_y = start.y(); + + if (rest_h < 200 && elm_h > 200) { + start_y = desktop_h-QMIN(elm_h,200); + } + + setGeometry(start.x(), start_y, width, QMIN(elm_h, below_h)); + show(); + qApp->enter_loop(); + return itemSelected; +*/ + return 0; +} + diff --git a/kregexpeditor/KMultiFormListBox/indexWindow.h b/kregexpeditor/KMultiFormListBox/indexWindow.h new file mode 100644 index 0000000..3597960 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/indexWindow.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __indexWindow +#define __indexWindow + +#include + +/** + Post a toplevel listbox synchronously. + + When the user presses the Idx button in the @ref KMultiFormListBox, then a + listbox with the elements from the KMultiFormListBox must be shown. From this + listbox the user should chose the element he wants to scroll to. + This widget takes care of posting this listbox, and ensuring that the + user can not do anything else before he has chosen an element. + + This widget resembles the behavior of @ref QPopupMenu, the difference + is, however, that the QPopupMenu can not handle that the elements in the + menu exceed the size of the screen. This widget can. + + In the future this widget may be replaced with the QPopupMenu if the + QPopupMenu can handle this situation. But for now - it works! + + @internal +**/ +class indexWindow : public QWidget{ + +Q_OBJECT + +public: + indexWindow(); + + /** + This method inserts an element into the listbox which is shown when + the @ref exec method is invoked. + **/ + void insertItem(QString txt); + + /** + This function shows the index window with the elements inserted using + the @ref insertItem function. The function will not return before the + user has chosen an element in the listbox, or have pressed the right + mouse button outside the window. As a result of returning from this + function, the listbox is hidden. + + @param start The upper left corner of the pop-up window. + @param width The width of the window + @return The index of the element chosen, or -1 if no element has been + chosen. + **/ + int exec(const QPoint &start, int width); + +protected: + void finish(int retVal); + virtual void hideEvent(QHideEvent *h); + +protected slots: + void lbSelected(int); + +private: + QListBox *lb; + bool lbFinish; + int itemSelected; + +}; + +#endif /* indexWindow */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.cpp b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.cpp new file mode 100644 index 0000000..335863b --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" + #include +#else + #include + #include "kmultiformlistbox-multivisible.moc" +#endif + +#include "kmultiformlistbox-multivisible.h" +#include "indexWindow.h" +#include "ccp.h" + +#include + +const int indexButtonWidth = 16; +const int indexButtonHeight = 12; +const uchar indexButtonBits[] = { + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x04, 0x02, 0x04, 0x02, 0xc4, 0x8a, + 0x24, 0x53, 0x14, 0x22, 0x14, 0x22, 0x24, 0x53, 0xce, 0x8a, 0x00, 0x00 +}; + + +KMultiFormListBoxMultiVisible::KMultiFormListBoxMultiVisible(KMultiFormListBoxFactory *fact, QWidget *parent, const char *name) + : QScrollView(parent, name) +{ + factory = fact; + + // Initialize the element list + elms = new WidgetList(); + + // Initialize the clipper. + enableClipper(true); + resizeContents(50,50); // This is required for proper functionality +} + + + +//---------------------------------------------------------------------- +// This function returns a list of the elements in the KMultiFormListBox widget. +//---------------------------------------------------------------------- +KMultiFormListBoxEntryList KMultiFormListBoxMultiVisible::elements() +{ + KMultiFormListBoxEntryList res; + for (QWidget *child = elms->first(); child; child=elms->next()) { + if (strcmp(child->name(),"seperator") != 0) { + res.append((KMultiFormListBoxEntry *) child); + } + } + return res; +} + + +//---------------------------------------------------------------------- +// This function is called whenever the KMultiFormListBox widget is resized. It is +// necessary to ensure that the content of the clipper is resized. +//---------------------------------------------------------------------- +void KMultiFormListBoxMultiVisible::resizeEvent(QResizeEvent *e) +{ + // The call of the super class ensures that the outer border is updated. + QScrollView::resizeEvent(e); + + updateClipperContent(); +} + +void KMultiFormListBoxMultiVisible::updateClipperContent() +{ + // Extract the current size of the clipper + int ClipperWidth = clipper()->size().width(); + int ClipperHeight = clipper()->size().height(); + + // Initialize the calculation of the size of the new clipper. + int totalHeight = 0; + int maxWidth = ClipperWidth; + int count = 0; + + + // calculate the required size. + for (QWidget *child = elms->first(); child; child=elms->next()) { + maxWidth = QMAX(maxWidth, child->sizeHint().width()); + if (strcmp(child->name(), "seperator") != 0) { + totalHeight += child->sizeHint().height(); + count++; + } + else { + totalHeight += child->size().height(); + } + } + + // Calculate the extra height for the elements. + int extra = 0; + if (totalHeight < ClipperHeight && count != 0) { + extra = (ClipperHeight - totalHeight) / count; + totalHeight = ClipperHeight; + } + + // Now place the elements in the clipper. + int yPos = 0; + for (QWidget *child2 = elms->first(); child2; child2=elms->next()) { + int h; + if ( strcmp(child2->name(),"seperator") != 0) { + h = child2->sizeHint().height(); + h += extra; + } + else { + h = child2->size().height(); + } + + moveChild(child2, 0,yPos); + + child2->resize(maxWidth,h); + yPos += h; + } + + // Finally call the resize procedure for the clipper to ensure that the + // new sizes is shown properly. + resizeContents(maxWidth, totalHeight); +} + + +void KMultiFormListBoxMultiVisible::addElement() +{ + addElement(0); +} + +void KMultiFormListBoxMultiVisible::addElement(KMultiFormListBoxEntry *after) +{ + KMultiFormListBoxEntry *elm = factory->create(viewport()); + insertElmIntoWidget(elm, after); +} + +void KMultiFormListBoxMultiVisible::append(KMultiFormListBoxEntry *elm) +{ + elm->reparent(viewport(), 0, QPoint(0,0), false); + insertElmIntoWidget(elm, 0); +} + +void KMultiFormListBoxMultiVisible::delElement(QWidget *elm) +{ + int index = elms->find(elm); + QWidget *next = elms->at(index+1); + if (strcmp(next->name(),"seperator") != 0) { + elms->removeRef(next); + removeChild(next); + } + + elms->removeRef(elm); + removeChild(elm); + + updateClipperContent(); +} + +void KMultiFormListBoxMultiVisible::delAnElement() +{ + delElement(elms->at(0)); +} + +void KMultiFormListBoxMultiVisible::insertElmIntoWidget(KMultiFormListBoxEntry *elm, KMultiFormListBoxEntry *after) +{ + // Bind the index button if it exists. + if (elm->indexButton()) { + elm->indexButton()->setPixmap(QBitmap(indexButtonWidth, indexButtonHeight, + indexButtonBits, true)); + connect(elm->indexButton(), SIGNAL(clicked()), elm, SLOT(acceptIndexButton())); + connect(elm, SIGNAL(gotoIndex(KMultiFormListBoxEntry *)), + this, SLOT(showIndexList(KMultiFormListBoxEntry *))); + } + + // Find the location to insert the new element. + int index = elms->count(); + if (after) { + index = elms->findRef(after); + } + + // Now show the new element. + elms->insert(index, elm); + elm->show(); + addChild(elm,0,0); // updateClipperContent will place the child correctly. + + QWidget *sep = factory->separator(viewport()); + if (sep != 0) { + sep->setName("seperator"); + sep->show(); + addChild(sep,0,0); // updateClipperContent will place the child correctly. + elms->insert(index+1, sep); + } + + updateClipperContent(); + + showWidget(elm); // scroll to show the new widget. + + // install cut'n'paste functionallity + new CCP(this,elm); +} + + +//---------------------------------------------------------------------- +// This function shows the list of available Idx elements. +//---------------------------------------------------------------------- +void KMultiFormListBoxMultiVisible::showIndexList(KMultiFormListBoxEntry *elm) +{ + indexWindow *menu = new indexWindow(); + + // Insert the elements into the menu item. + for (QWidget *child = elms->first(); child; child=elms->next()) { + if ( strcmp(child->name(), "seperator") != 0) { + QString txt = ((KMultiFormListBoxEntry *) child)->idxString(); + menu->insertItem(txt); + } + } + + // Calculate the location of the window + QPoint start; + int width; + elm->indexWindowPos(&start, &width); + + // Show the window. + int index = menu->exec(start,width); + + if (index != -1) { + for (QWidget *child = elms->first(); child; child=elms->next()) { + if ( strcmp(child->name(), "seperator") != 0) { + + if (index == 0) { + showWidget((KMultiFormListBoxEntry *) child); + break; + } + index--; + } + } + } + delete menu; +} + +//---------------------------------------------------------------------- +// Scroll to the loaction of the given KMultiFormListBoxEntry element. +//---------------------------------------------------------------------- +void KMultiFormListBoxMultiVisible::showWidget(KMultiFormListBoxEntry *elm) +{ + setContentsPos(childX(elm), childY(elm)); +} + + +void KMultiFormListBoxMultiVisible::cut(KMultiFormListBoxEntry *elm) +{ + if (countElements(elms) == 1) { + KMessageBox::information(this, i18n("Due to a bug, it is not possible to remove the last element."), i18n("Internal Error") ); + return; + } + + QDataStream stream(clipboard, IO_WriteOnly); + factory->toStream( elm, stream ); + delElement(elm); +} + +void KMultiFormListBoxMultiVisible::copy(KMultiFormListBoxEntry *elm) +{ + QDataStream stream(clipboard, IO_WriteOnly); + factory->toStream(elm, stream); +} + +void KMultiFormListBoxMultiVisible::paste(KMultiFormListBoxEntry *oldElm) +{ + if (clipboard.size() == 0) { + KMessageBox::information(this, i18n("There is no element on the clipboard to paste in.")); + return; + } + + KMultiFormListBoxEntry *newElm = factory->create(viewport()); + QDataStream stream( clipboard, IO_ReadOnly ); + factory->fromStream(stream, newElm); + insertElmIntoWidget(newElm,oldElm); +} + + +int KMultiFormListBoxMultiVisible::countElements(WidgetList *elms) +{ + int count = 0; + + for (QWidget *child = elms->first(); child; child=elms->next()) { + if (dynamic_cast(child)) + count++; + } + + return count; +} + + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.h b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.h new file mode 100644 index 0000000..87aeba4 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-multivisible.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +// ------------------------------- Description ---------------------------- +// This is the KMultiFormListBox Widget. You do not need to inheret from this class, +// your interface to it will be through the methods `append` and `elements'. +// +// To make an instance of the widget, you need to inherit the classes +// `KMultiFormListBoxFactory' and `KMultiFormListBoxEntry'. +// ------------------------------------------------------------------------ +#ifndef __kmultiformlistboxmultivisble +#define __kmultiformlistboxmultivisble + +// -------------------------------- includes ------------------------------ +#include "kmultiformlistbox.h" +//------------------------------------------------------------------------- + +/** + @internal +*/ +class KMultiFormListBoxMultiVisible :public QScrollView, KMultiFormListBoxShower { + +Q_OBJECT + +friend class KMultiFormListBox; + +private: + /** + @param factory A factory used to generate the instances of KMultiFormListBoxEntry + class which is repeated in the KMultiFormListBox + @param parent A pointer to the parent widget + */ + KMultiFormListBoxMultiVisible(KMultiFormListBoxFactory *factory, QWidget *parent = 0, const char *name = 0); + + /** + @return The elements in the KMultiFormListBox + */ + KMultiFormListBoxEntryList elements(); + void append(KMultiFormListBoxEntry *); + + QWidget* qWidget() { return this; } + + +public slots: + + /** + This slot should be connected to a button which lets the user know that + he may get more elements in this KMultiFormListBox by pressing it. + The button should be labeled ``More Entries'' or something similar. + */ + void addElement(); // Adds an empty element to the KMultiFormListBox + + +protected slots: + + /** + When this slot is invoked then the Idx menu will be shown. + @param elm The KMultiFormListBoxEntry element where the Idx button was + pressed. This information is necessary to be able to calculate the + location where the drop down menu should be shown + */ + void showIndexList(KMultiFormListBoxEntry *elm); + +protected: + /** + Copies the element pointed to by which to the clipboard and removes it + from the interface. + This function is accessed from the class @ref CCP. + @param which A pointer to the element to cut. + */ + void cut(KMultiFormListBoxEntry *which); + + /** + Copies the element pointed to by which to the clipboard. + This function is accessed from the class @ref CCP. + @param which A pointer to the element to copied. + */ + void copy(KMultiFormListBoxEntry *which); + + /** + Paste the element from the clipboard to the KMultiFormListBox + This function is accessed from the class @ref CCP. + @param which A pointer to the KMultiFormListBoxEntry element which the + clipboard element should be inserted before,. + */ + void paste(KMultiFormListBoxEntry *which); + + /** + Inserts an empty KMultiFormListBoxEntry into the widget. + @param which A pointer to the element which the new empty widget + should be inserted before. + */ + + void addElement(KMultiFormListBoxEntry *); + + friend class CCP; + + virtual void resizeEvent(QResizeEvent *); + void addElemBefore(KMultiFormListBoxEntry *newElm, QWidget *existing); + void insertElmIntoWidget(KMultiFormListBoxEntry *elm, KMultiFormListBoxEntry *after); + void showWidget(KMultiFormListBoxEntry *elm); + void delElement(QWidget *); + void delAnElement(); + void addElemBefore(KMultiFormListBoxEntry *newElm, KMultiFormListBoxEntry *existing); + void updateClipperContent(); + int countElements(WidgetList *); + + + +private: + // Instance variables + + KMultiFormListBoxFactory *factory; + WidgetList *elms; + QPushButton *addBut; + QByteArray clipboard; +}; + + +#endif /* kmultiformlistboxmultivisble */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox-shower.h b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-shower.h new file mode 100644 index 0000000..fe786d7 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-shower.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __kmultiformlistboxshower +#define __kmultiformlistboxshower + +// -------------------------------- includes ------------------------------ +//------------------------------------------------------------------------- +typedef QPtrList KMultiFormListBoxEntryList ; + +/** + Abstract class defining the interface for widgets showing a number of @ref KMultiFormListBoxEntry. + + @internal +*/ +class KMultiFormListBoxShower { + +public: + virtual KMultiFormListBoxEntryList elements() = 0; + + /** Appends the given argument to the list */ + virtual void append(KMultiFormListBoxEntry *) = 0; + + /** Return the element as a QWidget */ + virtual QWidget* qWidget() = 0; + + /** Adds an empty element. */ + virtual void addElement() = 0; + + /** Deletes an element at the given index. */ + virtual void delElement(QWidget *) = 0; + + /** Deletes any element from the list */ + virtual void delAnElement() = 0; +}; + + +#endif /* kmultiformlistboxshower */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.cpp b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.cpp new file mode 100644 index 0000000..6ef14d3 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include + #include + #include "kmultiformlistbox-windowed.moc" +#endif + +#include "widgetwindow.h" +#include "windowlistboxitem.h" + +KMultiFormListBoxWindowed::KMultiFormListBoxWindowed(KMultiFormListBoxFactory *factory, QWidget *parent, + bool showUpDownButtons, bool showHelpButton, + QString addButtonText,const char *name) + : QWidget( parent, name ) +{ + _layout = new QVBoxLayout(this); + + QHBoxLayout *innerLayout = new QHBoxLayout(); + _layout->addLayout(innerLayout); + + _listbox = new KListBox(this,"listbox"); + _listbox->setSelectionMode(QListBox::Single); + innerLayout->addWidget(_listbox); + + QVBoxLayout *buttons = new QVBoxLayout(); + innerLayout->addLayout(buttons); + + QPushButton *but = new QPushButton(addButtonText, this,"Add Button"); + buttons->addWidget(but,0); + connect(but, SIGNAL(clicked()), this, SLOT(addNewElement())); + + but = new QPushButton(i18n("Edit"), this,"Edit Button"); + buttons->addWidget(but,0); + connect(but,SIGNAL(clicked()), this, SLOT(slotEditSelected())); + connect(_listbox, SIGNAL(doubleClicked(QListBoxItem *)), this, SLOT(slotEditSelected(QListBoxItem *))); + _buttonList.append(but); + + but = new QPushButton(i18n("Delete"), this, "Delete Button"); + buttons->addWidget(but,0); + connect(but, SIGNAL(clicked()), this, SLOT(slotDeleteEntry())); + _buttonList.append(but); + + but = new QPushButton(i18n("Copy"), this, "Copy Button"); + buttons->addWidget(but,0); + connect(but, SIGNAL(clicked()), this, SLOT(slotCopySelected())); + _buttonList.append(but); + + if (showUpDownButtons) { + but = new QPushButton(i18n("Up"), this, "Up Button"); + buttons->addWidget(but, 0); + connect(but, SIGNAL(clicked()), this, SLOT(slotMoveItemUp())); + _buttonList.append(but); + + but = new QPushButton(i18n("Down"), this, "Down Button"); + buttons->addWidget(but, 0); + connect(but, SIGNAL(clicked()), this, SLOT(slotMoveItemDown())); + _buttonList.append(but); + } + + if (showHelpButton) { + but = new KPushButton(KStdGuiItem::help(), this, "Help Button"); + buttons->addWidget(but, 0); + connect(but, SIGNAL(clicked()), this, SIGNAL(showHelp())); + } + + buttons->addStretch(1); + _factory = factory; + slotUpdateButtonState(); + +} + +KMultiFormListBoxEntryList KMultiFormListBoxWindowed::elements() +{ + KMultiFormListBoxEntryList list; + for (unsigned int i=0; i < _listbox->count(); i++) { + WindowListboxItem *item = (WindowListboxItem *) _listbox->item(i); + list.append(item->entry()); + } + return list; +} + +void KMultiFormListBoxWindowed::delElement(QWidget */*elm*/) +{ + // kdDebug() << "KMultiFormListBoxWindowed::delElement NOT YET IMPLEMENTED"<show(); + connect(widget, SIGNAL(finished()), this, SLOT(slotUpdateButtonState())); +} + +void KMultiFormListBoxWindowed::addElement() +{ + new WidgetWindow(_factory, _listbox); + slotUpdateButtonState(); +} + +void KMultiFormListBoxWindowed::slotEditSelected(QListBoxItem *item) +{ + ((WindowListboxItem *) item)->displayWidget(); +} + +void KMultiFormListBoxWindowed::slotEditSelected() +{ + WindowListboxItem *item = selected(); + if (item) { + slotEditSelected(item); + } +} + +void KMultiFormListBoxWindowed::slotDeleteEntry() +{ + WindowListboxItem *item = selected(); + if (item) { + int answer = + KMessageBox::warningContinueCancel(0, i18n("Delete item \"%1\"?").arg(item->text()),i18n("Delete Item"),KStdGuiItem::del()); + if (answer == KMessageBox::Continue) { + delete item; + slotUpdateButtonState(); + } + } +} + +void KMultiFormListBoxWindowed::slotCopySelected() +{ + WindowListboxItem *item = selected(); + if (item) { + item->clone(); + } +} + +WindowListboxItem *KMultiFormListBoxWindowed::selected() +{ + int i = _listbox->currentItem(); + if (i == -1) { + return 0; + } else { + return (WindowListboxItem *) _listbox->item(i); + } +} + +void KMultiFormListBoxWindowed::slotMoveItemUp() +{ + WindowListboxItem *item = selected(); + if (item == 0) + return; + + int index = _listbox->index(item); + if (index != 0) { + _listbox->takeItem(item); + _listbox->insertItem(item, index-1); + _listbox->setCurrentItem(item); + } +} + +void KMultiFormListBoxWindowed::slotMoveItemDown() +{ + WindowListboxItem *item = selected(); + if (item == 0) + return; + + unsigned int index = _listbox->index(item); + if (index < _listbox->count()) { + _listbox->takeItem(item); + _listbox->insertItem(item, index+1); + _listbox->setCurrentItem(item); + } +} + +void KMultiFormListBoxWindowed::slotUpdateButtonState() +{ + bool on = (_listbox->count() != 0); + for (unsigned int i=0; i<_buttonList.count(); i++) { + _buttonList.at(i)->setEnabled(on); + } +} diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.h b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.h new file mode 100644 index 0000000..74d6d9f --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox-windowed.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __kmultiformlistboxwindowed +#define __kmultiformlistboxwindowed + +#ifdef QT_ONLY + #include "compat.h" + #include +#else + #include +#endif + +#include "kmultiformlistboxfactory.h" +#include "kmultiformlistbox.h" +class WindowListboxItem; + + +/** + This class implements the windowed look for a @ref KMultiFormListBox + + @internal +*/ +class KMultiFormListBoxWindowed :public QWidget, KMultiFormListBoxShower { + +Q_OBJECT + +friend class KMultiFormListBox; + +private: + KMultiFormListBoxWindowed(KMultiFormListBoxFactory *factory, QWidget *parent, + bool showUpDownButtons, bool showHelpButton, QString addButtonText, + const char *name); + + KMultiFormListBoxEntryList elements(); + const KMultiFormListBoxEntryList elements() const; + void append(KMultiFormListBoxEntry *); + WindowListboxItem *selected(); + QWidget* qWidget() { return this; } + + QVBoxLayout* _layout; + KMultiFormListBoxFactory* _factory; + QPtrList _buttonList; + KListBox* _listbox; + virtual void delElement(QWidget *); // Deletes the given element + virtual void delAnElement(); + void addElement(); + + +public slots: + void addNewElement(); + +signals: + void showHelp(); + +private slots: + void slotEditSelected(); + void slotEditSelected(QListBoxItem *item); + void slotCopySelected(); + void slotMoveItemUp(); + void slotMoveItemDown(); + void slotDeleteEntry(); + void slotUpdateButtonState(); + +}; + + +#endif /* kmultiformlistboxwindowed */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox.cpp b/kregexpeditor/KMultiFormListBox/kmultiformlistbox.cpp new file mode 100644 index 0000000..57b5abb --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef QT_ONLY + #include "kmultiformlistbox.moc" +#endif + +#include "kmultiformlistbox-multivisible.h" +#include "kmultiformlistbox-windowed.h" + +KMultiFormListBox::KMultiFormListBox( KMultiFormListBoxFactory *factory, KMultiFormListBoxType tp, QWidget *parent, + bool showUpDownButtons, bool showHelpButton, QString addButtonText, + const char *name ) : QWidget( parent, name ) +{ + switch ( tp ) { + + case MultiVisible: + theWidget = new KMultiFormListBoxMultiVisible( factory, this, "KMultiFormListBox Widget" ); + break; + + case Windowed: + theWidget = new KMultiFormListBoxWindowed( factory, this, showUpDownButtons, + showHelpButton, addButtonText, "KMultiFormListBox Widget" ); + break; + } + + QWidget *widget = theWidget->qWidget(); + + QHBoxLayout *layout = new QHBoxLayout( this ); + _factory = factory; + layout->addWidget( widget ); +} + +void KMultiFormListBox::append( KMultiFormListBoxEntry *element ) +{ + theWidget->append( element ); +} + +void KMultiFormListBox::addElement() +{ + theWidget->addElement(); +} + +KMultiFormListBoxEntryList KMultiFormListBox::elements() +{ + return theWidget->elements(); +} + +const KMultiFormListBoxEntryList KMultiFormListBox::elements() const +{ + return const_cast(this)->elements(); +} + +void KMultiFormListBox::slotChangeFace( KMultiFormListBoxType /*newFace*/ ) +{ + // TODO + // kdDebug() << "It's not possible yet to change the face on the fly." << endl + // << "Please let me (blackie@kde.org) know that you need it, and I'll work on it" << endl; +} + +void KMultiFormListBox::toStream( QDataStream& stream ) const +{ + const KMultiFormListBoxEntryList elms = elements(); + stream << elms.count(); + for ( QPtrListIterator it(elms); *it; ++it) + _factory->toStream( *it, stream ); +} + +void KMultiFormListBox::fromStream( QDataStream& stream ) +{ + unsigned int fromCount, toCount; + stream >> fromCount; + + toCount = elements().count(); + + // adds/remove elements in the to list, to make it have the correct length. + for (unsigned int j=toCount; j< fromCount; ++j) { + addElement(); + } + for (unsigned int k=fromCount; k < toCount; ++k) { + theWidget->delAnElement(); + } + + KMultiFormListBoxEntryList elms = elements(); + for (QPtrListIterator it(elms); *it; ++it) + _factory->fromStream( stream, *it ); +} + + + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistbox.h b/kregexpeditor/KMultiFormListBox/kmultiformlistbox.h new file mode 100644 index 0000000..8e85808 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistbox.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __kmultiformlistbox +#define __kmultiformlistbox + +#include "kmultiformlistboxfactory.h" +#include "kmultiformlistbox-shower.h" +#include "kmultiformlistboxentry.h" +#include +#include +#include + +#ifdef QT_ONLY + #include "compat.h" +#else + #include +#endif + +class QDataStream; + + +typedef QPtrList KMultiFormListBoxEntryList ; +typedef QPtrList WidgetList; +class KMultiFormListBoxMultiVisible; + +/** + The main class used to get an KMultiFormListBox widget. + + The KMultiFormListBox widget consist of a sub-widget which is repeated a + number of times, it is up to the end user to determine the number of times + the sub widget is repeated, and he may require an additional copy simply + by pressing a ``Add'' or ``More Entries'' button. The KMultiFormListBox + widget has two different faces (i.e. two different end user + interfaces). One (Windowed) will show a listbox from which the end user + can access each subwidget containing data by pressing the LMB on a name + for the element. The other face (MultiVisible) shows all the subwidgets in + one huge ``Listbox''. + + To use the KMultiFormListBox widget you must create a class which is inherited + from the @ref KMultiFormListBoxFactory class. This new class must override the + function `create'. This function must return a freshly made instance of + the class @ref KMultiFormListBoxEntry (or a subclass of this). The KMultiFormListBoxEntry + instance is the one inserted into the KMultiFormListBox widget (one instance for + each sub widget in the KMultiFormListBox widget). + + @author Jesper Kjr Pedersen + **/ +class KMultiFormListBox : public QWidget { + +Q_OBJECT + +public: + + enum KMultiFormListBoxType {MultiVisible, Windowed}; + + /** + @param factory A factory used to generate the instances of + KMultiFormListBoxEntry class which is repeated in the KMultiFormListBox + @param parent A pointer to the parent widget + **/ + KMultiFormListBox(KMultiFormListBoxFactory *factory, + KMultiFormListBoxType tp=Windowed, + QWidget *parent = 0, bool showUpDownButtons = true, + bool showHelpButton = true, QString addButtonText = i18n("Add"), + const char *name = 0); + + /** + @return The elements in the KMultiFormListBox. + **/ + KMultiFormListBoxEntryList elements(); + const KMultiFormListBoxEntryList elements() const; + + /** + TODO. + **/ + void append(KMultiFormListBoxEntry *); + + /** write data out to stream */ + void toStream( QDataStream& stream ) const; + + /** reads data in from stream */ + void fromStream( QDataStream& stream ); + +public slots: + + /** + Adds an empty element to the KMultiFormListBox. + + This slot is only required for the @ref MultiVisible face. It should + be connected to a button which lets the user know that he may get more + elements in this KMultiFormListBox by pressing it. The button should + be labeled ``More Entries'' or something similar. + **/ + void addElement(); // Adds an empty element to the KMultiFormListBox + + /** + Changes the face of the KMultiFormListBox. + @param face The new face of the KMultiFormListBox + **/ + void slotChangeFace(KMultiFormListBoxType newFace); + +private: + KMultiFormListBoxShower *theWidget; + KMultiFormListBoxFactory *_factory; + +}; + + +#endif /* kmultiformlistbox */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.cpp b/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.cpp new file mode 100644 index 0000000..e6768a3 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef QT_ONLY + #include "kmultiformlistboxentry.moc" +#endif + +#include "kmultiformlistboxentry.h" +//---------------------------------------------------------------------- +// This function is needed to signal which of the KMultiFormListBox entries +// the Idx button was invoked from. +//---------------------------------------------------------------------- +void KMultiFormListBoxEntry::acceptIndexButton() +{ + emit gotoIndex(this); +} + + +void KMultiFormListBoxEntry::indexWindowPos(QPoint *start, int *width) +{ + // Calculate the position of the value widgets left-buttom border + QPoint global_point = valueWidget()->mapToGlobal(QPoint(0,0)); + start->setX(global_point.x()); + start->setY(global_point.y() + valueWidget()->height()); + + // Calculate the width of the list. + global_point = indexButton()->mapToGlobal(QPoint(0,0)); + *width = global_point.x() + indexButton()->width() - start->x(); +} diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.h b/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.h new file mode 100644 index 0000000..7937fe1 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistboxentry.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __kmultiformlistboxentry +#define __kmultiformlistboxentry + +#include +#include +#include + +/** + This widget must be the base class for an entry widget used in the @ref + KMultiFormListBox class. It is necessary for you to inherit this class to get any + information attached to the elements in the KMultiFormListBox. + + The KMultiFormListBox widget features a fast scrolling mechanism through the Idx + button. If you want to use this in you KMultiFormListBox, then you must do the + following: + @li Create a @ref QPushButton as a sub-widget to your KMultiFormListBoxEntry. + @li Override the @ref indexButton method to return your QPushButton + @li Override the @ref idxString to return a @ref QString + with a textual representation of the content in this KMultiFormListBoxEntry. This + string will be used in the drop-down box which the user gets when he + presses the Idx button. + @li The drop down window must be aligned horizontal to some widget + (which should be next to the Idx button, to ensure a good looking GUI. The + position of the drop down widget may be specified in two ways: (1) + override the @ref valueWidget method to return a widget, to align with + (that is the upper right corner of the drop down window will be the + same as the lower right corner of this widget) or (2) override the @ref + indexWindowPos method to return a start point for the drop down window and + a width. + **/ +class KMultiFormListBoxEntry : public QWidget +{ + Q_OBJECT + +public: + KMultiFormListBoxEntry(QWidget *parent, const char *name) : QWidget(parent,name) {} + + virtual QPushButton *indexButton() { return 0; } + virtual QWidget *valueWidget() { return 0; } + + virtual void indexWindowPos(QPoint *start, int *width); // both variables are return values. + + // This function must return a string representing the KMultiFormListBox. This is + // used when showing the fast-search menu available from the `Idx' button. + virtual QString idxString() { return QString::fromLatin1(""); } + +public slots: + void acceptIndexButton(); + +signals: + void gotoIndex(KMultiFormListBoxEntry *); + +}; + +#endif /* kmultiformlistboxentry */ + diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.cpp b/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.cpp new file mode 100644 index 0000000..89b5d74 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "kmultiformlistboxfactory.h" +#include + +QWidget *KMultiFormListBoxFactory::separator(QWidget *parent) { + QFrame* sep = new QFrame( parent ); + sep->setFrameStyle( QFrame::HLine | QFrame::Sunken); + sep->setLineWidth(1); + return sep; +} diff --git a/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.h b/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.h new file mode 100644 index 0000000..13f6561 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/kmultiformlistboxfactory.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +// -------------------------------- includes ------------------------------ +#ifndef __kmultiformlistboxfactory +#define __kmultiformlistboxfactory +#include +#include "kwidgetstreamer.h" +class KMultiFormListBoxEntry; +//------------------------------------------------------------------------- + + +/** + Factory use to generate elements for the @ref KMultiFormListBox widget. + + To use an @ref KMultiFormListBox, one must inherit from the class KMultiFormListBoxFactory + and override the method @ref create. This method must return an empty + element for the KMultiFormListBox (that is an @ref KMultiFormListBoxEntry or a subclass of + it). + + If you dislike the default separator between each of the elements or + simply do not want a separator in the KMultiFormListBox, then you may override + the method @ref separator. +**/ +class KMultiFormListBoxFactory : public KWidgetStreamer +{ +public: + virtual ~KMultiFormListBoxFactory() {} + + /** + This method must be overridden in subclasses and must return an + ``empty'' instance of the @ref KMultiFormListBoxEntry class, or perhaps rather + a subclass of this class. This instance will be owned by the caller of + this function. + + @param parent A pointer to the parent of this KMultiFormListBoxEntry widget + returned. + @return A fresh @ref KMultiFormListBoxEntry to be used in an instance of the + @ref KMultiFormListBox class. + **/ + virtual KMultiFormListBoxEntry *create(QWidget *parent) = 0; + + /** + This method is used to get a separator between the elements in an @ref + KMultiFormListBox. The widget returned from this method will be owned by the + caller. + + @param parent A pointer to the parent of the QWidget returned. + @return A widget which must be used as a separator between the @ref + KMultiFormListBoxEntry elements in an @ref KMultiFormListBox. + **/ + virtual QWidget *separator(QWidget *parent); +}; + +#endif /* kmultiformlistbox */ + diff --git a/kregexpeditor/KMultiFormListBox/widgetwindow.cpp b/kregexpeditor/KMultiFormListBox/widgetwindow.cpp new file mode 100644 index 0000000..022e452 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/widgetwindow.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "widgetwindow.h" +#include "windowlistboxitem.h" +#include + +WidgetWindow::WidgetWindow(KMultiFormListBoxFactory *factory, KListBox *lb) + :KDialogBase(Plain, i18n("Widget Configuration"), Ok | Cancel, Ok, 0, "ConfigWindow", false) +{ + init(factory, lb); +} + +WidgetWindow::WidgetWindow(KMultiFormListBoxFactory *factory, KMultiFormListBoxEntry *widget, KListBox *lb) + :KDialogBase(Plain, i18n("Widget Configuration"), Ok | Cancel, Ok, 0, "ConfigWindow", false) +{ + init(factory, lb, widget); +} + +void WidgetWindow::init(KMultiFormListBoxFactory *factory, KListBox *lb, KMultiFormListBoxEntry *widget) +{ + listbox = lb; + myFact = factory; + + QFrame *frame = plainPage(); + QHBoxLayout *lay = new QHBoxLayout(frame,0,-1,"WidgetWindow::init::lay"); + + if (widget != 0) { + myWidget = widget; + widget->reparent(frame, 0, QPoint(0,0)); + } + else { + myWidget = factory->create(frame); + } + QDataStream stream( _backup, IO_WriteOnly ); + myFact->toStream( myWidget, stream ); + + lay->addWidget(myWidget); + + if (widget != 0) { + initialShow = false; + myListboxItem = new WindowListboxItem(listbox,myWidget->idxString(), this); + } + else { + initialShow = true; + } +} + + + +WidgetWindow::~WidgetWindow() +{ + delete myWidget; +} + +void WidgetWindow::slotOk() +{ + if (initialShow) { + myListboxItem = new WindowListboxItem(listbox,myWidget->idxString(), this); + } + else { + myListboxItem->setText(myWidget->idxString()); + } + initialShow = false; + KDialogBase::slotOk(); +} + +void WidgetWindow::slotCancel() +{ + if (initialShow) { + deleteLater(); + } + else { + QDataStream stream( _backup, IO_ReadOnly ); + myFact->fromStream( stream, myWidget ); + } + KDialogBase::slotCancel(); +} + +WidgetWindow *WidgetWindow::clone() +{ + WidgetWindow *item = new WidgetWindow(myFact, listbox); + QByteArray data; + QDataStream ws( data, IO_WriteOnly ); + myFact->toStream( myWidget, ws ); + QDataStream rs( data, IO_ReadOnly ); + myFact->fromStream( rs, item->myWidget ); + + item->slotOk(); + return item; +} + +void WidgetWindow::display() +{ + QDataStream stream( _backup, IO_WriteOnly); + myFact->toStream( myWidget, stream ); + show(); +} + +KMultiFormListBoxEntry *WidgetWindow::entry() +{ + return myWidget; +} diff --git a/kregexpeditor/KMultiFormListBox/widgetwindow.h b/kregexpeditor/KMultiFormListBox/widgetwindow.h new file mode 100644 index 0000000..f81b359 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/widgetwindow.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __configwindow +#define __configwindow + +#ifdef QT_ONLY + #include "compat.h" + #include +#else + #include + #include +#endif + +#include "kmultiformlistbox-windowed.h" + +/** + @internal +*/ +class WidgetWindow :public KDialogBase +{ + friend class KMultiFormListBoxWindowed; + friend class WindowListboxItem; + + WidgetWindow(KMultiFormListBoxFactory *, KListBox *); + WidgetWindow(KMultiFormListBoxFactory *, KMultiFormListBoxEntry *widget, KListBox *); + void init(KMultiFormListBoxFactory *, KListBox *, KMultiFormListBoxEntry *widget = 0); + void display(); + KMultiFormListBoxEntry *entry(); + WidgetWindow *clone(); + ~WidgetWindow(); + +protected slots: + void slotOk(); + void slotCancel(); + +private: + KMultiFormListBoxFactory *myFact; + KMultiFormListBoxEntry *myWidget; + QByteArray _backup; + KListBox *listbox; + WindowListboxItem *myListboxItem; + bool initialShow; +}; + +#endif // configwindow diff --git a/kregexpeditor/KMultiFormListBox/windowlistboxitem.cpp b/kregexpeditor/KMultiFormListBox/windowlistboxitem.cpp new file mode 100644 index 0000000..41f9e5b --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/windowlistboxitem.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "windowlistboxitem.h" +#include "widgetwindow.h" + +WindowListboxItem::WindowListboxItem(QListBox *lb, QString text, WidgetWindow *windowWidget) + :QListBoxText(lb, text), myItem(windowWidget) +{ +} + +WindowListboxItem::~WindowListboxItem() +{ + delete myItem; +} + +void WindowListboxItem::displayWidget() +{ + myItem->display(); +} + +void WindowListboxItem::clone() +{ + myItem->clone(); +} + +KMultiFormListBoxEntry *WindowListboxItem::entry() +{ + return myItem->entry(); +} + diff --git a/kregexpeditor/KMultiFormListBox/windowlistboxitem.h b/kregexpeditor/KMultiFormListBox/windowlistboxitem.h new file mode 100644 index 0000000..2505b88 --- /dev/null +++ b/kregexpeditor/KMultiFormListBox/windowlistboxitem.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __windowlistboxitem +#define __windowlistboxitem +#include +class WidgetWindow; +class KMultiFormListBoxWindowed; +class KMultiFormListBoxEntry; + + +/** + @internal +*/ +class WindowListboxItem :public QListBoxText +{ + friend class WidgetWindow; + friend class KMultiFormListBoxWindowed; +public: + WindowListboxItem(QListBox *, QString, WidgetWindow *); + ~WindowListboxItem(); + void clone(); + void displayWidget(); + KMultiFormListBoxEntry *entry(); + +private: + WidgetWindow *myItem; +}; + +#endif // __windowlistboxitem diff --git a/kregexpeditor/KWidgetStreamer/Makefile.am b/kregexpeditor/KWidgetStreamer/Makefile.am new file mode 100644 index 0000000..c9b1260 --- /dev/null +++ b/kregexpeditor/KWidgetStreamer/Makefile.am @@ -0,0 +1,9 @@ +AM_CPPFLAGS = -DQT_NO_CAST_ASCII +noinst_LTLIBRARIES = libkwidgetstreamer.la + +INCLUDES= -I$(srcdir)/../KMultiFormListBox $(all_includes) + +include_HEADERS = kwidgetstreamer.h +libkwidgetstreamer_la_SOURCES = kwidgetstreamer.cpp + +METASOURCES = AUTO diff --git a/kregexpeditor/KWidgetStreamer/kwidgetstreamer.cpp b/kregexpeditor/KWidgetStreamer/kwidgetstreamer.cpp new file mode 100644 index 0000000..e91813a --- /dev/null +++ b/kregexpeditor/KWidgetStreamer/kwidgetstreamer.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "kwidgetstreamer.h" +#include "kmultiformlistbox.h" +#include +#include + + +void KWidgetStreamer::toStream(const QObject* from, QDataStream& stream ) +{ + if ( from->inherits("KMultiFormListBox") ) { + // Hmm, we'll trust Qt that this dynamic_cast won't fail! + dynamic_cast(from)->toStream( stream ); + } + + propertyToStream( from, stream ); +} + +void KWidgetStreamer::fromStream( QDataStream& stream, QObject* to ) +{ + if ( to->inherits("KMultiFormListBox") ) { + // Hmm, we'll trust Qt that this dynamic_cast won't fail! + dynamic_cast(to)->fromStream( stream ); + } + + propertyFromStream( stream, to ); +} + + +void KWidgetStreamer::propertyToStream( const QObject* from, QDataStream& stream ) +{ + // Only handle widgets. Alternatives to widgets are layouts, validators, timers, etc. + if ( ! from->inherits("QWidget") ) + return; + + // Serializing all the children (if any). + const QObjectList* children = from->children(); + if ( children ) { + stream << children->count(); + for ( QObjectListIt it = QObjectListIt(*children); *it; ++it ) { + toStream( *it, stream ); + } + } + else { + stream << (unsigned int) 0; + } + + // Now stream out properties + for ( PropertyMapIt mapIt = _map.begin(); mapIt != _map.end(); mapIt++ ) { + QString tp = mapIt.key(); + PropertyList list = mapIt.data(); + if ( from->inherits( tp.latin1() ) ) { + for ( PropertyListIt it = list.begin(); it != list.end(); ++it ) { + QVariant prop = from->property( (*it).latin1() ); + if ( ! prop.isValid() ) + qWarning("Invalid property: %s:%s", tp.latin1(), (*it).latin1() ); + + stream << prop ; + } + } + } +} + + +void KWidgetStreamer::propertyFromStream( QDataStream& stream, QObject* to ) +{ + // Only handle widgets. Alternatives to widgets are layouts, validators, timers, etc. + if ( ! to->inherits("QWidget") ) + return; + + // Stream in all the children (if any) + const QObjectList* children = to->children(); + unsigned int count; + + stream >> count; + if ( children ) { + Q_ASSERT( count == children->count() ); + for ( QObjectListIt it = QObjectListIt(*children); *it; ++it ) + fromStream( stream, *it ); + } + else { + Q_ASSERT( count == 0 ); + } + + // Now stream in properties + for ( PropertyMapIt mapIt = _map.begin(); mapIt != _map.end(); mapIt++ ) { + QString tp = mapIt.key(); + PropertyList list = mapIt.data(); + if ( to->inherits( tp.latin1() ) ) { + for ( PropertyListIt it = list.begin(); it != list.end(); ++it ) { + QVariant value; + stream >> value; + to->setProperty((*it).latin1(), value); + } + } + } +} + +KWidgetStreamer::KWidgetStreamer () +{ + QStringList l; + + // QCheckBox + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("checked") << QString::fromLatin1("tristate"); + _map.insert(QString::fromLatin1("QCheckBox"), l); + + // QComboBox + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("editable") << QString::fromLatin1("currentItem") + << QString::fromLatin1("maxCount") << QString::fromLatin1("insertionPolicy") + << QString::fromLatin1("autoCompletion"); + _map.insert(QString::fromLatin1("QComboBox"), l); + + // QDial + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("tracking") << QString::fromLatin1("wrapping") + << QString::fromLatin1("value"); + _map.insert(QString::fromLatin1("QDial"), l); + + // QLCDNumber + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("numDigits") << QString::fromLatin1("mode") + << QString::fromLatin1("segmentStyle") << QString::fromLatin1("value"); + _map.insert(QString::fromLatin1("QLCDNumber"), l); + + // QLineEdit + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("text") << QString::fromLatin1("maxLength") + << QString::fromLatin1("echoMode") << QString::fromLatin1("alignment"); + _map.insert(QString::fromLatin1("QLineEdit"), l); + + // QMultiLineEdit + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("text") + << QString::fromLatin1("alignment"); + _map.insert(QString::fromLatin1("QTextEdit"), l); + + // QRadioButton + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("checked"); + _map.insert(QString::fromLatin1("QRadioButton"), l); + + // QSlider + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("value"); + _map.insert(QString::fromLatin1("QSlider"), l); + + // QSpinBox + l.clear(); + l << QString::fromLatin1("enabled") + << QString::fromLatin1("value"); + _map.insert(QString::fromLatin1("QSpinBox"), l); +} diff --git a/kregexpeditor/KWidgetStreamer/kwidgetstreamer.h b/kregexpeditor/KWidgetStreamer/kwidgetstreamer.h new file mode 100644 index 0000000..9534a92 --- /dev/null +++ b/kregexpeditor/KWidgetStreamer/kwidgetstreamer.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __kwidgetstreamer +#define __kwidgetstreamer +#include +#include +#include +#include + +/** + This class defines methods for streaming widget data. + + For each widget type rules are defined telling which attributes should be + streamed. If you need to stream other attributes or to avoid streaming + certain attributes, then this may be obtained by editing the property + map, which is obtained by calling @ref propertyMap. For further control + inherit from this class and override @ref toStream and @ref fromStream. + + The following example shows how you can avoid streaming + numDigits for a QLCDNumber. The same approach applies if you + want to add extra properties to be streamed. +
+   KWidgetStreamer streamer;
+   KWidgetStreamer::PropertyMap& map = streamer.propertyMap();
+   KWidgetStreamer::PropertyList& list = *map.find("QLCDNumber");
+   list.remove("numDigits");
+   
+**/ +class KWidgetStreamer +{ + +public: + typedef QStringList PropertyList; + typedef QMap< QString, PropertyList > PropertyMap; + typedef QMap< QString, PropertyList >::ConstIterator PropertyMapIt; + typedef QStringList::Iterator PropertyListIt; + + KWidgetStreamer(); + virtual ~KWidgetStreamer() {} + + virtual void toStream(const QObject* from, QDataStream& stream ); + virtual void fromStream(QDataStream& stream, QObject* to); + + PropertyMap& propertyMap() { return _map; } + + +protected: + void propertyToStream( const QObject* from, QDataStream& stream ); + void propertyFromStream( QDataStream& stream, QObject* to ); + +private: + PropertyMap _map; + +}; + + + +#endif /* __kwidgetstreamer */ + diff --git a/kregexpeditor/Makefile.am b/kregexpeditor/Makefile.am new file mode 100644 index 0000000..6f8a4e4 --- /dev/null +++ b/kregexpeditor/Makefile.am @@ -0,0 +1,65 @@ +SUBDIRS = KWidgetStreamer KMultiFormListBox picts predefined + +KDE_ICON=AUTO + +AM_CPPFLAGS = -DQT_NO_CAST_ASCII -I$(srcdir)/KWidgetStreamer -I$(srcdir)/KMultiFormListBox $(all_includes) + +# (useless) +noinst_HEADERS = \ + kregexpeditorgui.h editorwindow.h regexpwidget.h drag.h limitedcharlineedit.h regexp.h selectablelineedit.h \ + dragaccepter.h repeatwidget.h concwidget.h textwidget.h characterswidget.h zerowidgets.h multicontainerwidget.h \ + scrollededitorwindow.h compoundwidget.h singlecontainerwidget.h widgetfactory.h dcbutton.h charselector.h \ + lookaheadwidget.h textregexp.h textrangeregexp.h repeatregexp.h lookaheadregexp.h concregexp.h altnregexp.h \ + positionregexp.h dotregexp.h infopage.h kregexpeditorprivate.h compoundregexp.h pair.h triple.h myfontmetrics.h \ + regexpbuttons.h userdefinedregexps.h auxbuttons.h verifier.h verifybuttons.h errormap.h qtregexphighlighter.h \ + regexpconverter.h qtregexpconverter.h emacsregexpconverter.h regexphighlighter.h util.h + +# The library contains all the code that is shared between the module and the app +lib_LTLIBRARIES = libkregexpeditorcommon.la +libkregexpeditorcommon_la_SOURCES = \ + kregexpeditorgui.cpp editorwindow.cpp regexpwidget.cpp drag.cpp concwidget.cpp zerowidgets.cpp dragaccepter.cpp \ + repeatwidget.cpp characterswidget.cpp altnwidget.cpp limitedcharlineedit.cpp textregexp.cpp textrangeregexp.cpp \ + concregexp.cpp altnregexp.cpp positionregexp.cpp dotregexp.cpp repeatregexp.cpp textwidget.cpp \ + selectablelineedit.cpp multicontainerwidget.cpp scrollededitorwindow.cpp compoundwidget.cpp \ + singlecontainerwidget.cpp widgetfactory.cpp dcbutton.cpp gen_qregexplexer.cpp gen_qregexpparser.cc \ + charselector.cpp lookaheadregexp.cpp lookaheadwidget.cpp regexp.cpp infopage.cpp kregexpeditorprivate.cpp \ + compoundregexp.cpp auxbuttons.cpp myfontmetrics.cpp regexpbuttons.cpp userdefinedregexps.cpp verifier.cpp \ + verifybuttons.cpp errormap.cpp qtregexphighlighter.cpp regexpconverter.cpp qtregexpconverter.cpp \ + emacsregexpconverter.cpp regexphighlighter.cpp util.cpp + +libkregexpeditorcommon_la_LDFLAGS = $(all_libraries) -version-info 1:0:0 -no-undefined +libkregexpeditorcommon_la_LIBADD = KMultiFormListBox/libkmultiformlistbox.la \ + KWidgetStreamer/libkwidgetstreamer.la $(LIB_KIO) + +METASOURCES = AUTO + +service_DATA = kregexpeditorgui.desktop +servicedir = $(kde_servicesdir) + +#### The dynamically-loadable module (its interface is defined in kdelibs) +kde_module_LTLIBRARIES = libkregexpeditorgui.la +libkregexpeditorgui_la_SOURCES = kregexpeditorfactory.cpp +libkregexpeditorgui_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +libkregexpeditorgui_la_LIBADD = libkregexpeditorcommon.la + +#### Binary + +bin_PROGRAMS = kregexpeditor +kregexpeditor_SOURCES = main.cpp +kregexpeditor_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kregexpeditor_LDADD = libkregexpeditorcommon.la $(LIB_KIO) +kregexpeditor_INCLUDES = $(all_includes) + +xdg_apps_DATA = kregexpeditor.desktop + + +##### Build rules for the parser + +.PHONY: parser +parser: + cd $(srcdir) && flex -Pqregexp -ogen_qregexplexer.cpp qregexpparser.l + cd $(srcdir) && bison -d -p qregexp -o gen_qregexpparser.cc qregexpparser.y + +messages: + perl extractrc-from-regexp `find . -name "*.regexp"` > predefined-regexps.cpp + $(XGETTEXT) *.cpp *.h */*.cpp */*.h -o $(podir)/kregexpeditor.pot diff --git a/kregexpeditor/TODO b/kregexpeditor/TODO new file mode 100644 index 0000000..d8c492b --- /dev/null +++ b/kregexpeditor/TODO @@ -0,0 +1,49 @@ +TODO: +----- + +When the user drops something on the regular expression area that is of +mime type text/plain, then ask the user whether he want it parsed as a +regular expression or whether he wants it inserted as plain text (that is the text escaped) + +Later wishes: +------------- +- Make the KMultiFormListBox widget support that a line can show several entries. + Use this feature to show two CharSelectors on one line for selecting a single char + in the CharacterWidget. +- Cleanup in the use of repaint(). Several of the repaint() can be update() instead. +- add a checker widget, which can show what the regexp matches from a user defined text. +- add the posibility to travers the widget using the keyboard. +- Highlight the dragaccepter on dragEnter + +Back references +--------------- +- when deleting a compound widget, which has a backreference, what should be done with the + back reference? +- cut/past should preserve back reference id, while cut/copy should create + a new one. +- create interface for extracting information about back references. + +- support back references in the regexp: "(abc|def)\1" + +Modules to go through to search for places to use KRegExpEditor +--------------------------------------------------------------- +KodeKnight +kdeadmin +kdebase +kdeedu +kdegames +kdegraphics +kdeinstaller +kdelibs +kdemultimedia +kdenetwork +kdenonbeta +kdepim +kdesdk +kdetoys +kfte +kmusic +koffice +kpfa +ksite +quanta diff --git a/kregexpeditor/altnregexp.cpp b/kregexpeditor/altnregexp.cpp new file mode 100644 index 0000000..adebf1b --- /dev/null +++ b/kregexpeditor/altnregexp.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "altnregexp.h" +#include "widgetfactory.h" + +AltnRegExp::AltnRegExp( bool selected ) :RegExp( selected ) +{ + // Nothing to do +} + +void AltnRegExp::addRegExp( RegExp *elm ) +{ + list.append( elm ); + addChild( elm ); +} + +RegExpList AltnRegExp::children() const +{ + return list; +} + +bool AltnRegExp::check( ErrorMap& map, bool first, bool last ) +{ + bool possibleEmpty = false; + for ( RegExpListIt it(list); *it; ++it ) { + possibleEmpty = (*it)->check( map, first, last ) || possibleEmpty; + } + return possibleEmpty; +} + +QDomNode AltnRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement( QString::fromLocal8Bit( "Alternatives" ) ); + for ( RegExpListIt it(list); *it; ++it ) { + top.appendChild( (*it)->toXml( doc ) ); + } + return top; +} + +bool AltnRegExp::load( QDomElement top, const QString& version ) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit( "Alternatives" ) ); + + for ( QDomNode child = top.firstChild(); !child.isNull(); child = child.nextSibling() ) { + if ( ! child.isElement() ) + continue; // User might have added a comment. + + RegExp* regexp = WidgetFactory::createRegExp( child.toElement(), version ); + if ( regexp == 0 ) + return false; + addRegExp( regexp ); + } + return true; + +} + +bool AltnRegExp::operator==( const RegExp& other ) const +{ + // TODO: merge with ConcRegExp::operator== + + if ( other.type() != type() ) + return false; + + const AltnRegExp& theOther = dynamic_cast( other ); + + if ( list.count() != theOther.list.count() ) + return false; + + RegExpListIt it1( list ); + RegExpListIt it2( theOther.list ); + + for ( ; *it1 && *it2 ; ) { + if ( ! (**it1 == **it2) ) + return false; + ++it1; + ++it2; + } + return true; +} + +void AltnRegExp::replacePart( CompoundRegExp* replacement ) +{ + for ( RegExpListIt it( list ); *it; ++it ) { + (*it)->replacePart( replacement ); + } +} + diff --git a/kregexpeditor/altnregexp.h b/kregexpeditor/altnregexp.h new file mode 100644 index 0000000..d5d9d1e --- /dev/null +++ b/kregexpeditor/altnregexp.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef ALTNREGEXP_H +#define ALTNREGEXP_H + +#include "regexp.h" + +/** + Abstract syntax node for `alternative' regular expression + @internal +*/ +class AltnRegExp :public RegExp +{ +public: + AltnRegExp( bool selected ); + + void addRegExp( RegExp * ); + RegExpList children() const; + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 1;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + virtual RegExpType type() const { return ALTN;} + virtual bool operator==( const RegExp& other ) const; + virtual void replacePart( CompoundRegExp* replacement ); + +private: + RegExpList list; +}; + +#endif // ALTNREGEXP_H diff --git a/kregexpeditor/altnwidget.cpp b/kregexpeditor/altnwidget.cpp new file mode 100644 index 0000000..22937ac --- /dev/null +++ b/kregexpeditor/altnwidget.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include +#endif + +#include "altnwidget.h" +#include "dragaccepter.h" +#include "concwidget.h" +#include "altnregexp.h" +#include + +AltnWidget::AltnWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + :MultiContainerWidget(editorWindow, parent, name == 0 ? "AltnWidget" : name) +{ + DragAccepter *accepter = new DragAccepter(editorWindow, this); + accepter->resize(0,0); // See note (1) in Comments + _children.append(accepter); + _text = i18n("Alternatives"); +} + +AltnWidget::AltnWidget( AltnRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name) + :MultiContainerWidget( editorWindow, parent, name ) +{ + DragAccepter *accepter = new DragAccepter(editorWindow, this); + accepter->resize(0,0); // See note (1) in Comments + _children.append(accepter); + _text = i18n("Alternatives"); + + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + RegExpWidget* child = WidgetFactory::createWidget( *it, editorWindow, this ); + ConcWidget* conc; + if ( ! (conc = dynamic_cast( child ) ) ) { + conc = new ConcWidget( editorWindow, child, parent ); + } + append( conc ); + } + updateDrawLineInfo(); +} + + +void AltnWidget::addNewChild(DragAccepter *accepter, RegExpWidget *child) +{ + ConcWidget *conc = new ConcWidget(_editorWindow, child,this); + MultiContainerWidget::addNewChild( accepter, conc ); + updateDrawLineInfo(); + repaint(); +} + +void AltnWidget::setConcChild(ConcWidget *child) +{ + addNewConcChild( dynamic_cast(_children.at(0)), child ); +} + +void AltnWidget::addNewConcChild(DragAccepter *accepter, ConcWidget *child) +{ + child->reparent(this, QPoint(0,0), false); + MultiContainerWidget::addNewChild( accepter, child ); + updateDrawLineInfo(); +} + + +QSize AltnWidget::sizeHint() const +{ + QPtrListIterator it(_children); + // Skip the first child, as we only need half of the size of the first and the + // last drag accepter. Does, however, not apply when there only is onw child. + if ( _children.count() != 1 ) + ++it; + + _childrenWidth = 0; + _childrenHeight = 0; + + for ( ; *it ; ++it) { + QSize thisChildSize = (*it)->sizeHint(); + _childrenWidth = QMAX(_childrenWidth, thisChildSize.width()); + _childrenHeight += thisChildSize.height(); + } + + // Now add the size of the header + QFontMetrics metrics = fontMetrics(); + _textSize = metrics.size(0,_text); + + int headerWidth = _textSize.width() + 2 * bdSize + 2; + + _childrenWidth = QMAX(_childrenWidth, headerWidth); + + return QSize(_childrenWidth + 2*pw, _childrenHeight + _textSize.height() + 1*pw ); +} + +void AltnWidget::paintEvent( QPaintEvent *e) +{ + Q_ASSERT( dynamic_cast(_children.at(0)) ); + // if this fails, then I should check the location of the show() + Q_ASSERT( _children.count() == 1 || + ( _children.count() >=3 && + dynamic_cast(_children.at(_children.count()-1)) ) ); + + int offset = 0; + QSize mySize = sizeHint(); + + QPainter painter(this); + drawPossibleSelection( painter, mySize ); + + //-------------------------------------- First draw the border and text + int startY = _textSize.height()/2; + + painter.drawLine(0, startY, bdSize, startY); + int xOffset = bdSize +1; + + painter.drawText(xOffset,0,_textSize.width(), _textSize.height(),0,_text); + xOffset += _textSize.width() +1; + painter.drawLine(xOffset,startY,mySize.width(), startY); + painter.drawLine(0,startY,0,mySize.height()); + painter.drawLine(mySize.width()-pw, startY, mySize.width()-pw, mySize.height()); + painter.drawLine(0,mySize.height()-pw, mySize.width()-pw, mySize.height()-pw); + + //---- Run through all the children and place them at the correct location. + offset = _textSize.height(); + xOffset = pw; + + for (unsigned int i = 0; i < _children.count(); i++ ) { + + RegExpWidget* child = _children.at(i); + + QSize childSize = child->sizeHint(); + QSize curChildSize = child->size(); + + //-------------------------------------- place the child + int x = xOffset; + int y = offset; + int h = childSize.height(); + if ( ( _children.count() != 1 ) && ( i == 0 || i == _children.count() -1 ) ) { + // first and last DragAccepter should only be half size. + h /= 2; + } + + int w = _childrenWidth; + child->setGeometry( x, y, w, h ); + if ( w != curChildSize.width() || h != curChildSize.height() ) { + // I resized the child, so give it a chance to relect thus. + child->update(); + } + + offset += h; + } + MultiContainerWidget::paintEvent( e ); +} + +RegExp* AltnWidget::regExp() const +{ + AltnRegExp *regexp = new AltnRegExp( isSelected() ); + + QPtrListIterator it(_children); + ++it; // start with the second element + for ( ; *it; it+=2 ) { + regexp->addRegExp( (*it)->regExp() ); + } + + return regexp; +} + +void AltnWidget::applyRegExpToSelection( RegExpType type ) +{ + for ( unsigned int i=1; i < _children.count(); i += 2 ) { + RegExpWidget* child = _children.at( i ); + if ( child->hasSelection() ) { + child->applyRegExpToSelection( type ); + } + } +} + + +RegExp* AltnWidget::selection() const +{ + if ( isSelected() ) + return regExp(); + else { + QPtrListIterator it(_children); + ++it; // Skip past DragAccepter + for ( ; *it; it+=2 ) { + if ( (*it)->hasSelection() ) { + return (*it)->selection(); + } + } + } + qFatal("Selection not found"); + return 0; // compiler shut up. +} + +bool AltnWidget::validateSelection() const +{ + if ( _isSelected ) { + return true; + } + + bool foundASelection = false; + QPtrListIterator it(_children); + ++it; // Skip past DragAccepter + for ( ; *it; it+=2 ) { + if ( (*it)->hasSelection() ) { + if ( foundASelection ) { + KMessageBox::information( const_cast(this), + i18n( "Selecting several alternatives is " + "currently not supported." ), + i18n( "Selection Invalid" ) ); + _editorWindow->clearSelection( true ); + return false; + } + else { + foundASelection = true; + } + } + } + return true; +} + +void AltnWidget::updateDrawLineInfo() +{ + for ( unsigned int i=0; i < _children.count(); i+=2 ) { + bool line = ( i != 0 && i!= _children.count()-1 ); + DragAccepter *accepter = dynamic_cast(_children.at(i)); + if (accepter) + accepter->setDrawLine( line ); + } +} + +void AltnWidget::deleteSelection() +{ + MultiContainerWidget::deleteSelection(); + updateDrawLineInfo(); +} + diff --git a/kregexpeditor/altnwidget.h b/kregexpeditor/altnwidget.h new file mode 100644 index 0000000..9a4f26b --- /dev/null +++ b/kregexpeditor/altnwidget.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef altnwidget +#define altnwidget + +#include "multicontainerwidget.h" +class AltnRegExp; + +/** + RegExp widget for alternatives. + + @internal +*/ +class AltnWidget :public MultiContainerWidget +{ +public: + AltnWidget( RegExpEditorWindow* editorWindow, QWidget *parent, + const char *label = 0); + AltnWidget( AltnRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0); + virtual void addNewChild(DragAccepter *accepter, RegExpWidget *child); + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual void applyRegExpToSelection( RegExpType type ); + virtual RegExpType type() const { return ALTN; } + virtual RegExp* selection() const; + virtual bool validateSelection() const; + virtual void setConcChild(ConcWidget *child); + virtual void addNewConcChild(DragAccepter *accepter, ConcWidget *child); + virtual void deleteSelection(); + +protected: + virtual void paintEvent( QPaintEvent* e ); + +private: + /** + This functions runs through all the dragaccepters and calls @ref + DragAccepter::setDrawLine. + */ + void updateDrawLineInfo(); + + QString _text; + mutable QSize _textSize; + + mutable int _maxSelectedWidth; + mutable int _childrenWidth; + mutable int _childrenHeight; +}; + +#endif // altnwidget diff --git a/kregexpeditor/auxbuttons.cpp b/kregexpeditor/auxbuttons.cpp new file mode 100644 index 0000000..ea28953 --- /dev/null +++ b/kregexpeditor/auxbuttons.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" + #include "images.h" +#else + #include "auxbuttons.moc" + #include + #include +#endif + +#include "auxbuttons.h" +#include +#include +#include +#include +#include "util.h" + +AuxButtons::AuxButtons( QWidget* parent, const char* name = 0) + :QDockWindow( QDockWindow::InDock, parent, name) +{ + QBoxLayout* layout = boxLayout(); + + _undo = new QToolButton( this ); + _undo->setIconSet( Util::getSystemIconSet(QString::fromLatin1("undo") ) ); + layout->addWidget( _undo ); + connect( _undo, SIGNAL(clicked()), this, SIGNAL(undo()) ); + QToolTip::add( _undo, i18n( "Undo" ) ); + + _redo = new QToolButton( this ); + _redo->setIconSet( Util::getSystemIconSet(QString::fromLatin1("redo") ) ); + layout->addWidget( _redo ); + connect( _redo, SIGNAL(clicked()), this, SIGNAL(redo()) ); + QToolTip::add( _redo, i18n( "Redo" ) ); + + _cut = new QToolButton( this ); + _cut->setIconSet( Util::getSystemIconSet(QString::fromLatin1("editcut") ) ); + layout->addWidget( _cut ); + connect( _cut, SIGNAL(clicked()), this, SIGNAL(cut()) ); + QToolTip::add( _cut, i18n( "Cut" ) ); + + _copy = new QToolButton( this ); + _copy->setIconSet( Util::getSystemIconSet(QString::fromLatin1("editcopy") ) ); + layout->addWidget( _copy ); + connect( _copy, SIGNAL(clicked()), this, SIGNAL(copy()) ); + QToolTip::add( _copy, i18n( "Copy" ) ); + + _paste = new QToolButton( this ); + _paste->setIconSet( Util::getSystemIconSet(QString::fromLatin1("editpaste")) ); + layout->addWidget( _paste ); + connect( _paste, SIGNAL(clicked()), this, SIGNAL(paste()) ); + QToolTip::add( _paste, i18n( "Paste" ) ); + + _save = new QToolButton( this ); + _save->setIconSet( Util::getSystemIconSet(QString::fromLatin1("filesave")) ); + layout->addWidget( _save ); + connect( _save, SIGNAL(clicked()), this, SIGNAL(save()) ); + QToolTip::add( _save, i18n( "Save" ) ); + + + QToolButton* button = new QToolButton(this); + button->setPixmap( Util::getSystemIcon( QString::fromLatin1("contexthelp") ) ); + layout->addWidget( button ); + connect(button, SIGNAL(clicked()), this, SLOT(slotEnterWhatsThis())); + + _undo->setEnabled( false ); + _redo->setEnabled( false ); + +} + +void AuxButtons::slotEnterWhatsThis() +{ + QWhatsThis::enterWhatsThisMode (); +} + +void AuxButtons::slotCanUndo( bool b ) +{ + _undo->setEnabled( b ); +} + +void AuxButtons::slotCanRedo( bool b ) +{ + _redo->setEnabled( b ); +} + +void AuxButtons::slotCanCut( bool b ) +{ + _cut->setEnabled( b ); +} + +void AuxButtons::slotCanCopy( bool b ) +{ + _copy->setEnabled( b ); +} + +void AuxButtons::slotCanPaste( bool b ) +{ + _paste->setEnabled( b ); +} + +void AuxButtons::slotCanSave( bool b ) +{ + _save->setEnabled( b ); +} + diff --git a/kregexpeditor/auxbuttons.h b/kregexpeditor/auxbuttons.h new file mode 100644 index 0000000..08c33ec --- /dev/null +++ b/kregexpeditor/auxbuttons.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef AUXBUTTONS_H +#define AUXBUTTONS_H + +#include +class QComboBox; +class QLabel; +class QToolButton; + +class AuxButtons :public QDockWindow +{ + Q_OBJECT + +public: + AuxButtons( QWidget* parent, const char* name ); + +signals: + void undo(); + void redo(); + void cut(); + void copy(); + void paste(); + void save(); + +public slots: + void slotEnterWhatsThis(); + void slotCanUndo( bool ); + void slotCanRedo( bool ); + void slotCanCut( bool ); + void slotCanCopy( bool ); + void slotCanPaste( bool ); + void slotCanSave( bool ); + +private: + QToolButton* _undo; + QToolButton* _redo; + QToolButton* _cut; + QToolButton* _copy; + QToolButton* _paste; + QToolButton* _save; +}; + + +#endif // AUXBUTTONS_H diff --git a/kregexpeditor/characterswidget.cpp b/kregexpeditor/characterswidget.cpp new file mode 100644 index 0000000..b219ed6 --- /dev/null +++ b/kregexpeditor/characterswidget.cpp @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include "characterswidget.moc" +#endif + +#include "characterswidget.h" +#include "textrangeregexp.h" +#include "regexp.h" +#include "charselector.h" +#include "myfontmetrics.h" +#include "regexpconverter.h" + +#include +#include +#include +#include +#include +#include + +CharacterEdits* CharactersWidget::_configWindow = 0; + +CharactersWidget::CharactersWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : RegExpWidget(editorWindow, parent, name) +{ + _regexp = new TextRangeRegExp( false /* not used */); +} + +CharactersWidget::CharactersWidget( TextRangeRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name ) + : RegExpWidget( editorWindow, parent, name ) +{ + _regexp = dynamic_cast( regexp->clone() ); + Q_ASSERT( _regexp ); +} + +CharactersWidget::~CharactersWidget() +{ + delete _regexp; +} + + +QSize CharactersWidget::sizeHint() const +{ + QFontMetrics metrics = fontMetrics(); + _textSize = HackCalculateFontSize(metrics, title()); + // _textSize = metrics.size(0, title()); + + QSize headerSize = QSize(_textSize.width() + 4 * bdSize, + _textSize.height()); + + _contentSize = HackCalculateFontSize(metrics,text()); + // _contentSize = metrics.size(0, text()); + + return QSize(QMAX(headerSize.width(), bdSize + _contentSize.width() + bdSize+ 2*pw), + headerSize.height() + bdSize + _contentSize.height() + bdSize + 2*pw); +} + +void CharactersWidget::paintEvent(QPaintEvent *e) +{ + QSize mySize = sizeHint(); + + QPainter painter(this); + drawPossibleSelection( painter, mySize ); + + int center = _textSize.height()/2; + int offset = 0; + + // draw the horizontal line and the label + painter.drawLine(pw,center, bdSize,center); + offset += pw + 2*bdSize; + + painter.drawText(offset, 0, _textSize.width(), _textSize.height(), 0, title()); + offset += _textSize.width() + bdSize; + + painter.drawLine(offset, center, mySize.width(), center); + + // Draw the rest of the lines + int y = mySize.width() - pw; + int x = mySize.height() -pw; + painter.drawLine(0,center,0,mySize.height()); + painter.drawLine(y,center,y,mySize.height()); + painter.drawLine(0,x,y,x); + + // Draw the text + painter.drawText(bdSize, bdSize+_textSize.height(), _contentSize.width(), + _contentSize.height(), 0, text()); + + RegExpWidget::paintEvent(e); +} + +RegExp* CharactersWidget::regExp() const +{ + RegExp* r = _regexp->clone(); + r->setSelected( isSelected() ); + return r; +} + +QString CharactersWidget::text() const +{ + QString res = QString::fromLatin1(""); + + if (_regexp->wordChar()) + res += i18n("- A word character\n"); + + if (_regexp->nonWordChar()) + res += i18n("- A non-word character\n"); + + if (_regexp->digit()) + res += i18n("- A digit character\n"); + + if (_regexp->nonDigit()) + res += i18n("- A non-digit character\n"); + + if ( _regexp->space() ) + res += i18n("- A space character\n"); + + if ( _regexp->nonSpace() ) + res += i18n("- A non-space character\n"); + + // Single characters + QStringList chars = _regexp->chars(); + if ( !chars.isEmpty() ) { + QString str = chars.join( QString::fromLocal8Bit(", ") ); + res += QString::fromLocal8Bit("- ") + str + QString::fromLocal8Bit("\n"); + } + + // Ranges characters + QPtrList range = _regexp->range(); + for ( QPtrListIterator it( range ); *it; ++it ) { + StringPair* elm = static_cast(*it); + if (elm) { + QString fromText = elm->first(); + QString toText = elm->second(); + + res += QString::fromLocal8Bit("- ") + i18n("from ") + fromText + i18n(" to ") + toText + QString::fromLocal8Bit("\n"); + } + } + return res.left(res.length()-1); +} + + +QString CharactersWidget::title() const +{ + if (_regexp->negate()) + return i18n("Any Character Except"); + else + return i18n("One of Following Characters"); +} + + +RegExpWidget* CharactersWidget::findWidgetToEdit( QPoint globalPos ) +{ + if ( QRect(mapToGlobal(QPoint(0,0)), size()).contains( globalPos ) ) + return this; + else + return 0; +} + +int CharactersWidget::edit() +{ + if ( _configWindow == 0 ) { + QApplication::setOverrideCursor( WaitCursor ); + // No parent here, as this window should continue to exists. + _configWindow = new CharacterEdits( 0, "CharactersWidget::_configWindow" ); + QApplication::restoreOverrideCursor(); + } + + _configWindow->move(QCursor::pos() - QPoint(_configWindow->sizeHint().width()/2, + _configWindow->sizeHint().height()/2)); + int ret = _configWindow->exec(_regexp ); + if ( ret == QDialog::Accepted ) { + _editorWindow->updateContent( 0 ); + update(); + } + return ret; +} + +void CharacterEdits::addCharacter( QString txt ) +{ + KMultiFormListBoxEntryList list = _single->elements(); + for ( QPtrListIterator it(list); *it; ++it ) { + SingleEntry* entry = dynamic_cast( *it ); + if ( entry && entry->isEmpty() ) { + entry->setText( txt ); + return; + } + } + + SingleEntry* entry = new SingleEntry( _single ); + entry->setText( txt ); + _single->append( entry ); +} + +void CharacterEdits::addRange( QString from, QString to ) +{ + KMultiFormListBoxEntryList list = _range->elements(); + for ( QPtrListIterator it(list); *it; ++it ) { + RangeEntry* entry = dynamic_cast( *it ); + if ( entry && entry->isEmpty() ) { + entry->setFrom( from ); + entry->setTo( to ); + return; + } + } + + RangeEntry* entry = new RangeEntry( _range ); + entry->setFrom( from ); + entry->setTo( to ); + _range->append( entry ); +} + +int CharacterEdits::exec( TextRangeRegExp* regexp ) +{ + _regexp = regexp; + negate->setChecked( regexp->negate() ); + digit->setChecked( regexp->digit() ); + _nonDigit->setChecked( regexp->nonDigit() ); + space->setChecked( regexp->space() ); + _nonSpace->setChecked( regexp->nonSpace() ); + wordChar->setChecked( regexp->wordChar() ); + _nonWordChar->setChecked( regexp->nonWordChar() ); + + bool enabled = (RegExpConverter::current()->features() & RegExpConverter::CharacterRangeNonItems); + _nonWordChar->setEnabled( enabled ); + _nonDigit->setEnabled( enabled ); + _nonSpace->setEnabled( enabled ); + + // Characters + + KMultiFormListBoxEntryList list1 = _single->elements(); + for ( QPtrListIterator it(list1); *it; ++it ) { + SingleEntry* entry = dynamic_cast( *it ); + if (entry) + entry->setText( QString::fromLocal8Bit("") ); + } + QStringList list2 = regexp->chars(); + for ( QStringList::Iterator it2( list2.begin() ); ! (*it2).isNull(); ++it2 ) { + addCharacter( *it2 ); + } + + // Ranges + KMultiFormListBoxEntryList list3 = _range->elements(); + for ( QPtrListIterator it3(list3); *it3; ++it3 ) { + RangeEntry* entry = dynamic_cast( *it3 ); + if (entry) { + entry->setFrom( QString::fromLocal8Bit("") ); + entry->setTo( QString::fromLocal8Bit("") ); + } + } + + QPtrList ranges = regexp->range(); + for ( QPtrListIterator it4(ranges); *it4; ++it4 ) { + QString from = (*it4)->first(); + QString to = (*it4)->second(); + addRange(from,to); + } + + int res = KDialogBase::exec(); + _regexp = 0; + return res; +} + + +CharacterEdits::CharacterEdits( QWidget *parent, const char *name) + : KDialogBase( parent, name == 0 ? "CharacterEdits" : name, true, + i18n("Specify Characters"), + KDialogBase::Ok | KDialogBase::Cancel) +{ + QWidget* top = new QWidget( this ); + QVBoxLayout *topLayout = new QVBoxLayout(top, 6); + setMainWidget( top ); + + negate = new QCheckBox(i18n("Do not match the characters specified here"), + top); + topLayout->addWidget( negate ); + + + // The predefined box + QHGroupBox* predefined = new QHGroupBox(i18n("Predefined Character Ranges"),top); + topLayout->addWidget(predefined); + QGrid* grid = new QGrid(3, predefined ); + + wordChar = new QCheckBox(i18n("A word character"),grid); + digit = new QCheckBox(i18n("A digit character"),grid); + space = new QCheckBox(i18n("A space character"), grid); + + _nonWordChar = new QCheckBox(i18n("A non-word character"),grid); + _nonDigit = new QCheckBox(i18n("A non-digit character"),grid); + _nonSpace = new QCheckBox(i18n("A non-space character"), grid); + + // Single characters + QVGroupBox* singleBox = new QVGroupBox(i18n("Single Characters"), top ); + topLayout->addWidget( singleBox ); + _single = new KMultiFormListBox(new SingleFactory(), KMultiFormListBox::MultiVisible, + singleBox); + _single->addElement(); _single->addElement(); _single->addElement(); + + QWidget* moreW = new QWidget( singleBox ); + QHBoxLayout* moreLay = new QHBoxLayout( moreW ); + QPushButton* more = new QPushButton( i18n("More Entries"), moreW ); + moreLay->addWidget( more ); + moreLay->addStretch( 1 ); + + connect(more,SIGNAL(clicked()), _single, SLOT(addElement())); + + // Ranges + QVGroupBox* rangeBox = new QVGroupBox(i18n("Character Ranges"), top ); + topLayout->addWidget( rangeBox ); + + _range = new KMultiFormListBox(new RangeFactory(), KMultiFormListBox::MultiVisible, + rangeBox); + _range->addElement(); _range->addElement(); _range->addElement(); + + moreW = new QWidget( rangeBox ); + moreLay = new QHBoxLayout( moreW ); + more = new QPushButton( i18n("More Entries"), moreW ); + moreLay->addWidget( more ); + moreLay->addStretch( 1 ); + connect(more,SIGNAL(clicked()), _range, SLOT(addElement())); + // Buttons + connect(this, SIGNAL(okClicked()), this, SLOT(slotOK())); +} + +void CharacterEdits::slotOK() +{ + _regexp->setNegate( negate->isChecked() ); + + _regexp->setWordChar( wordChar->isChecked() ); + _regexp->setNonWordChar( _nonWordChar->isChecked() ); + + _regexp->setDigit( digit->isChecked() ); + _regexp->setNonDigit( _nonDigit->isChecked() ); + + _regexp->setSpace( space->isChecked() ); + _regexp->setNonSpace( _nonSpace->isChecked() ); + + // single characters + _regexp->clearChars(); + KMultiFormListBoxEntryList list = _single->elements(); + for ( QPtrListIterator it( list ); *it; ++it ) { + SingleEntry* entry = dynamic_cast(*it); + if ( entry && !entry->isEmpty() ) { + _regexp->addCharacter( entry->text() ); + } + } + + // Ranges + _regexp->clearRange(); + list = _range->elements(); + for ( QPtrListIterator it2( list ); *it2; ++it2 ) { + RangeEntry* entry = dynamic_cast(*it2); + if ( entry && !entry->isEmpty() ) { + _regexp->addRange( entry->fromText(), entry->toText() ); + } + } +} + + +SingleEntry::SingleEntry(QWidget* parent, const char* name ) + :KMultiFormListBoxEntry( parent, name ) +{ + QHBoxLayout* layout = new QHBoxLayout( this, 3, 6 ); + _selector = new CharSelector( this ); + layout->addWidget( _selector ); + layout->addStretch(1); +} + +QString SingleEntry::text() const +{ + return _selector->text(); +} + +void SingleEntry::setText( QString text ) +{ + _selector->setText( text ); +} + +bool SingleEntry::isEmpty() const +{ + return _selector->isEmpty(); +} + + +RangeEntry::RangeEntry(QWidget* parent, const char* name ) + :KMultiFormListBoxEntry( parent, name ) +{ + QHBoxLayout* layout = new QHBoxLayout( this, 3, 6 ); + + QLabel* label = new QLabel(i18n("From:"), this ); + _from = new CharSelector( this ); + layout->addWidget( label ); + layout->addWidget( _from ); + + layout->addStretch(1); + + label = new QLabel(i18n("end of range","To:"), this ); + _to = new CharSelector( this ); + layout->addWidget( label ); + layout->addWidget( _to ); +} + +QString RangeEntry::fromText() const +{ + return _from->text(); +} + +QString RangeEntry::toText() const +{ + return _to->text(); +} + +void RangeEntry::setFrom( QString text ) +{ + _from->setText( text ); +} + +void RangeEntry::setTo( QString text ) +{ + _to->setText( text ); +} + +bool RangeEntry::isEmpty() const +{ + return _from->isEmpty() || _to->isEmpty(); +} + diff --git a/kregexpeditor/characterswidget.h b/kregexpeditor/characterswidget.h new file mode 100644 index 0000000..9df89b3 --- /dev/null +++ b/kregexpeditor/characterswidget.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef characterswidget +#define characterswidget + +#ifdef QT_ONLY +#include "compat.h" +#else +#include +#endif + +#include +#include "regexpwidget.h" +#include + +class KDialogBase; +class CharacterEdits; +class TextRangeRegExp; +class CharSelector; +class QCheckBox; + +/** + RegExp widget for charcter ranges. + @internal +*/ +class CharactersWidget :public RegExpWidget +{ +public: + CharactersWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *label = 0); + CharactersWidget( TextRangeRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0 ); + ~CharactersWidget(); + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual RegExpType type() const { return CHARSET; } + virtual RegExpWidget* findWidgetToEdit( QPoint globalPos ); + virtual int edit(); + +protected: + virtual void paintEvent(QPaintEvent *event); + QString text() const; + QString title() const; + +private: + TextRangeRegExp *_regexp; + static CharacterEdits *_configWindow; + + mutable QSize _textSize; + mutable QSize _contentSize; +}; + + +/** + @internal +*/ +class SingleEntry :public KMultiFormListBoxEntry +{ +public: + SingleEntry(QWidget* parent, const char* name = 0 ); + QString text() const; + void setText( QString text ); + bool isEmpty() const; + +private: + CharSelector* _selector; +}; + +/** + @internal +*/ +class RangeEntry :public KMultiFormListBoxEntry +{ +public: + RangeEntry(QWidget* parent, const char* name = 0 ); + QString fromText() const; + QString toText() const; + void setFrom( QString text ); + void setTo( QString text ); + bool isEmpty() const; +private: + CharSelector *_from, *_to; +}; + +/** + @internal +*/ +class SingleFactory :public KMultiFormListBoxFactory +{ +public: + KMultiFormListBoxEntry *create(QWidget *parent) { return new SingleEntry( parent ); } + QWidget *separator( QWidget* ) { return 0; } +}; + +/** + @internal +*/ +class RangeFactory :public KMultiFormListBoxFactory +{ +public: + KMultiFormListBoxEntry *create(QWidget *parent) { return new RangeEntry( parent ); } + QWidget *separator( QWidget* ) { return 0; } +}; + +/** + @internal +*/ +class CharacterEdits : public KDialogBase +{ + Q_OBJECT +public: + CharacterEdits(QWidget *parent = 0, const char *name = 0); + +public slots: + int exec( TextRangeRegExp* regexp ); + +protected slots: + void slotOK(); + +private: + QCheckBox *negate, *wordChar, *_nonWordChar, *digit, *_nonDigit, *space, *_nonSpace; + KMultiFormListBox *_single, *_range; + + void addCharacter( QString txt ); + void addRange( QString from, QString to ); + TextRangeRegExp* _regexp; +}; + +#endif // characterswidget diff --git a/kregexpeditor/charselector.cpp b/kregexpeditor/charselector.cpp new file mode 100644 index 0000000..27fd23d --- /dev/null +++ b/kregexpeditor/charselector.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY +#include "compat.h" +#else +#include +#include "charselector.moc" +#endif + +#include "charselector.h" +#include "limitedcharlineedit.h" +#include "regexpconverter.h" +#include +#include +#include + +/** + In the class CharSelector, three LimitedCharLineEdit are used. + These widgets are all used in a QWidgetStack. The LimitedCharLineEdit + class is basically a QLineEdit, which is limited to a certain + number of characters. This conflicts with the QWidgetStack, as this + class expects the widgets on the stack to take up all space. + StackContainer fills in this gab. +*/ +class StackContainer :public QWidget +{ +public: + StackContainer( QWidget* child, QWidget* parent ) : QWidget( parent ) + { + QHBoxLayout* layout = new QHBoxLayout( this ); + child->reparent( this, QPoint(0,0), false ); + layout->addWidget( child ); + layout->addStretch( 1 ); + } +}; + +CharSelector::CharSelector( QWidget* parent, const char* name ) + :QWidget( parent, name ), _oldIndex(0) +{ + QStringList items; + QHBoxLayout* layout = new QHBoxLayout( this, 0, 6 ); + + _type = new QComboBox( this, "_type" ); + items << i18n("Normal Character") + << i18n("Unicode Char in Hex.") + << i18n("Unicode Char in Oct.") + << QString::fromLatin1("----") + << i18n("The Bell Character (\\a)") + << i18n("The Form Feed Character (\\f)") + << i18n("The Line Feed Character (\\n)") + << i18n("The Carriage Return Character (\\r)") + << i18n("The Horizontal Tab Character (\\t)") + << i18n("The Vertical Tab Character (\\v)"); + _type->insertStringList( items ); + layout->addWidget( _type ); + + _stack = new QWidgetStack( this, "_stack" ); + layout->addWidget( _stack ); + + _normal = new LimitedCharLineEdit( LimitedCharLineEdit::NORMAL, 0, "_normal" ); + _stack->addWidget( new StackContainer( _normal, _stack ), 0 ); + + _hex = new LimitedCharLineEdit( LimitedCharLineEdit::HEX, _stack, "_hex" ); + _stack->addWidget( new StackContainer( _hex, _stack ), 1 ); + + _oct = new LimitedCharLineEdit( LimitedCharLineEdit::OCT, _stack, "_oct" ); + _stack->addWidget( new StackContainer( _oct, _stack ), 2 ); + + _stack->raiseWidget( 0 ); + + connect( _type, SIGNAL( activated( int ) ), this, SLOT(slotNewItem( int ) ) ); +} + +void CharSelector::slotNewItem( int which ) +{ + _type->setCurrentItem( which ); + if ( which <= 2 ) { + _stack->raiseWidget( which ); + _normal->setEnabled( true ); + _hex->setEnabled( true ); + _oct->setEnabled( true ); + } + else if ( which == 3 ) { + _type->setCurrentItem( _oldIndex ); + slotNewItem(_oldIndex); + return; + } + else { + _normal->setEnabled( false ); + _hex->setEnabled( false ); + _oct->setEnabled( false ); + } + + _oldIndex = which; +} + +void CharSelector::setText( QString text ) +{ + // This is the best I can do about missing character range features, unless all of + // textrangeregexp is to be reworked. The problem is that textrangeregexp only allows to + // get the characters, which would be something like \a, but \a does not work with say Emacs + // style regexps -- ko28 Sep. 2003 10:55 -- Jesper K. Pedersen + bool enabled = ( RegExpConverter::current()->features() & RegExpConverter::ExtRange ); + _type->setEnabled( enabled ); + + if ( text.at(0) == QChar('\\') ) { + if ( text.at(1) == QChar('x') ) { + _hex->setText(text.mid(2)); + slotNewItem( 1 ); + } + else if ( text.at(1) == QChar('0') ) { + _oct->setText(text.mid(2)); + slotNewItem( 2 ); + } + else if ( text.at(1) == QChar('a') ) + slotNewItem(4); + else if ( text.at(1) == QChar('f') ) + slotNewItem(5); + else if ( text.at(1) == QChar('n') ) + slotNewItem(6); + else if ( text.at(1) == QChar('r') ) + slotNewItem(7); + else if ( text.at(1) == QChar('t') ) + slotNewItem(8); + else if ( text.at(1) == QChar('v') ) + slotNewItem(9); + else { + qWarning("Warning %s:%d Unknown escape %s", __FILE__, __LINE__, text.latin1() ); + } + } + else { + slotNewItem(0); + _normal->setText(text); + } +} + +bool CharSelector::isEmpty() const +{ + return ( _type->currentItem() == 0 && _normal->text().isEmpty() ) || + ( _type->currentItem() == 1 && _hex->text().isEmpty() ) || + ( _type->currentItem() == 2 && _oct->text().isEmpty() ); +} + +QString CharSelector::text() const +{ + switch ( _type->currentItem() ) { + case 0: // Normal Character + return _normal->text(); + case 1: // Hex + return QString::fromLocal8Bit("\\x") + _hex->text(); + case 2: // Oct + return QString::fromLocal8Bit("\\0") + _oct->text(); + case 3: // The seperator + break; + case 4: + return QString::fromLatin1("\\a"); + case 5: + return QString::fromLatin1("\\f"); + case 6: + return QString::fromLatin1("\\n"); + case 7: + return QString::fromLatin1("\\r"); + case 8: + return QString::fromLatin1("\\t"); + case 9: + return QString::fromLatin1("\\v"); + } + return QString::null; +} diff --git a/kregexpeditor/charselector.h b/kregexpeditor/charselector.h new file mode 100644 index 0000000..07aa056 --- /dev/null +++ b/kregexpeditor/charselector.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef CHARSELECTOR_H +#define CHARSELECTOR_H + +#include + +class QComboBox; +class QWidgetStack; +class LimitedCharLineEdit; + +class CharSelector :public QWidget +{ + Q_OBJECT + +public: + CharSelector( QWidget* parent, const char* name = 0 ); + QString text() const; + void setText( QString text ); + bool isEmpty() const; + +protected: + void fillComboBox(); + +private slots: + void slotNewItem( int which ); + +private: + QComboBox* _type; + QWidgetStack* _stack; + LimitedCharLineEdit* _normal; + LimitedCharLineEdit* _hex; + LimitedCharLineEdit* _oct; + int _oldIndex; +}; + +#endif // CHARSELECTOR_H diff --git a/kregexpeditor/compoundregexp.cpp b/kregexpeditor/compoundregexp.cpp new file mode 100644 index 0000000..2949b48 --- /dev/null +++ b/kregexpeditor/compoundregexp.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include +#endif + +#include "compoundregexp.h" +#include "widgetfactory.h" + +CompoundRegExp::CompoundRegExp( bool selected, const QString& title, const QString& description, bool hidden, + bool allowReplace, RegExp* child) + : RegExp( selected ), _title( title ), _description( description ), _hidden( hidden ), _allowReplace( allowReplace ), _child( child ) +{ + if ( child ) + addChild( child ); +} + +bool CompoundRegExp::check( ErrorMap& map, bool first, bool last ) +{ + return _child->check( map, first, last ); +} + +QDomNode CompoundRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement( QString::fromLocal8Bit( "Compound" ) ); + if (_hidden) + top.setAttribute( QString::fromLocal8Bit("hidden"), true ); + if ( _allowReplace ) + top.setAttribute( QString::fromLocal8Bit("allowReplace"), true ); + + QDomElement title = doc->createElement( QString::fromLocal8Bit( "Title" ) ); + QDomText titleTxt = doc->createTextNode( _title ); + title.appendChild( titleTxt ); + top.appendChild( title ); + + QDomElement description = doc->createElement( QString::fromLocal8Bit( "Description" ) ); + QDomText descriptionTxt = doc->createTextNode( _description ); + description.appendChild( descriptionTxt ); + top.appendChild( description ); + + top.appendChild( _child->toXml( doc ) ); + + return top; +} + + +bool CompoundRegExp::load( QDomElement top, const QString& version ) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit("Compound") ); + QString str = top.attribute( QString::fromLocal8Bit( "hidden" ), QString::fromLocal8Bit("0") ); + _hidden = true; // alway hidden. (str == QString::fromLocal8Bit("1") ); + + str = top.attribute( QString::fromLocal8Bit( "allowReplace" ), QString::fromLocal8Bit("0") ); + _allowReplace = (str == QString::fromLocal8Bit("1") ); + + for ( QDomNode node = top.firstChild(); !node.isNull(); node = node.nextSibling() ) { + if ( !node.isElement() ) + continue; // skip past comments. + QString txt; + QDomElement child = node.toElement(); + QDomNode txtNode = child.firstChild(); + if ( txtNode.isText() ) + txt = txtNode.toText().data(); + if ( child.tagName() == QString::fromLocal8Bit( "Title" ) ) { + if ( txt.isEmpty() ) + _title = txt; + else + _title = i18n(txt.utf8()); + } + else if ( child.tagName() == QString::fromLocal8Bit( "Description" ) ) { + if ( txt.isEmpty() ) + _description = txt; + else + _description = i18n(txt.utf8()); + } + else { + _child = WidgetFactory::createRegExp( child, version ); + if ( _child ) { + addChild( _child ); + return true; + } + else { + return false; + } + } + } + return false; +} + +bool CompoundRegExp::operator==( const RegExp& other ) const +{ + // Note the order is important in the comparison below. + // Using other as the first argument, means that + // the following will be evaluated: other.operator== rather than (*child).operator== + // This means that if other is a CompoundRegExp too, then this level will be striped. + return ( other == *_child ); +} diff --git a/kregexpeditor/compoundregexp.h b/kregexpeditor/compoundregexp.h new file mode 100644 index 0000000..4e9aa8c --- /dev/null +++ b/kregexpeditor/compoundregexp.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef COMPOUNDREGEXP_H +#define COMPOUNDREGEXP_H +#include "regexp.h" + +/** + Abstract syntax node for `compound content' regular expression + @internal +*/ +class CompoundRegExp :public RegExp +{ +public: + CompoundRegExp( bool selected, const QString& title = QString::null, + const QString& description = QString::null, + bool hidden = false, bool allowReplace = false, RegExp* child = 0); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return _child->precedence();} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + QString title() const { return _title; } + QString description() const { return _description; } + RegExp* child() const { return _child; } + bool hidden() const { return _hidden; } + bool allowReplace() const { return _allowReplace; } + virtual RegExpType type() const { return COMPOUND;} + virtual bool operator==( const RegExp& other ) const; + +private: + QString _title; + QString _description; + bool _hidden; + bool _allowReplace; + RegExp* _child; +}; + + +#endif // COMPOUNDREGEXP_H diff --git a/kregexpeditor/compoundwidget.cpp b/kregexpeditor/compoundwidget.cpp new file mode 100644 index 0000000..3294313 --- /dev/null +++ b/kregexpeditor/compoundwidget.cpp @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" + #include "images.h" +#else + #include + #include + #include + #include "compoundwidget.moc" +#endif + +#include "compoundwidget.h" +#include +#include +#include +#include +#include +#include "concwidget.h" +#include "kwidgetstreamer.h" +#include "qcheckbox.h" + +//================================================================================ + +CompoundDetailWindow::CompoundDetailWindow( QWidget* parent, const char* name ) + :QWidget( parent, name ) +{ + QVBoxLayout* layout = new QVBoxLayout( this ); + layout->setAutoAdd( true ); + + QLabel* label = new QLabel( i18n("&Title:"), this); + _title = new QLineEdit( this ); + label->setBuddy( _title ); + + label = new QLabel( i18n("&Description:"), this ); + _description = new QMultiLineEdit( this ); + label->setBuddy( _description ); + + _allowReplace = new QCheckBox( i18n("&Automatically replace using this item"), this ); + QToolTip::add( _allowReplace, i18n("When the content of this box is typed in to the ASCII line,
" + "this box will automatically be added around it,
" + "if this check box is selected.") ); + _allowReplace->setChecked( true ); + + _title->setFocus(); + +} + +QString CompoundDetailWindow::title() const +{ + return _title->text(); +} + +QString CompoundDetailWindow::description() const +{ + return _description->text(); +} + +bool CompoundDetailWindow::allowReplace() const +{ + return _allowReplace->isChecked(); +} + +void CompoundDetailWindow::setTitle( QString txt ) +{ + _title->setText( txt ); +} + +void CompoundDetailWindow::setDescription( QString txt ) +{ + _description->setText( txt ); +} + +void CompoundDetailWindow::setAllowReplace( bool b ) +{ + _allowReplace->setChecked( b ); +} + +//================================================================================ + +CompoundWidget::CompoundWidget( RegExpEditorWindow* editorWindow, QWidget* parent, + const char* name ) + :SingleContainerWidget( editorWindow, parent, name == 0 ? "CompoundWidget" : name ) +{ + _child = new ConcWidget( editorWindow, this ); + init(); +} + +CompoundWidget::CompoundWidget( CompoundRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name ) + : SingleContainerWidget( editorWindow, parent, name == 0 ? "CompoundWidget" : name ) +{ + init(); + _content->setTitle( regexp->title() ); + _content->setDescription( regexp->description() ); + _content->setAllowReplace( regexp->allowReplace() ); + RegExpWidget* child = WidgetFactory::createWidget( regexp->child(), _editorWindow, this ); + if ( !( _child = dynamic_cast(child) ) ) { + _child = new ConcWidget( _editorWindow, child, this ); + } + + _hidden = regexp->hidden(); +} + +void CompoundWidget::init( ) +{ + _configWindow = new KDialogBase( this, "_configWindow", true, + i18n("Configure Compound"), + KDialogBase::Ok | KDialogBase::Cancel ); + _content = new CompoundDetailWindow( _configWindow ); + _configWindow->setMainWidget( _content ); + + connect( _configWindow, SIGNAL(cancelClicked()), this, SLOT(slotConfigCanceled())) ; + connect(_configWindow, SIGNAL(finished()), this, SLOT(slotConfigWindowClosed())); + + _down = getIcon( QString::fromLocal8Bit( "1downarrow" )); + _up = getIcon( QString::fromLocal8Bit( "1uparrow" ) ); + + _hidden = false; + _backRefId = -1; +} + +QSize CompoundWidget::sizeHint() const +{ + QFontMetrics metrics = fontMetrics(); + _childSize = _child->sizeHint(); + _textSize = metrics.size( 0, _content->title() ); + + int width, height; + + if ( _hidden ) { + _pixmapSize = _up.size(); + width = 2*pw + QMAX( 2*bdSize+_textSize.width(), 2*bdSize+_pixmapSize.width()); + height = _pixmapSize.height() + 2*bdSize + _textSize.height()+pw; + } + else { + _pixmapSize = _down.size(); + int headerLineWidth = 2*pw + 2*bdSize + _pixmapSize.width(); + if ( _textSize.width() != 0) + headerLineWidth += 3*bdSize + _textSize.width(); + + width = QMAX( 2*pw + _childSize.width(), headerLineWidth ); + height = QMAX( _textSize.height(), _pixmapSize.height() ) + + 2*bdSize + _childSize.height() + pw; + } + return QSize( width, height ); + +} + +void CompoundWidget::paintEvent( QPaintEvent *e ) +{ + QSize mySize = sizeHint(); + + QPainter painter(this); + drawPossibleSelection( painter, mySize); + + int horLineY, childY; + + // draw top line + if ( _hidden ) { + horLineY = _pixmapSize.height()/2; + childY = _pixmapSize.height() + bdSize; + _pixmapPos = QPoint( mySize.width()-pw-bdSize-_pixmapSize.width(), 0 ); + painter.drawLine( pw, horLineY, _pixmapPos.x(), horLineY ); + painter.drawLine( mySize.width() - bdSize - pw, horLineY, + mySize.width(), horLineY); + painter.drawPixmap( _pixmapPos, _up ); + } + else { + int maxH = QMAX( _textSize.height(), _pixmapSize.height() ); + int offset = 0; + horLineY = maxH/2; + childY = maxH+bdSize; + + painter.drawLine(pw, horLineY, bdSize, horLineY); + if ( _textSize.width() != 0 ) { + offset += pw + 2*bdSize; + + painter.drawText(offset, horLineY-_textSize.height()/2, + bdSize+_textSize.width(), horLineY+_textSize.height()/2, + 0, _content->title()); + offset += _textSize.width() + bdSize; + } + + _pixmapPos = QPoint( mySize.width()-pw-bdSize-_pixmapSize.width(), + horLineY - _pixmapSize.height()/2 ); + + painter.drawLine( offset, horLineY, _pixmapPos.x(), horLineY ); + painter.drawPixmap( _pixmapPos, _down ); + + painter.drawLine( mySize.width()-bdSize-pw, horLineY, mySize.width(), horLineY ); + } + + // draw rest frame + painter.drawLine(0, horLineY, 0, mySize.height() ); + painter.drawLine( mySize.width()-pw, horLineY, mySize.width()-pw, mySize.height() ); + painter.drawLine( 0, mySize.height()-pw, mySize.width(), mySize.height()-pw ); + + // place/size child + if ( _hidden ) { + _child->hide(); + painter.drawText( pw+bdSize, childY, + pw+bdSize+_textSize.width(), childY+_textSize.height(), 0, + _content->title() ); + } + else { + QSize curSize = _child->size(); + QSize newSize = QSize( QMAX( _child->sizeHint().width(), mySize.width()-2*pw), + _child->sizeHint().height()); + + _child->move( pw, childY ); + if ( curSize != newSize ) { + _child->resize(newSize); + // I resized the child, so give it a chance to relect thus. + _child->update(); + } + + _child->show(); + } + + RegExpWidget::paintEvent( e ); +} + +void CompoundWidget::slotConfigWindowClosed() +{ + _editorWindow->updateContent( 0 ); + update(); +} + +void CompoundWidget::slotConfigCanceled() +{ + QDataStream stream( _backup, IO_ReadOnly ); + KWidgetStreamer streamer; + streamer.fromStream( stream, _content ); + repaint(); +} + +RegExp* CompoundWidget::regExp() const +{ + return new CompoundRegExp( isSelected(), _content->title(), _content->description(), + _hidden, _content->allowReplace(), _child->regExp() ); +} + +void CompoundWidget::mousePressEvent( QMouseEvent* event ) +{ + if ( event->button() == LeftButton && + QRect( _pixmapPos, _pixmapSize ).contains( event->pos() ) ) { + // Skip otherwise we will never see the mouse release + // since it is eaten by Editor window. + } + else + SingleContainerWidget::mousePressEvent( event ); +} + +void CompoundWidget::mouseReleaseEvent( QMouseEvent* event) +{ + if ( event->button() == LeftButton && + QRect( _pixmapPos, _pixmapSize ).contains( event->pos() ) ) { + _hidden = !_hidden; + _editorWindow->updateContent( 0 ); + repaint(); // is this necesary? + _editorWindow->emitChange(); + } + else + SingleContainerWidget::mouseReleaseEvent( event ); +} + +bool CompoundWidget::updateSelection( bool parentSelected ) +{ + if ( _hidden ) { + bool changed = RegExpWidget::updateSelection( parentSelected ); + _child->selectWidget( _isSelected ); + if (changed) + repaint(); + return changed; + } + else { + return SingleContainerWidget::updateSelection( parentSelected ); + } +} + +int CompoundWidget::edit() +{ + _configWindow->move(QCursor::pos() - QPoint(_configWindow->sizeHint().width()/2, + _configWindow->sizeHint().height()/2) ); + QDataStream stream( _backup, IO_WriteOnly ); + KWidgetStreamer streamer; + streamer.toStream( _content, stream ); + return _configWindow->exec(); +} + +int nextId() +{ + static int counter = 0; + return ++counter; +} + +QPixmap CompoundWidget::getIcon( const QString& name ) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage(name) ); + return pix; +#else + return SmallIcon( name ); +#endif +} + + diff --git a/kregexpeditor/compoundwidget.h b/kregexpeditor/compoundwidget.h new file mode 100644 index 0000000..f757c05 --- /dev/null +++ b/kregexpeditor/compoundwidget.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef compoundwidget +#define compoundwidget +class QLineEdit; +class QMultiLineEdit; +class KDialogBase; +class QCheckBox; + +#include "singlecontainerwidget.h" +#include "compoundregexp.h" + +/** + Widget containing configuration details for @ref CompoundWidget + @internal +*/ +class CompoundDetailWindow :public QWidget +{ +public: + CompoundDetailWindow(QWidget* parent, const char* name = 0); + QString title() const; + QString description() const; + bool allowReplace() const; + void setTitle( QString ); + void setDescription( QString ); + void setAllowReplace( bool ); + +private: + QLineEdit* _title; + QMultiLineEdit* _description; + QCheckBox* _allowReplace; +}; + + +/** + Comopund RegExp widget. + + This widget has two purposes: + @li To make it possible for a user to collapse a huge regular expression + to take up less screen space. + @li To act as back references for later use. + + @internal +*/ +class CompoundWidget :public SingleContainerWidget +{ +Q_OBJECT + +public: + CompoundWidget( RegExpEditorWindow* editorWindow, QWidget* parent, + const char* name = 0); + CompoundWidget( CompoundRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0); + + virtual bool updateSelection( bool parentSelected ); + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual RegExpType type() const { return COMPOUND; } + virtual int edit(); + +protected: + virtual void paintEvent( QPaintEvent *e ); + virtual void mousePressEvent( QMouseEvent* e ); + virtual void mouseReleaseEvent( QMouseEvent* e); + void init(); + QPixmap getIcon( const QString& name ); + +protected slots: + void slotConfigCanceled(); + void slotConfigWindowClosed(); + +private: + bool _hidden; + QPixmap _up, _down; + mutable QSize _pixmapSize; + mutable QPoint _pixmapPos; + + KDialogBase* _configWindow; + CompoundDetailWindow* _content; + + mutable QSize _textSize; + mutable QSize _childSize; + QByteArray _backup; + + int _backRefId; +}; + + +#endif // compoundwidget diff --git a/kregexpeditor/concregexp.cpp b/kregexpeditor/concregexp.cpp new file mode 100644 index 0000000..4fac8d0 --- /dev/null +++ b/kregexpeditor/concregexp.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "concregexp.h" +#include "widgetfactory.h" +#include "compoundregexp.h" + +ConcRegExp::ConcRegExp( bool selected ) :RegExp( selected ) +{ +} + +void ConcRegExp::addRegExp( RegExp *regExp ) +{ + list.append(regExp); + addChild( regExp ); +} + +RegExpList ConcRegExp::children() +{ + return list; +} + + +bool ConcRegExp::check( ErrorMap& map, bool first, bool last) +{ + bool f = first; + bool possibleEmpty = true; + for ( RegExpListIt it(list); *it; ++it ) { + possibleEmpty = (*it)->check( map, f, last && it.atLast() ) && possibleEmpty; + if ( ! possibleEmpty ) + f = false; + } + return possibleEmpty; +} + +RegExp* ConcRegExp::lastRegExp() +{ + if ( list.count() == 0) + return 0; + else + return list.at( list.count()-1); +} + +QDomNode ConcRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement( QString::fromLocal8Bit("Concatenation") ); + for ( RegExpListIt it(list); *it; ++it ) { + top.appendChild( (*it)->toXml( doc ) ); + } + return top; +} + +bool ConcRegExp::load( QDomElement top, const QString& version ) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit( "Concatenation" ) ); + + for ( QDomNode child = top.firstChild(); !child.isNull(); child = child.nextSibling() ) { + if ( ! child.isElement() ) + continue; // User might have added a comment. + + RegExp* regexp = WidgetFactory::createRegExp( child.toElement(), version ); + if ( regexp == 0 ) + return false; + addRegExp( regexp ); + } + return true; +} + +bool ConcRegExp::operator==( const RegExp& other ) const +{ + // TODO: Merge with AltnRegExp::operator== + if ( list.count() == 1 ) + return ( other == *(const_cast< QPtrList& >(list).at(0)) ); + + if ( other.type() != type() ) + return false; + + const ConcRegExp& theOther = dynamic_cast( other ); + + if ( list.count() != theOther.list.count() ) + return false; + + RegExpListIt it1( list ); + RegExpListIt it2( theOther.list ); + + for ( ; *it1 && *it2 ; ) { + if ( ! (**it1 == **it2) ) + return false; + ++it1; + ++it2; + } + return true; +} + + +void ConcRegExp::replacePart( CompoundRegExp* replacement ) +{ + RegExp* otherChild = replacement->child(); + ConcRegExp* otherConc = dynamic_cast( otherChild ); + if ( ! otherConc ) { + // Watch out for garbage here! + otherConc = new ConcRegExp( false ); + otherConc->addRegExp( otherChild ); + } + + RegExpList newList; + RegExpListIt it1( list ); + while ( *it1 ) { + (*it1)->replacePart( replacement ); + RegExpListIt it2 = it1; + RegExpListIt it3( otherConc->list ); + bool match = true; + int count = 0; + + // See if replacement is a sublist of list starting from what it1 points at + for ( ; *it2 && * it3 && match ; ) { + if (! ( **it2 == **it3 ) ) + match = false; + ++it2; + ++it3; + ++count; + } + + if ( match && ! *it3) { + // I found a match, delete the element in it1, which is common with it3 + while ( *it1 != *it2 ) { + RegExp* item = *it1; + ++it1; + delete item; + } + RegExp* theClone = replacement->clone(); + newList.append( theClone ); + addChild( theClone ); + } + else { + newList.append( *it1 ); + ++it1; + } + } + list = newList; +} + + diff --git a/kregexpeditor/concregexp.h b/kregexpeditor/concregexp.h new file mode 100644 index 0000000..52a6342 --- /dev/null +++ b/kregexpeditor/concregexp.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __CONCREGEXP_H +#define __CONCREGEXP_H + +#include "regexp.h" + + +/** + Abstract syntax node for `concatenated' regular expression + @internal +*/ +class ConcRegExp :public RegExp +{ +public: + ConcRegExp( bool selected ); + + void addRegExp( RegExp *); + RegExpList children(); + RegExp* lastRegExp(); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 2;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + virtual RegExpType type() const {return CONC; } + virtual bool operator==( const RegExp& other ) const; + virtual void replacePart( CompoundRegExp* replacement ); + +private: + RegExpList list; +}; + +#endif // __CONCREGEXP_H diff --git a/kregexpeditor/concwidget.cpp b/kregexpeditor/concwidget.cpp new file mode 100644 index 0000000..f67c49b --- /dev/null +++ b/kregexpeditor/concwidget.cpp @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "concregexp.h" +#include "concwidget.h" +#include "dragaccepter.h" + +#include + +ConcWidget::ConcWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + :MultiContainerWidget(editorWindow, parent, name == 0 ? "concwidget" : name) +{ + init(); + DragAccepter *accepter = new DragAccepter(editorWindow, this); + accepter->show(); + _children.append(accepter); +} + + +ConcWidget::ConcWidget(RegExpEditorWindow* editorWindow, RegExpWidget *child, + QWidget *parent, const char *name) + :MultiContainerWidget(editorWindow, parent, name == 0 ? "concwidget" : name) +{ + init(); + DragAccepter *accepter = new DragAccepter(editorWindow, this); + _children.append(accepter); + child->reparent(this, QPoint(0,0), false); + addNewChild(accepter, child); +} + +ConcWidget::ConcWidget( RegExpEditorWindow* editorWindow, ConcWidget* origConc, + unsigned int start, unsigned int end) + :MultiContainerWidget(editorWindow, 0, "Splitted ConcWidget") +{ + init(); + _children.prepend( new DragAccepter(editorWindow, this) ); + for (unsigned int i = end; i >= start; i--) { + RegExpWidget* child = origConc->_children.take( i ); + _children.prepend( child ); + child->reparent( this, QPoint(0,0), false); + } + _children.prepend( new DragAccepter(editorWindow, this) ); +} + +ConcWidget::ConcWidget( ConcRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name ) + :MultiContainerWidget( editorWindow, parent, name == 0 ? "concwidget" : name ) +{ + init(); + DragAccepter *accepter = new DragAccepter(editorWindow, this); + _children.append(accepter); + + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + RegExpWidget* child = WidgetFactory::createWidget( *it, editorWindow, this ); + append( child ); + } +} + +void ConcWidget::init() +{ + _maxSelectedHeight = 0; +} + + +QSize ConcWidget::sizeHint() const +{ + int childrenWidth = 0; + int childrenHeight = 0; + QPtrListIterator it(_children); + + for ( ; *it; ++it) { + QSize thisChildSize = (*it)->sizeHint(); + childrenWidth += thisChildSize.width(); + childrenHeight = QMAX(childrenHeight, thisChildSize.height()); + } + + return QSize(childrenWidth, childrenHeight); +} + +void ConcWidget::paintEvent( QPaintEvent *e) +{ + Q_ASSERT( dynamic_cast(_children.at(0)) ); + // if this fails, then I should check the location of the show() + Q_ASSERT( _children.count() == 1 || + ( _children.count() >=3 && + dynamic_cast(_children.at(_children.count()-1)) ) ); + + if ( _children.count() == 1) { + // There is only an accepter, lets give it all the space. + _children.at(0)->setGeometry( 0, 0, size().width(), size().height() ); + } + else { + QSize myReqSize = sizeHint(); + QSize mySize(QMAX(myReqSize.width(), size().width()), + QMAX(myReqSize.height(), size().height())); + + // If the widget needs less space than it can get then this space should + // be given to the leftmost and rightmost accepter. So lets calculate + // this extra space. + int extra = 0; + if (size().width() > myReqSize.width()) { + extra = (size().width() - myReqSize.width())/2; + } + + QPainter painter( this ); + + drawPossibleSelection( painter, mySize ); + + int lastHeight = 0; + int offset = 0; + + for (unsigned int i = 1; i < _children.count(); i += 2 ) { + DragAccepter* accepter = dynamic_cast(_children.at(i-1)); + if (!accepter) + continue; + RegExpWidget* child = _children.at(i); + + QSize childSize = child->sizeHint(); + QSize curChildSize = child->size(); + + //----------------------------- first place the accepter + int x = offset; + int w = accepter->sizeHint().width(); + if ( i == 1 ) w+= extra; + int h = QMAX( lastHeight, childSize.height() ); + int y = (mySize.height() - h)/2; + accepter->setGeometry( x, y, w, h ); + + offset += w; + lastHeight = childSize.height(); + + + //------------------------------ Draw Accepter selection + if ( accepter->isSelected() ) { + y = (mySize.height()-_maxSelectedHeight)/2; + h = _maxSelectedHeight; + painter.fillRect( x, y, w, h, QBrush( gray ) ); + } + + //-------------------------------------- place the child + x = offset; + h = childSize.height(); + w = childSize.width(); + y = (mySize.height() - h)/2; + child->setGeometry( x, y, w, h ); + if ( childSize != curChildSize ) { + // I resized the child, so give it a chance to relect thus. + child->update(); + } + + offset += w; + + //------------------------------ Draw Accepter selection + if ( child->isSelected() ) { + y = (mySize.height()-_maxSelectedHeight)/2; + h = _maxSelectedHeight; + painter.fillRect( x, y, w, h, QBrush( gray ) ); + } + } + + //---------------------- Finally place the last accepter. + DragAccepter* accepter = + dynamic_cast(_children.at(_children.count()-1)); + // dynamic_cast is ASSERTed at top + int x = offset; + int h = lastHeight; + int w = accepter->sizeHint().width() + extra; + int y = (mySize.height()-h)/2; + accepter->setGeometry( x, y, w, h ); + } + MultiContainerWidget::paintEvent( e ); +} + +void ConcWidget::mousePressEvent ( QMouseEvent* event ) +{ + if ( event->button() == RightButton ) { + _editorWindow->showRMBMenu( _editorWindow->hasSelection() ); + } + else { + RegExpWidget::mousePressEvent( event ); + } +} + + + +void ConcWidget::sizeAccepter( DragAccepter* accepter, int height, int totHeight ) +{ + if (accepter->height() != height ) { + accepter->resize( accepter->width(), height ); + } + + if (accepter->y() != (totHeight - height)/2) { + accepter->move( accepter->x(), (totHeight - height)/2 ); + } +} + +RegExp* ConcWidget::regExp() const +{ + QPtrListIterator it( _children ); + ++it; // start with the second element. + + if ( _children.count() == 3 ) { + // Exactly one child (and two drag accepters) + return (*it)->regExp(); + } + else { + ConcRegExp *regexp = new ConcRegExp( isSelected() ); + + for ( ; *it; it+=2 ) { + regexp->addRegExp( (*it)->regExp() ); + } + return regexp; + } +} + +bool ConcWidget::updateSelection(bool parentSelected) +{ + bool isSel = _isSelected; + bool changed = MultiContainerWidget::updateSelection( parentSelected ); + + _maxSelectedHeight = 0; + + QPtrListIterator it(_children); + ++it; // Skip past the first DragAccepter + for ( ; *it; it +=2 ) { + if ( (*it)->isSelected() ) { + _maxSelectedHeight = QMAX( _maxSelectedHeight, (*it)->sizeHint().height() ); + } + } + + changed = changed || isSel != _isSelected; + if ( changed ) { + repaint(); + } + + return changed; +} + +void ConcWidget::getSelectionIndexes( int* start, int* end ) +{ + *start = -1; + *end = -1; + + // Start with element at index 1, and skip every second element, as we + // know they are dragAccepters. + for ( unsigned int index = 1; index< _children.count(); index += 2 ) { + RegExpWidget* child = _children.at(index); + + if ( child->isSelected() ) { + // The child is selected at topmost level. + if ( *start == -1 ) { + *start = index; + } + } + else if ( *start != -1 ) { + // Found the end of the selection. + *end = index -2; + break; + } + } + + if ( *start != -1 && *end == -1 ) + *end = _children.count() -2; +} + +void ConcWidget::applyRegExpToSelection( RegExpType type ) +{ + int start, end; + getSelectionIndexes( &start, &end ); + + if ( start == -1 ) { + // No item selected at top level + + QPtrListIterator it(_children); + ++it; // Skip past the first DragAccepter + for ( ; *it ; it += 2 ) { + if ( (*it)->hasSelection() ) { + (*it)->applyRegExpToSelection( type ); + break; + } + } + } + else { + // Apply RegExp to selection. + RegExpWidget* newElm = WidgetFactory::createWidget( _editorWindow, this, type ); + + if ( newElm ) { + ConcWidget* subSequence = new ConcWidget(_editorWindow, this, start, end); + newElm->setConcChild( subSequence ); + + + subSequence->resize(0,0); // see note (1) + subSequence->reparent( newElm, QPoint(0,0), false); + _children.insert( start, newElm ); + newElm->show(); + } + } +} + +bool ConcWidget::isSelected() const +{ + // A ConcWidget should be considered selected when all its elements has been selected + // otherwise empty ConcWidgets may be left behind when for example selection is deleted. + bool allSelected = true; + QPtrListIterator it(_children); + ++it; // Skip past first DragAccepter. + for ( ; *it && allSelected; it += 2 ) { + allSelected = allSelected && (*it)->isSelected(); + } + + return allSelected; +} + +RegExp* ConcWidget::selection() const +{ + if ( isSelected() ) + return regExp(); + + bool foundAny = false; + bool foundMoreThanOne = false; + RegExp* regexp = 0; + + QPtrListIterator it(_children); + ++it; // Skip past the first DragAccepter + for ( ; (*it) ; it += 2 ) { + if ( (*it)->hasSelection() ) { + if (!foundAny) { + regexp = (*it)->selection(); + foundAny = true; + } + else if ( !foundMoreThanOne ) { + ConcRegExp* reg = new ConcRegExp( isSelected() ); + reg->addRegExp( regexp ); + reg->addRegExp( (*it)->selection() ); + regexp = reg; + foundMoreThanOne = true; + } + else { + dynamic_cast(regexp)->addRegExp( (*it)->selection() ); + } + } + } + + Q_ASSERT( foundAny ); + return regexp; +} + +void ConcWidget::addNewConcChild(DragAccepter *accepter, ConcWidget *other) +{ + for ( unsigned int i=0; i<_children.count(); i+= 2 ) { + RegExpWidget *ch = _children.at( i ); + if ( ch == accepter ) { + // Move all the element from the `child' ConcWidget to this one. + // Do not copy the first one as this is a dragAccepter, and we place the widgets + // after this drag accepter. + // We must take them in pairs to avoid breaking the invariant for paintEvent, + // namely that every second element is a dragAccepter + for ( unsigned int j = other->_children.count()-1; j > 0 ; j-=2 ) { + RegExpWidget* newChildA = other->_children.take(j); + newChildA->reparent( this, QPoint(0,0), false); + _children.insert( i+1, newChildA ); + RegExpWidget* newChildB = other->_children.take(j-1); + newChildB->reparent( this, QPoint(0,0), false); + _children.insert( i+1, newChildB ); + newChildA->show(); + newChildB->show(); + } + delete other; + return; + } + } + qFatal("accepter not found"); +} + +bool ConcWidget::validateSelection() const +{ + bool cont = true; + QPtrListIterator it(_children); + ++it; // skip past the DragAccepter. + for ( ; *it && cont; it += 2 ) { + cont = (*it)->validateSelection(); + } + return cont; +} diff --git a/kregexpeditor/concwidget.h b/kregexpeditor/concwidget.h new file mode 100644 index 0000000..6101ed2 --- /dev/null +++ b/kregexpeditor/concwidget.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __concwidget +#define __concwidget + +#include "multicontainerwidget.h" +class ConcRegExp; + +/** + RegExp widget which can have several sub widget inside it. + This widget is invisible to the user, but act as a container around + other RegExp widgets + @internal +*/ +class ConcWidget :public MultiContainerWidget +{ +public: + ConcWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + ConcWidget(RegExpEditorWindow* editorWindow, RegExpWidget *child, + QWidget *parent, const char *name=0); + ConcWidget( RegExpEditorWindow* editorWindow, ConcWidget* origConc, + unsigned int start, unsigned int end); + ConcWidget( ConcRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0); + void init(); + + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual bool updateSelection(bool parentSelected); + virtual bool isSelected() const; + + virtual void applyRegExpToSelection( RegExpType type ); + virtual RegExpType type() const { return CONC; } + virtual RegExp* selection() const; + virtual void addNewConcChild(DragAccepter *accepter, ConcWidget *child); + virtual bool validateSelection() const; + virtual bool acceptWidgetInsert( RegExpType ) const { return false; } + virtual bool acceptWidgetPaste() const { return false; } + bool hasAnyChildren() { return _children.count() > 1; } + +protected: + virtual void paintEvent( QPaintEvent *e ); + virtual void mousePressEvent ( QMouseEvent* event ); + void sizeAccepter( DragAccepter* accepter, int height, int totHeight ); + void getSelectionIndexes( int* start, int* end ); + virtual void dragEnterEvent(QDragEnterEvent* event) { event->accept( false ); } + +private: + int _maxSelectedHeight; +}; + + +#endif // __concwidget diff --git a/kregexpeditor/dcbutton.cpp b/kregexpeditor/dcbutton.cpp new file mode 100644 index 0000000..b5bdcf8 --- /dev/null +++ b/kregexpeditor/dcbutton.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include "dcbutton.moc" +#endif + +#include "dcbutton.h" + +DoubleClickButton::DoubleClickButton( QPixmap pixmap, QWidget* parent, const char* name ) + : QToolButton( parent, name ? name : "DoubleClickButton" ) +{ + setPixmap( pixmap ); +} + +void DoubleClickButton::mouseDoubleClickEvent( QMouseEvent* ) +{ + emit doubleClicked(); +} + + diff --git a/kregexpeditor/dcbutton.h b/kregexpeditor/dcbutton.h new file mode 100644 index 0000000..78a18a3 --- /dev/null +++ b/kregexpeditor/dcbutton.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef dcbutton +#define dcbutton + +#include +class QMouseEvent; + +/** + QToolButton extended to emit a signal on double click. + @internal +*/ +class DoubleClickButton :public QToolButton +{ +Q_OBJECT + +public: + DoubleClickButton( QPixmap pix, QWidget* parent, const char* name = 0); + +protected: + virtual void mouseDoubleClickEvent ( QMouseEvent * ); + +signals: + void doubleClicked(); +}; + +#endif // dcbutton diff --git a/kregexpeditor/dotregexp.cpp b/kregexpeditor/dotregexp.cpp new file mode 100644 index 0000000..3d375be --- /dev/null +++ b/kregexpeditor/dotregexp.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "dotregexp.h" + +DotRegExp::DotRegExp( bool selected ) :RegExp( selected ) +{ +} + +bool DotRegExp::check( ErrorMap&, bool, bool ) +{ + return false; +} + +QDomNode DotRegExp::toXml( QDomDocument* doc ) const +{ + return doc->createElement( QString::fromLocal8Bit("AnyChar") ); +} + +bool DotRegExp::load( QDomElement /* top */, const QString& /*version*/ ) +{ + // Nothing to do + return true; +} + diff --git a/kregexpeditor/dotregexp.h b/kregexpeditor/dotregexp.h new file mode 100644 index 0000000..b46cffb --- /dev/null +++ b/kregexpeditor/dotregexp.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef DOTREGEXP_H +#define DOTREGEXP_H + +#include "regexp.h" + +/** + Abstract syntax node for "the dot" regular expression (i.e. any characters) + @internal +*/ +class DotRegExp :public RegExp +{ +public: + + DotRegExp( bool selected ); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 4;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + virtual RegExpType type() const { return DOT;} +}; + +#endif // DOTREGEXP_H + diff --git a/kregexpeditor/drag.cpp b/kregexpeditor/drag.cpp new file mode 100644 index 0000000..11ecc63 --- /dev/null +++ b/kregexpeditor/drag.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "drag.h" +#include "regexp.h" +#include "regexpconverter.h" +#include "widgetfactory.h" + +RegExpWidgetDrag::RegExpWidgetDrag( RegExp* regexp, QWidget* dragSource ) + : QDragObject( dragSource ), _regexp( regexp->clone() ) +{ +} + +RegExpWidgetDrag::~RegExpWidgetDrag() +{ + delete _regexp; +} + + +bool RegExpWidgetDrag::canDecode( QDragMoveEvent* event ) +{ + return event->provides( "KRegExpEditor/widgetdrag" ); +} + +RegExpWidget* RegExpWidgetDrag::decode(QDropEvent* event, RegExpEditorWindow* window, + QWidget* parent) +{ + QByteArray payload = event->encodedData("KRegExpEditor/widgetdrag" ); + QTextStream stream( payload, IO_ReadOnly ); + QString str = stream.read(); + RegExp* regexp = WidgetFactory::createRegExp( str ); + RegExpWidget* widget = WidgetFactory::createWidget( regexp, window, parent ); + delete regexp; + return widget; +} + +const char * RegExpWidgetDrag::format ( int i ) const +{ + if ( i == 0 ) + return "KRegExpEditor/widgetdrag"; + else if ( i == 1 ) + return "text/plain"; + else + return 0; +} + +QByteArray RegExpWidgetDrag::encodedData ( const char* format ) const +{ + QByteArray data; + QTextStream stream( data, IO_WriteOnly ); + if ( QString::fromLocal8Bit( format ).startsWith(QString::fromLocal8Bit( "KRegExpEditor/widgetdrag" ) ) ) { + QString xml = _regexp->toXmlString(); + stream << xml; + } + else if ( QString::fromLocal8Bit( format ).startsWith(QString::fromLocal8Bit( "text/plain" ) ) ) { + stream << RegExpConverter::current()->toStr( _regexp, false ); + } + else { + qWarning("Unexpected drag and drop format: %s", format ); + } + return data; +} + diff --git a/kregexpeditor/drag.h b/kregexpeditor/drag.h new file mode 100644 index 0000000..5a074d1 --- /dev/null +++ b/kregexpeditor/drag.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef drag_h +#define drag_h + +#include + +class RegExp; +class RegExpWidget; +class RegExpEditorWindow; + +/** + Class used for drag and drop in the RegExp widget. + @internal +*/ +class RegExpWidgetDrag :public QDragObject +{ +public: + RegExpWidgetDrag( RegExp* regexp , QWidget* dragSource); + ~RegExpWidgetDrag(); + virtual const char * format ( int i = 0 ) const; + virtual QByteArray encodedData ( const char * ) const; + static bool canDecode(QDragMoveEvent* event); + static RegExpWidget* decode(QDropEvent* event, RegExpEditorWindow* window, + QWidget* parent); +private: + RegExp* _regexp; +}; + +#endif // drag_h diff --git a/kregexpeditor/dragaccepter.cpp b/kregexpeditor/dragaccepter.cpp new file mode 100644 index 0000000..0198e58 --- /dev/null +++ b/kregexpeditor/dragaccepter.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "dragaccepter.h" +#include "concwidget.h" + +#include + +DragAccepter::DragAccepter(RegExpEditorWindow* editorWindow, RegExpWidget *parent, + const char *name) + : RegExpWidget(editorWindow, parent, name == 0 ? "dragaccepter" : name ), + _drawLine( false ) +{ + setAcceptDrops(TRUE); +} + +QSize DragAccepter::sizeHint() const +{ + return QSize(10,10); +} + +void DragAccepter::paintEvent(QPaintEvent *e) +{ + QPainter painter(this); + drawPossibleSelection( painter, size() ); + + if ( _drawLine ) + painter.drawLine( 0, height()/2, width(), height()/2 ); + + RegExpWidget::paintEvent(e); +} + +void DragAccepter::mousePressEvent ( QMouseEvent* event ) +{ + if ( event->button() == RightButton ) { + _editorWindow->showRMBMenu( _editorWindow->hasSelection() ); + } + else { + RegExpWidget::mousePressEvent( event ); + } +} + +void DragAccepter::mouseReleaseEvent( QMouseEvent* event ) +{ + if ( _editorWindow->isPasteing() && event->button() == LeftButton ) { + RegExp* regexp = _editorWindow->pasteData(); + + RegExpWidget *newElm = WidgetFactory::createWidget( regexp, _editorWindow, 0 ); + if ( newElm ) { + ConcWidget* elm; + if (! (elm = dynamic_cast( newElm ) ) ) { + elm = new ConcWidget( _editorWindow, newElm, 0 ); + } + + Q_ASSERT( elm ); + + RegExpWidget *w = dynamic_cast(parent()); + if (w) + w->addNewConcChild(this, elm); + _editorWindow->updateContent( this ); + _editorWindow->clearSelection( true ); + } + } + else if ( _editorWindow->isInserting() && event->button() == LeftButton ) { + if ( WidgetFactory::isContainer( _editorWindow->insertType() ) && + _editorWindow->pointSelected( mapToGlobal( event->pos() ) ) ) { + RegExpWidget::mouseReleaseEvent( event ); + } + else { + RegExpWidget *child = WidgetFactory::createWidget( _editorWindow, + dynamic_cast(parent()), + _editorWindow->insertType() ); + if ( child ) { + RegExpWidget *w = dynamic_cast(parent()); + if (w) + w->addNewChild(this, child); + _editorWindow->updateContent( child ); + child->setFocus(); + _editorWindow->clearSelection( true ); + } + } + } + _editorWindow->slotEndActions(); +} + + +void DragAccepter::dragEnterEvent(QDragEnterEvent *event) +{ + bool selfDrag = ( event->source() && event->source()->topLevelWidget() == topLevelWidget() && _isSelected ); + event->accept(RegExpWidgetDrag::canDecode( event ) && !selfDrag ); +} + +void DragAccepter::dropEvent(QDropEvent *event) +{ + // The widget will be reparent afterward or part of it will, so no need to give + // it a parent here. + RegExpWidget *newElm = RegExpWidgetDrag::decode( event, _editorWindow, 0 ); + ConcWidget* elm; + if ( !(elm = dynamic_cast( newElm ) ) ) { + elm = new ConcWidget( _editorWindow, newElm, 0 ); + } + + Q_ASSERT( elm ); + + RegExpWidget *rew = dynamic_cast(parent()); + if (rew) + rew->addNewConcChild(this, elm); + QWidget *w = dynamic_cast(parent()); + if (w) + w->update(); + _editorWindow->updateContent( this ); + + bool selfDrag = ( event->source() && event->source()->topLevelWidget() == topLevelWidget() ); + if ( ! selfDrag ) + _editorWindow->clearSelection( true ); + else { + // selection should not be cleared here, since we might want to delete it. + } + event->accept(); +} + +RegExp* DragAccepter::regExp() const +{ + return 0; +} diff --git a/kregexpeditor/dragaccepter.h b/kregexpeditor/dragaccepter.h new file mode 100644 index 0000000..48af09f --- /dev/null +++ b/kregexpeditor/dragaccepter.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __dragaccepter +#define __dragaccepter + +#include "regexpwidget.h" +class MultiContainerWidget; + +/** + RegExp widget representing a "spot" in which new RegExp widgets can be inserted. + @internal +*/ +class DragAccepter :public RegExpWidget +{ + friend class MultiContainerWidget; + +public: + DragAccepter(RegExpEditorWindow* editorWindow, RegExpWidget *parent, + const char *name = 0); + QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual RegExpType type() const { return DRAGACCEPTER; } + void setDrawLine( bool drawLine ) { _drawLine = drawLine; } + +protected: + virtual void mousePressEvent ( QMouseEvent* event ); + virtual void mouseReleaseEvent( QMouseEvent* event ); + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); + virtual void paintEvent(QPaintEvent *); + virtual bool acceptWidgetInsert( RegExpType ) const { return true; } + virtual bool acceptWidgetPaste() const { return true; } + +private: + bool _drawLine; +}; + +#endif // __dragaccepter diff --git a/kregexpeditor/editorwindow.cpp b/kregexpeditor/editorwindow.cpp new file mode 100644 index 0000000..e8c4ac8 --- /dev/null +++ b/kregexpeditor/editorwindow.cpp @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" + #include "images.h" +#else + #include + #include +// #include + #include + #include + #include "editorwindow.moc" + #include +#endif + +#include "editorwindow.h" +#include "concwidget.h" +#include +#include +#include +#include +#include +#include +#include "regexp.h" +#include "userdefinedregexps.h" +#include + +RegExpEditorWindow::RegExpEditorWindow( QWidget *parent, const char *name) + : QWidget(parent, name, Qt::WPaintUnclipped) +{ + _top = new ConcWidget(this, this); + _layout = new QHBoxLayout( this); + _layout->addWidget(_top); + _top->setToplevel(); + _undrawSelection = false; + _menu = 0; + _insertInAction = false; + _pasteInAction = false; + _pasteData = 0; + + QAccel* accel = new QAccel( this ); + accel->connectItem( accel->insertItem( CTRL+Key_C ), this, SLOT( slotCopy() ) ); + accel->connectItem( accel->insertItem( CTRL+Key_X ), this, SLOT( slotCut() ) ); + accel->connectItem( accel->insertItem( Key_Delete ), this, SLOT( slotCut() ) ); + accel->connectItem( accel->insertItem( Key_BackSpace ), this, SLOT( slotCut() ) ); + accel->connectItem( accel->insertItem( CTRL+Key_V ), this, SLOT( slotStartPasteAction() ) ); + accel->connectItem( accel->insertItem( Key_Escape ), this, SLOT( slotEndActions() ) ); + accel->connectItem( accel->insertItem( CTRL+Key_S ), this, SLOT( slotSave() ) ); + + connect( this, SIGNAL( change() ), this, SLOT( emitVerifyRegExp() ) ); +} + +RegExp* RegExpEditorWindow::regExp() const +{ + return _top->regExp(); +} + +void RegExpEditorWindow::mousePressEvent ( QMouseEvent* event ) +{ + setFocus(); + updateContent( 0 ); + + _start = event->pos(); + _lastPoint = QPoint(0,0); + + if ( pointSelected( event->globalPos() ) ) { + _isDndOperation = true; + } + else { + _isDndOperation = false; + _selection = QRect(); + _top->updateSelection( false ); + + QWidget::mousePressEvent( event ); + } + grabMouse(); +} + +bool RegExpEditorWindow::pointSelected( QPoint p ) const +{ + QRect rect = _top->selectionRect(); + return rect.contains(p); +} + +void RegExpEditorWindow::mouseMoveEvent ( QMouseEvent* event ) +{ + if ( _isDndOperation ) { + if ( ( _start - event->pos() ).manhattanLength() > QApplication::startDragDistance() ) { + RegExp* regexp = _top->selection(); + if ( !regexp ) + return; + QDragObject *d = new RegExpWidgetDrag( regexp, this ); + delete regexp; + + bool del = d->drag(); + if ( del ) + slotDeleteSelection(); + else { + clearSelection( true ); + } + releaseMouse(); + emit change(); + emit canSave( _top->hasAnyChildren() ); + } + } + else { + QPainter p( this ); + p.setRasterOp( Qt::NotROP ); + p.setPen( Qt::DotLine ); + + // remove last selection rectangle + if ( ! _lastPoint.isNull() && _undrawSelection ) { + p.drawRect(QRect(_start, _lastPoint)); + } + + // Note this line must come after the old rect has been removed + // and before the new one is draw otherwise the update event which this + // line invokes, will remove a line, which later will be drawn instead of + // removed during NotROP. + _top->updateSelection( false ); + emit scrolling( event->pos() ); + + p.drawRect(QRect(_start, event->pos())); + _undrawSelection = true; + _lastPoint = event->pos(); + + _selection = QRect(mapToGlobal(_start), mapToGlobal(_lastPoint)).normalize(); + } +} + +void RegExpEditorWindow::mouseReleaseEvent( QMouseEvent *event) +{ + releaseMouse(); + QWidget::mouseReleaseEvent( event); + + // remove last selection rectangle + QPainter p( this ); + p.setRasterOp( Qt::NotROP ); + p.setPen( Qt::DotLine ); + if ( ! _lastPoint.isNull() ) { + p.drawRect(QRect(_start, _lastPoint)); + } + _top->validateSelection(); + _top->updateAll(); + emit anythingSelected( hasSelection() ); + if ( hasSelection() ) { + emit verifyRegExp(); + } +} + +bool RegExpEditorWindow::selectionOverlap( QPoint pos, QSize size ) const +{ + QRect child(pos, size); + + return (_selection.intersects(child) && ! child.contains(_selection)); +} + +bool RegExpEditorWindow::hasSelection() const +{ + return _top->hasSelection(); +} + +void RegExpEditorWindow::clearSelection( bool update ) +{ + _top->clearSelection(); + if ( update ) + _top->updateAll(); + emit anythingSelected(false); +} + +void RegExpEditorWindow::slotInsertRegExp( RegExpType type ) +{ + _insertInAction = true; + _insertTp = type; + + updateCursorUnderPoint(); + setFocus(); +} + +void RegExpEditorWindow::slotInsertRegExp( RegExp* regexp ) +{ + if ( _pasteData ) + delete _pasteData; + + _pasteData = regexp->clone(); + _pasteInAction = true; + updateCursorUnderPoint(); + setFocus(); +} + +void RegExpEditorWindow::slotDoSelect() +{ + _pasteInAction = false; + _insertInAction = false; + + // I need to update the cursor recursively, as a repaint may not have been issued yet + // when this method is invoked. This means that when the repaint comes, the cursor may + // move to an other widget. + _top->updateCursorRecursively(); +} + +void RegExpEditorWindow::slotDeleteSelection() +{ + if ( ! hasSelection() ) { + KMessageBox::information(this, i18n( "There is no selection."), i18n("Missing Selection") ); + } + else { + _top->deleteSelection(); + } + updateContent( 0 ); +} + +void RegExpEditorWindow::updateContent( QWidget* focusChild) +{ + QPoint p(0,0); + if ( focusChild ) + p = focusChild->mapTo( this, QPoint(0,0) ); + + _top->update(); + emit contentChanged( p ); +} + +QSize RegExpEditorWindow::sizeHint() const +{ + return _top->sizeHint(); +} + +void RegExpEditorWindow::paintEvent( QPaintEvent* event ) +{ + QWidget::paintEvent( event ); + _undrawSelection = false; +} + +void RegExpEditorWindow::slotCut() +{ + cut( QCursor::pos() ); + emit change(); + emit canSave( _top->hasAnyChildren() ); +} + +void RegExpEditorWindow::cut( QPoint pos ) +{ + cutCopyAux( pos ); + slotDeleteSelection(); +} + +void RegExpEditorWindow::slotCopy() +{ + copy( QCursor::pos() ); +} + +void RegExpEditorWindow::copy( QPoint pos ) +{ + cutCopyAux( pos ); + clearSelection( true ); +} + + +void RegExpEditorWindow::cutCopyAux( QPoint pos ) +{ + if ( !hasSelection() ) { + RegExpWidget* widget = _top->widgetUnderPoint( pos, true ); + if ( !widget ) { + KMessageBox::information(this, i18n("There is no widget under cursor."), i18n("Invalid Operation") ); + return; + } + else { + widget->updateSelection( true ); // HACK! + } + } + + RegExp* regexp = _top->selection(); + RegExpWidgetDrag *clipboardData = new RegExpWidgetDrag( regexp, this ); + delete regexp; + + QClipboard* clipboard = qApp->clipboard(); + clipboard->setData( clipboardData ); + emit anythingOnClipboard( true ); + emit canSave( _top->hasAnyChildren() ); +} + + +void RegExpEditorWindow::slotStartPasteAction() +{ + QByteArray data = qApp->clipboard()->data()->encodedData( "KRegExpEditor/widgetdrag" ); + QTextStream stream( data, IO_ReadOnly ); + QString str = stream.read(); + + RegExp* regexp = WidgetFactory::createRegExp( str ); + if ( regexp ) + slotInsertRegExp( regexp ); +} + +void RegExpEditorWindow::slotEndActions() { + emit doneEditing(); + emit change(); + emit canSave( _top->hasAnyChildren() ); +} + +void RegExpEditorWindow::showRMBMenu( bool enableCutCopy ) +{ + enum CHOICES { CUT, COPY, PASTE, SAVE, EDIT }; + + if ( !_menu ) { + _menu = new QPopupMenu( 0 ); + _menu->insertItem(getIcon(QString::fromLocal8Bit("editcut")), + i18n("C&ut"), CUT); + _menu->insertItem(getIcon(QString::fromLocal8Bit("editcopy")), + i18n("&Copy"), COPY); + _menu->insertItem(getIcon(QString::fromLocal8Bit("editpaste")), + i18n("&Paste"), PASTE); + _menu->insertSeparator(); + _menu->insertItem(getIcon(QString::fromLocal8Bit("edit")), + i18n("&Edit"), EDIT); + _menu->insertItem(getIcon(QString::fromLocal8Bit("filesave")), + i18n("&Save Regular Expression..."), SAVE); + } + + _menu->setItemEnabled( CUT, enableCutCopy ); + _menu->setItemEnabled( COPY, enableCutCopy ); + + if ( ! qApp->clipboard()->data()->provides( "KRegExpEditor/widgetdrag" ) ) + _menu->setItemEnabled( PASTE, false ); + else + _menu->setItemEnabled( PASTE, true ); + + _menu->setItemEnabled( SAVE, _top->hasAnyChildren() ); + + RegExpWidget* editWidget = _top->findWidgetToEdit( QCursor::pos() ); + + _menu->setItemEnabled( EDIT, editWidget ); + + QPoint pos = QCursor::pos(); + int choice = _menu->exec( pos ); + switch ( choice ) { + case COPY: copy( pos ); break; + case CUT: cut( pos ); break; + case PASTE: slotStartPasteAction(); break; + case SAVE: slotSave(); break; + case EDIT: editWidget->edit(); break; + } + emit change(); + emit canSave( _top->hasAnyChildren() ); +} + +void RegExpEditorWindow::applyRegExpToSelection( RegExpType tp ) +{ + _top->applyRegExpToSelection( tp ); +} + +void RegExpEditorWindow::slotSave() +{ + QString dir = WidgetWinItem::path(); + QString txt; + +#ifdef QT_ONLY + txt = QInputDialog::getText( tr("Name for regexp"), tr("Enter name:") ); + if ( txt.isNull() ) + return; +#else + KLineEditDlg dlg(i18n("Enter name:"), QString::null, this); + dlg.setCaption(i18n("Name for Regular Expression")); + if (!dlg.exec()) return; + txt = dlg.text(); +#endif + + QString fileName = dir + QString::fromLocal8Bit("/") + txt + QString::fromLocal8Bit(".regexp"); + QFileInfo finfo( fileName ); + if ( finfo.exists() ) { + int answer = KMessageBox::warningContinueCancel( this, i18n("

Overwrite named regular expression %1

").arg(txt), QString::null, i18n("Overwrite")); + if ( answer != KMessageBox::Continue ) + return; + } + + QFile file( fileName ); + if ( ! file.open(IO_WriteOnly) ) { + KMessageBox::sorry( this, i18n("Could not open file for writing: %1").arg(fileName) ); + return; + } + + // Convert to XML. + RegExp* regexp = _top->regExp(); + QString xml = regexp->toXmlString(); + delete regexp; + + QTextStream stream(&file); + stream << xml; + + file.close(); + emit savedRegexp(); +} + + +void RegExpEditorWindow::slotSetRegExp( RegExp* regexp ) +{ + // I have no clue why the following line is necesarry, but if it is not here + // then the editor area is messed up when calling slotSetRegExp before starting the eventloop. + qApp->processEvents(); + + delete _top; + RegExpWidget* widget = WidgetFactory::createWidget( regexp, this, this ); + if ( ! (_top = dynamic_cast( widget ) ) ) { + // It was not a ConcWidget + _top = new ConcWidget( this, widget, this ); + } + _top->setToplevel(); + + _top->show(); + _layout->addWidget( _top ); + clearSelection( true ); // HACK? + emit canSave( _top->hasAnyChildren() ); +} + +void RegExpEditorWindow::updateCursorUnderPoint() +{ + RegExpWidget* widget = _top->widgetUnderPoint( QCursor::pos(), false ); + if ( widget ) + widget->updateCursorShape(); +} + +void RegExpEditorWindow::emitVerifyRegExp() +{ + emit verifyRegExp(); +} + + +QIconSet RegExpEditorWindow::getIcon( const QString& name ) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage( name ) ); + return pix; +#else + return SmallIconSet( name ); +#endif +} + diff --git a/kregexpeditor/editorwindow.h b/kregexpeditor/editorwindow.h new file mode 100644 index 0000000..e925c59 --- /dev/null +++ b/kregexpeditor/editorwindow.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef editorwindow_h +#define editorwindow_h + +#include "drag.h" +#include "widgetfactory.h" +#include +#include +#include +class RegExp; +class RegExpWidget; +class QHBoxLayout; + +/** Widget representing the editor window of a regular expression editor. + + @internal + This widget represent the editor part (That is the location where the + regexp widgets are located). + + Furthermore, it also responsible for: + @li Widget traversal operations (see e.g. @ref hasSelection, @ref + clearSelection, and @ref applyRegExpToSelection ). + @li Containing global information for regexp editing. (See @ref + _pasteData and @ref _insertInAction ) + + All subclasses of @ref RegExpWidget contains a pointer to the @ref + RegExpEditorWindow which the widget is a child of. They use this + pointer to start operations like rubber band selection, cut/paste etc. +*/ +class RegExpEditorWindow :public QWidget +{ + Q_OBJECT + +public: + RegExpEditorWindow(QWidget *parent, const char *name = 0); + + /** + Returns an object which represent the regular expression "drawn" in + the editor window. This object is capable of generating a textual + representation of the regexp (see @ref RegExp::emacs, and @ref + RegExp::perl etc) + */ + RegExp* regExp() const; + + /** + This method returns true if the rectangle starting at `globalPos' with + size `size' overlaps the rubber-band rectangle. + Note this method is only valid while doing rubber-band + selection. Afterwards, use @ref pointSelected instead. + */ + bool selectionOverlap( QPoint globalPos, QSize size ) const; + + /** + returns true if `pos' lays on top of a widget that is selected. + */ + bool pointSelected( QPoint pos ) const; + + /** + returns true if the editor has a selection. + */ + bool hasSelection() const; + + /** + clears the selection, and if `update', invokes update on all the + widgets + */ + void clearSelection( bool update ); + + /** + invoked update on the top widget, and ensures that `focusChild' is + visible. It's valid for `focusChild' to be 0. + */ + void updateContent(QWidget* focusChild); + + RegExp* pasteData() { return _pasteData; } + bool isPasteing() const { return _pasteInAction; } + bool isInserting() const { return _insertInAction; } + + /** + Returns the type currently being inserted. + This is the type, which was given to @ref slotInsertRegExp + */ + RegExpType insertType() const { return _insertTp; } + + /** + Create a regexp widget, so that it wraps around the current selected + regexp. + */ + void applyRegExpToSelection( RegExpType tp ); + + /** + Pops up the RMB menu, which contains cut, copy, past, ... + */ + void showRMBMenu( bool enableCutCopy ); + + virtual QSize sizeHint() const; + +public slots: + + /** + Set the editor window to the regular expression given as argument + */ + void slotSetRegExp( RegExp* regexp ); + + /** + Change editing mode to insertion. This means that the cursor will + change to a cross (where ever inserting of the `type' is allowed), + and the next mouse press in allowed places will result in that a + regular expression of type `type' will be inserted there. + + Note this method do not do the actual insertion. + + This method is used when the user presses one of the buttons to the + right of the editor window. + */ + void slotInsertRegExp( RegExpType type ); + + /** + Change editing state to selection. + */ + void slotDoSelect(); + + /** + Like @ref slotInsertRegExp above. This time, however, data will be + submitted in as a RegExp pointer. + + Note this method do not do the actual insertion. + + This method is called when the user pastes data (using the RPM menu), + or when a regular expression is loaded from file. + */ + void slotInsertRegExp( RegExp* regexp ); + + /** + see @ref RegExpWidget::deleteSelection + */ + void slotDeleteSelection(); + + /** + This method is invoked when the user selects paste in the RMB menu. It + will change the mouse cursor etc. as described in @ref + slotInsertRegExp + */ + void slotStartPasteAction(); + + /** + Ends an insert or paste action. This involves changing cursor back to + normal cursor. + */ + void slotEndActions(); + + void emitChange() { emit change(); } + + void updateCursorUnderPoint(); + + void slotCut(); + void slotCopy(); + void slotSave(); + +signals: + /** + This signal is emitted whenever the content of the editor window is + changed. + + If focusPoint is non-null then this point should be made visible + */ + void contentChanged( QPoint focusPoint ); + + /** + This signal is emitted whenever mouse is being dragged in the editor + window. `focusPoint' is the mouse' current position. + */ + void scrolling( QPoint focusPoint ); + + /** + see @ref RegExpScrolledEditorWindow::doneEditing + */ + void doneEditing(); + + /** + see @ref RegExpScrolledEditorWindow::change + */ + void change(); + + /** + see @ref RegExpScrolledEditorWindow::savedRegexp + */ + void savedRegexp(); + + /** + see @ref RegExpScrolledEditorWindow::verifyRegExp + */ + void verifyRegExp(); + + void anythingSelected( bool ); + void anythingOnClipboard( bool ); + void canSave( bool ); + + +protected: + virtual void mousePressEvent ( QMouseEvent* event ); + virtual void mouseMoveEvent ( QMouseEvent* event ); + virtual void mouseReleaseEvent( QMouseEvent *event); + virtual void paintEvent( QPaintEvent* event ); + +protected slots: + virtual void emitVerifyRegExp(); + +private: + void cutCopyAux( QPoint pos ); + void copy( QPoint pos ); + void cut( QPoint pos ); + +private: + /** This points to the top @ref RegExpWidget in the editor window. */ + ConcWidget *_top; + + /** This points to the layout manager for the editor window */ + QHBoxLayout* _layout; + + /** Start point and last point draw. Used when doing rubber band selection */ + QPoint _start, _lastPoint; + + /** The area which the rubber band selection is over */ + QRect _selection; + + /** + True when a rubber band selection rectangle is drawn, and need to be + un-drawn before next rubber band selection rectangle may be drawn. + */ + bool _undrawSelection; + + /** true when a paste action is in action (see @ref isPasteing ). */ + bool _pasteInAction; + + /** true when an insert action is in action (see @ref isInserting ). */ + bool _insertInAction; + + /** The type being inserted (see @ref insertType ) */ + RegExpType _insertTp; + + /** The data being inserted (see @ref pasteData ) */ + RegExp* _pasteData; + + /** Popup menu used for RMB */ + QPopupMenu* _menu; + + QIconSet getIcon( const QString& name ); + + bool _isDndOperation; +}; + +#endif // editorwindow_h diff --git a/kregexpeditor/emacsregexpconverter.cpp b/kregexpeditor/emacsregexpconverter.cpp new file mode 100644 index 0000000..327d04c --- /dev/null +++ b/kregexpeditor/emacsregexpconverter.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "emacsregexpconverter.h" +#include "regexp.h" +#include "altnregexp.h" +#include "concregexp.h" +#include "lookaheadregexp.h" +#include "textrangeregexp.h" +#include "textregexp.h" +#include "compoundregexp.h" +#include "dotregexp.h" +#include "positionregexp.h" +#include "repeatregexp.h" + +#include +#include +bool EmacsRegExpConverter::canParse() +{ + return false; +} + +QString EmacsRegExpConverter::toString( AltnRegExp* regexp, bool markSelection ) +{ + QString res; + + bool first = true; + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + if ( !first ) { + res += QString::fromLatin1("\\|"); + } + first = false; + res += toStr( *it, markSelection ); + } + return res; + +} + +QString EmacsRegExpConverter::toString( ConcRegExp* regexp, bool markSelection ) +{ + QString res; + + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + QString startPar = QString::fromLocal8Bit(""); + QString endPar = QString::fromLocal8Bit(""); + if ( (*it)->precedence() < regexp->precedence() ) { + startPar = QString::fromLatin1( "\\(" ); + endPar = QString::fromLatin1( "\\)" ); + } + + res += startPar + toStr( *it, markSelection ) + endPar; + } + + return res; + +} + +QString EmacsRegExpConverter::toString( LookAheadRegExp* /*regexp*/, bool /*markSelection*/ ) +{ + static bool haveWarned = false; + if ( ! haveWarned ) { + KMessageBox::sorry( 0, i18n("Look ahead regular expressions not supported in Emacs style") ); + haveWarned = true; + } + + return QString::null; +} + +QString EmacsRegExpConverter::toString( TextRangeRegExp* regexp, bool /*markSelection*/ ) +{ + QString txt; + + bool foundCarrot = false; + bool foundDash = false; + bool foundParenthesis = false; + + // print the single characters, but keep "^" as the very + // last element of the characters. + QStringList chars = regexp->chars(); + for (unsigned int i = 0; i< chars.count(); i++) { + if ( *chars.at(i) == QChar(']') ) { + foundParenthesis = true; + } + else if ( *chars.at(i) == QChar('-') ) { + foundDash = true; + } + else if ( *chars.at(i) == QChar('^') ) { + foundCarrot = true; + } + else { + txt.append( *chars.at(i) ); + } + } + + // Now insert the ranges. + QPtrList ranges = regexp->range(); + for ( QPtrListIterator it(ranges); *it; ++it ) { + txt.append((*it)->first()+ QString::fromLatin1("-")+ (*it)->second()); + } + + // Ok, its time to build each part of the regexp, here comes the rule: + // if a ']' is one of the characters, then it must be the first one in the + // list (after then opening '[' and eventually negation '^') + // Next if a '-' is one of the characters, then it must come + // finally if '^' is one of the characters, then it must not be the first + // one! + + QString res = QString::fromLatin1("["); + + if ( regexp->negate() ) + res.append(QString::fromLatin1("^")); + + + // a ']' must be the first character in teh range. + if ( foundParenthesis ) { + res.append(QString::fromLatin1("]")); + } + + // a '-' must be the first character ( only coming after a ']') + if ( foundDash ) { + res.append(QString::fromLatin1("-")); + } + + res += txt; + + // Insert equivalents to \s,\S,\d,\D,\w, and \W + // non-digit, non-space, and non-word is not supported in Emacs style + if ( regexp->digit() ) + res += QString::fromLocal8Bit("0-9"); + if ( regexp->space() ) + res += QString::fromLocal8Bit(" ") + QString( QChar( (char) 9 ) ); // Tab char + if ( regexp->wordChar() ) + res += QString::fromLocal8Bit("a-zA-Z"); + + if ( foundCarrot ) { + res.append( QChar( '^' ) ); + } + + res.append(QString::fromLatin1("]")); + + return res; +} + +QString EmacsRegExpConverter::toString( CompoundRegExp* regexp, bool markSelection ) +{ + return toStr( regexp->child(), markSelection ); +} + +QString EmacsRegExpConverter::toString( DotRegExp* /*regexp*/, bool /*markSelection*/ ) +{ + return QString::fromLatin1( "." ); +} + +QString EmacsRegExpConverter::toString( PositionRegExp* regexp, bool /*markSelection*/ ) +{ + static bool haveWarned = false; + switch ( regexp->position()) { + case PositionRegExp::BEGLINE: + return QString::fromLatin1("^"); + case PositionRegExp::ENDLINE: + return QString::fromLatin1("$"); + case PositionRegExp::WORDBOUNDARY: + case PositionRegExp::NONWORDBOUNDARY: + if ( ! haveWarned ) { + KMessageBox::sorry( 0, i18n( "Word boundary and non word boundary is not supported in Emacs syntax" ) ); + haveWarned = true; + return QString::fromLatin1(""); + } + } + return QString::fromLatin1(""); +} + +QString EmacsRegExpConverter::toString( RepeatRegExp* regexp, bool markSelection ) +{ + RegExp* child = regexp->child(); + QString cText = toStr( child, markSelection ); + QString startPar; + QString endPar; + + if ( child->precedence() < regexp->precedence() ) { + startPar = QString::fromLatin1( "\\(" ); + endPar = QString::fromLatin1( "\\)" ); + } + + if (regexp->min() == 0 && regexp->max() == -1) { + return startPar + cText +endPar + QString::fromLocal8Bit("*"); + } + else if ( regexp->min() == 0 && regexp->max() == 1 ) { + return startPar + cText + endPar + QString::fromLocal8Bit("?"); + } + else if ( regexp->min() == 1 && regexp->max() == -1 ) { + return startPar + cText + endPar + QString::fromLocal8Bit("+"); + } + else { + QString res = QString::fromLatin1(""); + for ( int i = 0; i < regexp->min(); ++i ) { + res += QString::fromLatin1( "\\(" ) + cText + QString::fromLatin1( "\\)" ); + } + if ( regexp->max() != -1 ) { + for ( int i = regexp->min(); i < regexp->max(); ++i ) { + res += QString::fromLatin1("\\(") + cText + QString::fromLatin1("\\)?"); + } + } + else + res += QString::fromLatin1("+"); + + return res; + } +} + +QString EmacsRegExpConverter::toString( TextRegExp* regexp, bool /*markSelection*/ ) +{ + QValueList list; + list << QChar('$') + << QChar('^') + << QChar('.') + << QChar('*') + << QChar('+') + << QChar('?') + << QChar('[') + << QChar(']') + << QChar('\\'); + + QString res = escape( regexp->text(), list, QChar('\\') ); + return res; +} + +QString EmacsRegExpConverter::name() +{ + return QString::fromLatin1( "Emacs" ); +} + +int EmacsRegExpConverter::features() +{ + return WordStart | WordEnd; +} diff --git a/kregexpeditor/emacsregexpconverter.h b/kregexpeditor/emacsregexpconverter.h new file mode 100644 index 0000000..bbc9e94 --- /dev/null +++ b/kregexpeditor/emacsregexpconverter.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef EMACSREGEXPCONVERTER_H +#define EMACSREGEXPCONVERTER_H + +#include "regexpconverter.h" + +class EmacsRegExpConverter :public RegExpConverter +{ +public: + virtual bool canParse(); + virtual QString name(); + virtual int features(); + virtual QString toString( AltnRegExp*, bool markSelection ); + virtual QString toString( ConcRegExp*, bool markSelection ); + virtual QString toString( LookAheadRegExp*, bool markSelection ); + virtual QString toString( TextRangeRegExp*, bool markSelection ); + virtual QString toString( CompoundRegExp*, bool markSelection ); + virtual QString toString( DotRegExp*, bool markSelection ); + virtual QString toString( PositionRegExp*, bool markSelection ); + virtual QString toString( RepeatRegExp*, bool markSelection ); + virtual QString toString( TextRegExp*, bool markSelection ); +}; + + +#endif /* EMACSREGEXPCONVERTER_H */ + diff --git a/kregexpeditor/errormap.cpp b/kregexpeditor/errormap.cpp new file mode 100644 index 0000000..c452ddb --- /dev/null +++ b/kregexpeditor/errormap.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include +#endif + +#include "errormap.h" + +ErrorMap::ErrorMap() : _prevLineStartError( false ), _prevLineEndError( false ), _prevLookAHeadError( false ) +{ +} + +void ErrorMap::start() +{ + _lineStartError = false; + _lineEndError = false; + _lookAHeadError = false; +} + +void ErrorMap::end() +{ + _prevLineStartError = _lineStartError; + _prevLineEndError = _lineEndError; + _prevLookAHeadError = _lookAHeadError; +} + +void ErrorMap::lineStartError() +{ + if ( ! _prevLineStartError ) { + KMessageBox::information( 0, i18n("Your regular expression is invalid, due to something preceding a 'line start'."), + i18n("Regular Expression Error"), QString::fromLatin1("KRegExpEditorLineStartError") ); + } + _lineStartError = true; +} + +void ErrorMap::lineEndError() +{ + if ( !_prevLineEndError ) { + KMessageBox::information( 0, i18n("Your regular expression is invalid, due to something following a 'line end'."), + i18n("Regular Expression Error"), QString::fromLatin1("KRegExpEditorLineEndError") ); + } + _lineEndError = true; +} + + +void ErrorMap::lookAheadError() +{ + if ( !_prevLookAHeadError ) { + KMessageBox::information( 0, i18n("Your regular expression is invalid. 'Look Ahead' regular expression must be the last sub expression."), + i18n("Regular Expression Error"), QString::fromLatin1("KRegExpEditorLookAHeadError") ); + } + _lookAHeadError = true; +} + diff --git a/kregexpeditor/errormap.h b/kregexpeditor/errormap.h new file mode 100644 index 0000000..88034dd --- /dev/null +++ b/kregexpeditor/errormap.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef ERRORMAP_H +#define ERRORMAP_H + +class ErrorMap +{ +public: + ErrorMap(); + void start(); + void end(); + void lineStartError(); + void lineEndError(); + void lookAheadError(); +private: + bool _lineStartError, _prevLineStartError; + bool _lineEndError, _prevLineEndError; + bool _lookAHeadError, _prevLookAHeadError; +}; + +#endif diff --git a/kregexpeditor/extractrc-from-regexp b/kregexpeditor/extractrc-from-regexp new file mode 100755 index 0000000..70c30ad --- /dev/null +++ b/kregexpeditor/extractrc-from-regexp @@ -0,0 +1,85 @@ +#! /usr/bin/perl +# This file is a modified version of extractrc, with the only addition that it Title|Description in the textstring regexp. +# +# This script extracts messages from designer (.ui) and XMLGIU (.rc) files +# and writes on standard output (usually redirected to rc.cpp) +# the equivalent i18n() calls so that xgettext can parse them. + +$filename = ""; +@filenames = (); + +sub writeoutstring($) +{ + print STDOUT "i18n(\"@_[0]\"); // $filename \n"; +} + +while (defined ($ARGV[0])) +{ + $_ = shift; + $filename = $_; # maybe check for options + +if (! $filename) { + print STDERR "no file to open\n"; + exit 1; +} + +$string = ""; +$intext = 0; +$linenr = 0; +$inskippedprop = 0; + +open(FILE, $filename); + +READING: while ( ) { + $linenr++; + if ($linenr == 1 && ($_ !~ /^'; + + # The 'database' property contains strings that shouldn't be translated + if ($inskippedprop == 0 && ($string =~ //g; + $text =~ s/&/&/g; + $text =~ s/\"/\\\"/g; + writeoutstring($text); + $string =~ s/^.*<\/$textstring//; + $intext = 0; + # Text can be multiline in .ui files (possibly), but we warn about it in XMLGUI .rc files. + if ($linenr != $starting_linenr && $filename =~ m/\.rc$/) { + print STDERR "there is floating $filename\n"; + } + } + +} + +if ($intext == 1) { + print STDERR "parsing error in $filename $linenr\n"; + exit 1; +} + +} diff --git a/kregexpeditor/gen_qregexplexer.cpp b/kregexpeditor/gen_qregexplexer.cpp new file mode 100644 index 0000000..30f2284 --- /dev/null +++ b/kregexpeditor/gen_qregexplexer.cpp @@ -0,0 +1,1980 @@ +#define yy_create_buffer qregexp_create_buffer +#define yy_delete_buffer qregexp_delete_buffer +#define yy_scan_buffer qregexp_scan_buffer +#define yy_scan_string qregexp_scan_string +#define yy_scan_bytes qregexp_scan_bytes +#define yy_flex_debug qregexp_flex_debug +#define yy_init_buffer qregexp_init_buffer +#define yy_flush_buffer qregexp_flush_buffer +#define yy_load_buffer_state qregexp_load_buffer_state +#define yy_switch_to_buffer qregexp_switch_to_buffer +#define yyin qregexpin +#define yyleng qregexpleng +#define yylex qregexplex +#define yyout qregexpout +#define yyrestart qregexprestart +#define yytext qregexptext + +#line 19 "gen_qregexplexer.cpp" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define yywrap() 1 +#define YY_SKIP_YYWRAP +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 29 +#define YY_END_OF_BUFFER 30 +static yyconst short int yy_accept[53] = + { 0, + 0, 0, 30, 28, 29, 13, 18, 19, 21, 23, + 12, 22, 28, 28, 14, 28, 20, 0, 0, 25, + 0, 27, 27, 26, 2, 4, 6, 8, 9, 1, + 3, 5, 7, 27, 0, 0, 24, 17, 15, 16, + 25, 11, 26, 10, 0, 11, 10, 11, 10, 11, + 10, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 1, 1, 4, 1, 1, 1, 5, + 6, 7, 8, 9, 1, 10, 1, 11, 12, 12, + 12, 12, 12, 12, 12, 13, 13, 14, 1, 1, + 15, 1, 16, 1, 17, 18, 17, 19, 17, 17, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 20, 1, 1, 1, 21, 1, 1, 1, + 22, 23, 24, 25, 1, 1, 26, 27, 17, 28, + + 17, 26, 1, 1, 1, 1, 1, 1, 1, 29, + 1, 1, 1, 29, 30, 29, 1, 29, 31, 32, + 1, 1, 33, 34, 35, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[36] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst short int yy_base[59] = + { 0, + 0, 33, 53, 137, 137, 137, 32, 137, 137, 137, + 137, 137, 2, 67, 137, 19, 137, 0, 20, 18, + 12, 137, 0, 6, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 0, 34, 94, 137, 137, 137, 137, + 137, 9, 39, 0, 97, 48, 0, 50, 0, 137, + 137, 137, 132, 134, 27, 22, 11, 7 + } ; + +static yyconst short int yy_def[59] = + { 0, + 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 54, 52, 52, 52, 52, 52, 54, 54, + 54, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 55, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 56, 52, 52, 57, 52, 58, 52, + 52, 0, 52, 52, 52, 52, 52, 52 + } ; + +static yyconst short int yy_nxt[173] = + { 0, + 52, 5, 38, 6, 7, 8, 9, 10, 51, 11, + 42, 42, 49, 39, 40, 12, 43, 43, 43, 46, + 46, 13, 14, 47, 15, 20, 21, 35, 44, 36, + 36, 36, 16, 17, 5, 20, 6, 7, 8, 9, + 10, 41, 11, 41, 45, 45, 45, 18, 12, 43, + 43, 43, 52, 37, 13, 14, 52, 15, 48, 48, + 50, 50, 52, 52, 52, 16, 17, 22, 37, 22, + 22, 22, 22, 22, 22, 22, 22, 23, 24, 24, + 22, 22, 22, 22, 25, 26, 27, 28, 22, 22, + 22, 22, 29, 30, 31, 29, 32, 33, 34, 22, + + 22, 22, 35, 52, 36, 36, 36, 45, 45, 45, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 37, 52, + 52, 37, 4, 4, 19, 19, 3, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52 + } ; + +static yyconst short int yy_chk[173] = + { 0, + 0, 1, 18, 1, 1, 1, 1, 1, 58, 1, + 23, 23, 57, 18, 18, 1, 24, 24, 24, 42, + 42, 1, 1, 56, 1, 13, 13, 16, 55, 16, + 16, 16, 1, 1, 2, 21, 2, 2, 2, 2, + 2, 20, 2, 19, 35, 35, 35, 7, 2, 43, + 43, 43, 3, 16, 2, 2, 0, 2, 46, 46, + 48, 48, 0, 0, 0, 2, 2, 14, 35, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + + 14, 14, 36, 0, 36, 36, 36, 45, 45, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, + 0, 45, 53, 53, 54, 54, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "qregexpparser.l" +#define INITIAL 0 +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#line 21 "qregexpparser.l" + #include + #include "textrangeregexp.h" + #include "gen_qregexpparser.hh" +#ifdef QT_ONLY + #include "compat.h" +#endif + void parseRange( char* txt, int* min, int* max ); + RegExp* parseCharClass( char* match ); +#line 464 "gen_qregexplexer.cpp" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 38 "qregexpparser.l" + +#line 617 "gen_qregexplexer.cpp" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 53 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 137 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 39 "qregexpparser.l" +return TOK_PosWordChar; + YY_BREAK +case 2: +YY_RULE_SETUP +#line 40 "qregexpparser.l" +return TOK_PosNonWordChar; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 41 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setDigit( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 47 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonDigit( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 53 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setSpace( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 59 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonSpace( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 65 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setWordChar( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 71 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonWordChar( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 77 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit( yytext ) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 84 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit(yytext) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 90 "qregexpparser.l" +{ + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit(yytext) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 96 "qregexpparser.l" +return TOK_Dot; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 97 "qregexpparser.l" +return TOK_Dollar; + YY_BREAK +case 14: +YY_RULE_SETUP +#line 98 "qregexpparser.l" +return TOK_Carat; + YY_BREAK +case 15: +YY_RULE_SETUP +#line 99 "qregexpparser.l" +return TOK_MagicLeftParent; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 100 "qregexpparser.l" +return TOK_PosLookAhead; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 101 "qregexpparser.l" +return TOK_NegLookAhead; + YY_BREAK +case 18: +YY_RULE_SETUP +#line 102 "qregexpparser.l" +return TOK_LeftParen; + YY_BREAK +case 19: +YY_RULE_SETUP +#line 103 "qregexpparser.l" +return TOK_RightParent; + YY_BREAK +case 20: +YY_RULE_SETUP +#line 104 "qregexpparser.l" +return TOK_Bar; + YY_BREAK +case 21: +YY_RULE_SETUP +#line 105 "qregexpparser.l" +{ qregexplval.range.min = 0; qregexplval.range.max=-1; return TOK_Quantifier; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 106 "qregexpparser.l" +{ qregexplval.range.min = 0; qregexplval.range.max=1; return TOK_Quantifier; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 107 "qregexpparser.l" +{ qregexplval.range.min = 1; qregexplval.range.max=-1; return TOK_Quantifier; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 108 "qregexpparser.l" +{ parseRange( yytext, &qregexplval.range.min, &qregexplval.range.max ); return TOK_Quantifier; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 109 "qregexpparser.l" +{ qregexplval.regexp = parseCharClass(yytext); return TOK_CharClass; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 110 "qregexpparser.l" +{ qregexplval.backRef = atoi( yytext+1 ); return TOK_BackRef; } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 111 "qregexpparser.l" +{ qregexplval.ch = yytext[1]; return TOK_EscapeChar; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 112 "qregexpparser.l" +{ qregexplval.ch = yytext[0]; return TOK_Char; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 114 "qregexpparser.l" +ECHO; + YY_BREAK +#line 890 "gen_qregexplexer.cpp" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 53 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 53 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 52); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +#include +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 114 "qregexpparser.l" + + +void setParseData( QString qstr ) { + const char* cstr; + if ( qstr.isNull() ) + cstr = ""; + else + cstr = qstr.latin1(); + yy_switch_to_buffer( yy_scan_string( cstr ) ); +} + +/** + This function parses a range in a form similar to "{3,4}", "{,7}" + etc. and returns the value in the integers pointed to by min and max. +*/ +void parseRange( char* txt, int* min, int* max ) +{ + + /* + case txt min max + 1 {} 0 -1 + 2 {,} 0 -1 + 3 {5} 5 5 + 4 {5,} 5 -1 + 5 {,7} 0 7 + 6 {5,7} 5 7 + */ + char c; + int i = 1; + int minimum=0, maximum=0; + int minFound=0, maxFound=0, commaFound = 0; + + while ( (c = txt[i++]) != ',' && c != '}') { + minimum = minimum*10+ c-'0'; + minFound=1; + } + + if ( c == ',' ) + commaFound = 1; + + if ( c != '}' ) { + while ( (c = txt[i++]) != '}') { + maximum = maximum*10+ c-'0'; + maxFound = 1; + } + } + + *min = minimum; + if ( maxFound ) + *max = maximum; /* case 5,6 */ + else if ( !minFound ) + *max = -1; /* case 1,2 */ + else if ( commaFound ) + *max = -1; /* case 4 */ + else + *max = minimum; /* case 3 */ +} + + +/** + This function parses a character range like "[^ab1-4]". +*/ +RegExp* parseCharClass( char* match ) +{ + TextRangeRegExp* res = new TextRangeRegExp( false ); + QString txt = QString::fromLocal8Bit( match ); + txt = txt.mid(1,txt.length()-2); + + unsigned int i = 0; + QChar ch = txt.at(i++); + QString pendingChar; + QString thisChar; + bool charPending = false; + bool rangePending = false; + bool flushPending = false; + + if ( ch == QChar('^') ) { + res->setNegate( true ); + ch = txt.at(i++); + } + + do { + // If a character is pending, and the next char is '-' then we are + // possible looking at a range. + if ( ch == QChar('-') && charPending ) { + rangePending = true; + ch = txt.at(i++); + continue; + } + + // If we have a pending character, but do not also have a pending + // range, then the pending character was not part of a range, and + // should therefore just be added as a single character. + if ( charPending && !rangePending ) { + res->addCharacter( pendingChar ); + charPending = false; + } + + if ( ch == QChar('\\') ) { + // Handle the cases where an escape character is specified. + ch = txt.at(i++); + + if ( ch == QChar('a') || ch == QChar('f') || ch == QChar('n') || ch == QChar('r') || ch == QChar('t') || ch == QChar('v') ) { + // These are just seen as normal characters. + thisChar = QString::fromLocal8Bit("\\") + ch; + } + else if ( ch == QChar('d') ) { + // The following characters represent character groups. If any of + // these are seen in a range, then the range is ignored, thus [a-\s] + // matches an 'a', a '-', and a space (\s means space). + res->setDigit( true ); + flushPending = true; + } + else if ( ch == QChar('D') ) { + res->setNonDigit( true ); + flushPending = true; + } + else if ( ch == QChar('s') ) { + res->setSpace( true ); + flushPending = true; + } + else if ( ch == QChar('S') ) { + res->setNonSpace( true ); + flushPending = true; + } + else if ( ch == QChar('w') ) { + res->setWordChar( true ); + flushPending = true; + } + else if ( ch == QChar('W') ) { + res->setNonWordChar( true ); + flushPending = true; + } + else if ( ch == QChar('x') || ch == QChar('X') ) { + // This is a hexidecimal character: \xHHHH + QString str; + for ( int j=0; j<4; j++) { + ch = txt.at(i++); + if ( ch == 'a' || ch == 'A' || ch == 'b' || ch == 'B' || ch == 'c' || ch == 'C' || ch == 'd' || ch == 'D' || + ch == 'e' || ch == 'E' || ch == 'f' || ch == 'F' || + ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || + ch == '8' || ch == '9' ) + str += ch; + else + i--; + } + thisChar = QString::fromLocal8Bit("\\x") + str; + } + else if ( ch == QChar('0') ) { + // This is an octal character + QString str; + for ( int j=0; j<4; j++) { + ch = txt.at(i++); + if ( ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' ) + str += ch; + else + i--; + } + thisChar = QString::fromLocal8Bit("\\x") + str ; + } + else { + // Anything else escaped just means the character itself. + thisChar = ch; + } + } + else { + // A non escaped character. + thisChar = ch; + } + + // The characters \s,\S,\w,\W,\d or \D, can not be part of a range, + // thus if they are meet in what looks like a range, then the + // characters of the range is justed seen as normal non range + // characters. thus [a-\s] matches an 'a', a '-', and a space (\s means + // space). + if ( flushPending ) { + if ( charPending ) + res->addCharacter( pendingChar ); + if ( rangePending ) + res->addCharacter( QString::fromLocal8Bit("-") ); + flushPending = false; + charPending = false; + rangePending = false; + } + else { + if ( rangePending ) { + res->addRange( pendingChar, thisChar ); + charPending = false; + rangePending = false; + } + else { + pendingChar = thisChar; + charPending = true; + } + } + ch = txt.at(i++); + } + while ( ch != QChar(']') && i <= txt.length() ); + + if ( charPending ) + res->addCharacter( pendingChar ); + if ( rangePending ) + res->addCharacter( QString::fromLocal8Bit("-") ); + + return res; +} diff --git a/kregexpeditor/gen_qregexpparser.cc b/kregexpeditor/gen_qregexpparser.cc new file mode 100644 index 0000000..b366293 --- /dev/null +++ b/kregexpeditor/gen_qregexpparser.cc @@ -0,0 +1,1447 @@ +/* A Bison parser, made from qregexpparser.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* If NAME_PREFIX is specified substitute the variables and functions + names. */ +#define yyparse qregexpparse +#define yylex qregexplex +#define yyerror qregexperror +#define yylval qregexplval +#define yychar qregexpchar +#define yydebug qregexpdebug +#define yynerrs qregexpnerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TOK_Dot = 258, + TOK_Dollar = 259, + TOK_Carat = 260, + TOK_MagicLeftParent = 261, + TOK_PosLookAhead = 262, + TOK_NegLookAhead = 263, + TOK_LeftParen = 264, + TOK_RightParent = 265, + TOK_Bar = 266, + TOK_Quantifier = 267, + TOK_BackRef = 268, + TOK_CharClass = 269, + TOK_Char = 270, + TOK_EscapeChar = 271, + TOK_PosWordChar = 272, + TOK_PosNonWordChar = 273 + }; +#endif +#define TOK_Dot 258 +#define TOK_Dollar 259 +#define TOK_Carat 260 +#define TOK_MagicLeftParent 261 +#define TOK_PosLookAhead 262 +#define TOK_NegLookAhead 263 +#define TOK_LeftParen 264 +#define TOK_RightParent 265 +#define TOK_Bar 266 +#define TOK_Quantifier 267 +#define TOK_BackRef 268 +#define TOK_CharClass 269 +#define TOK_Char 270 +#define TOK_EscapeChar 271 +#define TOK_PosWordChar 272 +#define TOK_PosNonWordChar 273 + + + + +/* Copy the first part of user declarations. */ +#line 18 "qregexpparser.y" + +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include +#endif + + #include + #include + + #include "regexp.h" + #include "textregexp.h" + #include "textrangeregexp.h" + #include "repeatregexp.h" + #include "lookaheadregexp.h" + #include "concregexp.h" + #include "altnregexp.h" + #include "positionregexp.h" + #include "dotregexp.h" + #include "compoundregexp.h" + + extern int yylex(); + extern void setParseData( QString str ); + int yyerror (const char *); + void setParseResult( RegExp* ); + RegExp* parseQtRegExp( QString qstr, bool* ok ); + static RegExp* parseResult; + static int _index; + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#ifndef YYSTYPE +#line 49 "qregexpparser.y" +typedef union { + struct { + int min; + int max; + } range; + int backRef; + RegExp* regexp; + char ch; +} yystype; +/* Line 193 of /usr/share/bison/yacc.c. */ +#line 159 "gen_qregexpparser.cc" +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +#ifndef YYLTYPE +typedef struct yyltype +{ + int first_line; + int first_column; + int last_line; + int last_column; +} yyltype; +# define YYLTYPE yyltype +# define YYLTYPE_IS_TRIVIAL 1 +#endif + +/* Copy the second part of user declarations. */ + + +/* Line 213 of /usr/share/bison/yacc.c. */ +#line 180 "gen_qregexpparser.cc" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAX) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 27 +#define YYLAST 47 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 19 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 8 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 27 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 36 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 273 + +#define YYTRANSLATE(X) \ + ((unsigned)(X) <= YYMAXUTOK ? yytranslate[X] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned char yyprhs[] = +{ + 0, 0, 3, 4, 6, 8, 12, 14, 17, 20, + 22, 25, 27, 30, 32, 36, 40, 44, 48, 50, + 52, 54, 56, 58, 60, 62, 64, 66 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 21, 0, -1, -1, 22, -1, 20, -1, 22, 11, + 23, -1, 23, -1, 22, 11, -1, 11, 23, -1, + 11, -1, 23, 24, -1, 24, -1, 25, 12, -1, + 25, -1, 9, 22, 10, -1, 6, 22, 10, -1, + 7, 22, 10, -1, 8, 22, 10, -1, 14, -1, + 26, -1, 4, -1, 5, -1, 3, -1, 13, -1, + 17, -1, 18, -1, 15, -1, 16, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned char yyrline[] = +{ + 0, 80, 80, 82, 83, 86, 96, 97, 107, 112, + 115, 129, 136, 139, 142, 145, 146, 149, 152, 153, + 154, 155, 156, 157, 172, 173, 176, 182 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "TOK_Dot", "TOK_Dollar", "TOK_Carat", + "TOK_MagicLeftParent", "TOK_PosLookAhead", "TOK_NegLookAhead", + "TOK_LeftParen", "TOK_RightParent", "TOK_Bar", "TOK_Quantifier", + "TOK_BackRef", "TOK_CharClass", "TOK_Char", "TOK_EscapeChar", + "TOK_PosWordChar", "TOK_PosNonWordChar", "$accept", "empty", "regexp", + "expression", "term", "factor", "atom", "char", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 19, 20, 21, 21, 22, 22, 22, 22, 22, + 23, 23, 24, 24, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 26, 26 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 0, 1, 1, 3, 1, 2, 2, 1, + 2, 1, 2, 1, 3, 3, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 2, 22, 20, 21, 0, 0, 0, 0, 9, 23, + 18, 26, 27, 24, 25, 4, 0, 3, 6, 11, + 13, 19, 0, 0, 0, 0, 8, 1, 7, 10, + 12, 15, 16, 17, 14, 5 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yysigned_char yydefgoto[] = +{ + -1, 15, 16, 17, 18, 19, 20, 21 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -18 +static const yysigned_char yypact[] = +{ + -1, -18, -18, -18, -1, -1, -1, -1, 18, -18, + -18, -18, -18, -18, -18, -18, 11, 8, 18, -18, + 16, -18, 19, 31, 34, 36, 18, -18, 18, -18, + -18, -18, -18, -18, -18, 18 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yysigned_char yypgoto[] = +{ + -18, -18, -18, 33, -8, -17, -18, -18 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, parse error. */ +#define YYTABLE_NINF -1 +static const unsigned char yytable[] = +{ + 26, 29, 1, 2, 3, 4, 5, 6, 7, 29, + 8, 27, 9, 10, 11, 12, 13, 14, 29, 28, + 35, 1, 2, 3, 4, 5, 6, 7, 30, 31, + 28, 9, 10, 11, 12, 13, 14, 22, 23, 24, + 25, 32, 28, 0, 33, 28, 34, 28 +}; + +static const yysigned_char yycheck[] = +{ + 8, 18, 3, 4, 5, 6, 7, 8, 9, 26, + 11, 0, 13, 14, 15, 16, 17, 18, 35, 11, + 28, 3, 4, 5, 6, 7, 8, 9, 12, 10, + 11, 13, 14, 15, 16, 17, 18, 4, 5, 6, + 7, 10, 11, -1, 10, 11, 10, 11 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 3, 4, 5, 6, 7, 8, 9, 11, 13, + 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, + 25, 26, 22, 22, 22, 22, 23, 0, 11, 24, + 12, 10, 10, 10, 10, 23 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up"); \ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.first_line = Rhs[1].first_line; \ + Current.first_column = Rhs[1].first_column; \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#define YYLEX yylex () + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +#endif /* !YYDEBUG */ + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*-----------------------------. +| Print this symbol on YYOUT. | +`-----------------------------*/ + +static void +#if defined (__STDC__) || defined (__cplusplus) +yysymprint (FILE* yyout, int yytype, YYSTYPE yyvalue) +#else +yysymprint (yyout, yytype, yyvalue) + FILE* yyout; + int yytype; + YYSTYPE yyvalue; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvalue; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyout, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyout, yytoknum[yytype], yyvalue); +# endif + } + else + YYFPRINTF (yyout, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyout, ")"); +} +#endif /* YYDEBUG. */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +#if defined (__STDC__) || defined (__cplusplus) +yydestruct (int yytype, YYSTYPE yyvalue) +#else +yydestruct (yytype, yyvalue) + int yytype; + YYSTYPE yyvalue; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvalue; + + switch (yytype) + { + default: + break; + } +} + + + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +# define YYPARSE_PARAM_DECL +# else +# define YYPARSE_PARAM_ARG YYPARSE_PARAM +# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +# endif +#else /* !YYPARSE_PARAM */ +# define YYPARSE_PARAM_ARG +# define YYPARSE_PARAM_DECL +#endif /* !YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +# ifdef YYPARSE_PARAM +int yyparse (void *); +# else +int yyparse (void); +# endif +#endif + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of parse errors so far. */ +int yynerrs; + + +int +yyparse (YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yychar1 = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + goto yyoverflowlab; + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with. */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more. */ + + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yychar1 = YYTRANSLATE (yychar); + + /* We have to keep this `#if YYDEBUG', since we use variables + which are defined only if `YYDEBUG' is set. */ + YYDPRINTF ((stderr, "Next token is ")); + YYDSYMPRINT ((stderr, yychar1, yylval)); + YYDPRINTF ((stderr, "\n")); + } + + /* If the proper action on seeing token YYCHAR1 is to reduce or to + detect an error, take that action. */ + yyn += yychar1; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %d (%s), ", + yychar, yytname[yychar1])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables which + are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + int yyi; + + YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", + yyn - 1, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyn]; yyrhs[yyi] >= 0; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + switch (yyn) + { + case 3: +#line 82 "qregexpparser.y" + { setParseResult( yyvsp[0].regexp) ; } + break; + + case 4: +#line 83 "qregexpparser.y" + { setParseResult( new ConcRegExp( false ) ); } + break; + + case 5: +#line 86 "qregexpparser.y" + { + if ( dynamic_cast( yyvsp[-2].regexp ) ) { + yyval.regexp = yyvsp[-2].regexp; + } + else { + yyval.regexp = new AltnRegExp( false ); + dynamic_cast( yyval.regexp )->addRegExp( yyvsp[-2].regexp ); + } + dynamic_cast( yyval.regexp )->addRegExp( yyvsp[0].regexp ); + } + break; + + case 6: +#line 96 "qregexpparser.y" + { yyval.regexp = yyvsp[0].regexp; } + break; + + case 7: +#line 97 "qregexpparser.y" + { + if ( dynamic_cast( yyvsp[-1].regexp ) ) { + yyval.regexp = yyvsp[-1].regexp; + } + else { + yyval.regexp = new AltnRegExp( false ); + dynamic_cast( yyval.regexp )->addRegExp( yyvsp[-1].regexp ); + } + dynamic_cast( yyval.regexp )->addRegExp( new TextRegExp( false, QString::fromLatin1("") ) ); + } + break; + + case 8: +#line 107 "qregexpparser.y" + { + yyval.regexp = new AltnRegExp( false ); + dynamic_cast( yyval.regexp )->addRegExp( new TextRegExp( false, QString::fromLatin1("") ) ); + dynamic_cast( yyval.regexp )->addRegExp( yyvsp[0].regexp ); + } + break; + + case 9: +#line 112 "qregexpparser.y" + { yyval.regexp = new AltnRegExp( false ); } + break; + + case 10: +#line 115 "qregexpparser.y" + { + RegExp* last = dynamic_cast( yyvsp[-1].regexp )->lastRegExp(); + TextRegExp *reg1, *reg2; + + if ( last && ( reg1 = dynamic_cast( last ) ) && + ( reg2 = dynamic_cast( yyvsp[0].regexp ) ) ) { + reg1->append( reg2->text() ); + delete reg2; + } + else { + dynamic_cast(yyval.regexp)->addRegExp( yyvsp[0].regexp ); + } + yyval.regexp = yyvsp[-1].regexp; + } + break; + + case 11: +#line 129 "qregexpparser.y" + { + ConcRegExp* reg = new ConcRegExp( false ); + reg->addRegExp( yyvsp[0].regexp ); + yyval.regexp = reg; + } + break; + + case 12: +#line 136 "qregexpparser.y" + { + yyval.regexp = new RepeatRegExp( false, yyvsp[0].range.min, yyvsp[0].range.max, yyvsp[-1].regexp ); + } + break; + + case 13: +#line 139 "qregexpparser.y" + { yyval.regexp = yyvsp[0].regexp; } + break; + + case 14: +#line 142 "qregexpparser.y" + { + yyval.regexp = yyvsp[-1].regexp; + } + break; + + case 15: +#line 145 "qregexpparser.y" + { yyval.regexp = yyvsp[-1].regexp; } + break; + + case 16: +#line 146 "qregexpparser.y" + { + yyval.regexp = new LookAheadRegExp( false, LookAheadRegExp::POSITIVE, yyvsp[-1].regexp ); + } + break; + + case 17: +#line 149 "qregexpparser.y" + { + yyval.regexp = new LookAheadRegExp( false, LookAheadRegExp::NEGATIVE, yyvsp[-1].regexp ); + } + break; + + case 18: +#line 152 "qregexpparser.y" + { yyval.regexp = yyvsp[0].regexp; } + break; + + case 19: +#line 153 "qregexpparser.y" + { yyval.regexp = yyvsp[0].regexp; } + break; + + case 20: +#line 154 "qregexpparser.y" + { yyval.regexp = new PositionRegExp( false, PositionRegExp::ENDLINE ); } + break; + + case 21: +#line 155 "qregexpparser.y" + { yyval.regexp = new PositionRegExp( false, PositionRegExp::BEGLINE ); } + break; + + case 22: +#line 156 "qregexpparser.y" + { yyval.regexp = new DotRegExp( false ); } + break; + + case 23: +#line 157 "qregexpparser.y" + { + QString match = QString::fromLocal8Bit("\\%1").arg( yyvsp[0].backRef ); + yyval.regexp = new TextRegExp( false, match ); + KMessageBox::information(0,i18n("Back reference regular expressions are not supported.

" + "\\1, \\2, ... are back references, meaning they refer to " + "previous matches. " + "Unfortunately this is not supported in the current version of this editor.

" + "In the graphical area the text %1 has been inserted. This is however " + "just a workaround to ensure that the application handles the regexp at all. " + "Therefore, as soon as you edit the regular expression in the graphical area, " + "the back reference will be replaced by matching the text %2 literally.") + .arg( match ).arg( match ), + i18n("Back reference regular expressions not supported"), + QString::fromLocal8Bit("backReferenceNotSupported") ); + } + break; + + case 24: +#line 172 "qregexpparser.y" + { yyval.regexp = new PositionRegExp( false, PositionRegExp::WORDBOUNDARY ); } + break; + + case 25: +#line 173 "qregexpparser.y" + { yyval.regexp = new PositionRegExp( false, PositionRegExp::NONWORDBOUNDARY ); } + break; + + case 26: +#line 176 "qregexpparser.y" + { + if ( yyvsp[0].ch == '{' || yyvsp[0].ch == '}' || yyvsp[0].ch == '[' || yyvsp[0].ch == ']' || yyvsp[0].ch == '\\' ) { + yyerror( "illigal character - needs escaping" ); + } + yyval.regexp = new TextRegExp( false, QString::fromLocal8Bit("%1").arg(yyvsp[0].ch)); + } + break; + + case 27: +#line 182 "qregexpparser.y" + { yyval.regexp = new TextRegExp( false, QString::fromLocal8Bit("%1").arg(yyvsp[0].ch)); } + break; + + + } + +/* Line 1016 of /usr/share/bison/yacc.c. */ +#line 1209 "gen_qregexpparser.cc" + + yyvsp -= yylen; + yyssp -= yylen; + + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen (yytname[yytype]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("parse error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror ("parse error"); + } + goto yyerrlab1; + + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* Return failure if at end of input. */ + if (yychar == YYEOF) + { + /* Pop the error token. */ + YYPOPSTACK; + /* Pop the rest of the stack. */ + while (yyssp > yyss) + { + YYDPRINTF ((stderr, "Error: popping ")); + YYDSYMPRINT ((stderr, + yystos[*yyssp], + *yyvsp)); + YYDPRINTF ((stderr, "\n")); + yydestruct (yystos[*yyssp], *yyvsp); + YYPOPSTACK; + } + YYABORT; + } + + YYDPRINTF ((stderr, "Discarding token %d (%s).\n", + yychar, yytname[yychar1])); + yydestruct (yychar1, yylval); + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + YYDPRINTF ((stderr, "Error: popping ")); + YYDSYMPRINT ((stderr, + yystos[*yyssp], *yyvsp)); + YYDPRINTF ((stderr, "\n")); + + yydestruct (yystos[yystate], *yyvsp); + yyvsp--; + yystate = *--yyssp; + + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "Error: state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + } + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; + + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 185 "qregexpparser.y" + + +RegExp* parseQtRegExp( QString qstr, bool* ok ) { + _index = 0; + parseResult = 0; + setParseData( qstr ); + yyparse(); + *ok = ( yynerrs == 0 ); + return parseResult; +} + +void setParseResult( RegExp* regexp ) { + parseResult = regexp; +} + +int yyerror(const char *) { + yynerrs++; + return 0; +} + diff --git a/kregexpeditor/gen_qregexpparser.hh b/kregexpeditor/gen_qregexpparser.hh new file mode 100644 index 0000000..19b2558 --- /dev/null +++ b/kregexpeditor/gen_qregexpparser.hh @@ -0,0 +1,93 @@ +/* A Bison parser, made from qregexpparser.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef BISON_GEN_QREGEXPPARSER_HH +# define BISON_GEN_QREGEXPPARSER_HH + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TOK_Dot = 258, + TOK_Dollar = 259, + TOK_Carat = 260, + TOK_MagicLeftParent = 261, + TOK_PosLookAhead = 262, + TOK_NegLookAhead = 263, + TOK_LeftParen = 264, + TOK_RightParent = 265, + TOK_Bar = 266, + TOK_Quantifier = 267, + TOK_BackRef = 268, + TOK_CharClass = 269, + TOK_Char = 270, + TOK_EscapeChar = 271, + TOK_PosWordChar = 272, + TOK_PosNonWordChar = 273 + }; +#endif +#define TOK_Dot 258 +#define TOK_Dollar 259 +#define TOK_Carat 260 +#define TOK_MagicLeftParent 261 +#define TOK_PosLookAhead 262 +#define TOK_NegLookAhead 263 +#define TOK_LeftParen 264 +#define TOK_RightParent 265 +#define TOK_Bar 266 +#define TOK_Quantifier 267 +#define TOK_BackRef 268 +#define TOK_CharClass 269 +#define TOK_Char 270 +#define TOK_EscapeChar 271 +#define TOK_PosWordChar 272 +#define TOK_PosNonWordChar 273 + + + + +#ifndef YYSTYPE +#line 49 "qregexpparser.y" +typedef union { + struct { + int min; + int max; + } range; + int backRef; + RegExp* regexp; + char ch; +} yystype; +/* Line 1281 of /usr/share/bison/yacc.c. */ +#line 86 "gen_qregexpparser.hh" +# define YYSTYPE yystype +#endif + +extern YYSTYPE qregexplval; + + +#endif /* not BISON_GEN_QREGEXPPARSER_HH */ + diff --git a/kregexpeditor/hi128-app-kregexpeditor.png b/kregexpeditor/hi128-app-kregexpeditor.png new file mode 100644 index 0000000..e1ea769 Binary files /dev/null and b/kregexpeditor/hi128-app-kregexpeditor.png differ diff --git a/kregexpeditor/hi16-app-kregexpeditor.png b/kregexpeditor/hi16-app-kregexpeditor.png new file mode 100644 index 0000000..86f7882 Binary files /dev/null and b/kregexpeditor/hi16-app-kregexpeditor.png differ diff --git a/kregexpeditor/hi22-app-kregexpeditor.png b/kregexpeditor/hi22-app-kregexpeditor.png new file mode 100644 index 0000000..11a7991 Binary files /dev/null and b/kregexpeditor/hi22-app-kregexpeditor.png differ diff --git a/kregexpeditor/hi32-app-kregexpeditor.png b/kregexpeditor/hi32-app-kregexpeditor.png new file mode 100644 index 0000000..af0f3f7 Binary files /dev/null and b/kregexpeditor/hi32-app-kregexpeditor.png differ diff --git a/kregexpeditor/hi48-app-kregexpeditor.png b/kregexpeditor/hi48-app-kregexpeditor.png new file mode 100644 index 0000000..fc589c9 Binary files /dev/null and b/kregexpeditor/hi48-app-kregexpeditor.png differ diff --git a/kregexpeditor/hi64-app-kregexpeditor.png b/kregexpeditor/hi64-app-kregexpeditor.png new file mode 100644 index 0000000..81013f9 Binary files /dev/null and b/kregexpeditor/hi64-app-kregexpeditor.png differ diff --git a/kregexpeditor/infopage.cpp b/kregexpeditor/infopage.cpp new file mode 100644 index 0000000..8f373c5 --- /dev/null +++ b/kregexpeditor/infopage.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include +#endif + +#include "infopage.h" + +InfoPage::InfoPage( QWidget* parent, const char* name ) + :KTextBrowser( parent, name ) +{ + QString txt = + QString::fromLatin1( "" ) + + i18n( "Translators, feel free to add yourself in the text below, asking for a postcard ;-), " + "also feel free to add a section saying

Translators

. " + "Kind regards, and thanks for your work - Jesper.", + "

Regular Expression Editor

" + "

What you are currently looking at is an editor for Regular Expressions.

" + "

The upper part in the middle is the editing area, the lower part is a verification window where you can " + "try your regular expressions right away. The row of buttons is the editing actions. " + "This is actually very similar to common drawing programs. Select an editing tool to start " + "editing your regular expression, and press the mouse button in the editing area where you want " + "this item inserted.

" + "

For a more detailed description of this editor see the info pages

" + + "

What is a regular expression?

" + "If you do not know what a regular expression is, then it might be a good idea " + "to read the introduction to regular expressions.

"); + +#ifdef HOUSEOFFUSION + txt += tr("

House Of Fusion note

" + "If you want to donate money to continue development on the KRegExpEditor port for " + "house of fusion then please contact Michael Dinowitz (mdinowit@houseoffusion.com)."); +#endif + txt += i18n( "

Send the author an electronic postcard

" + "I don't get any money for working on KRegExpEditor, " + "I therefore appreciate it very much when users tell me what they think about my work. " + "I would therefore be very happy if you " + "sent me a short mail, telling me that you use my regular expression editor." + + "

Author

" + "Jesper K. Pedersen <blackie@kde.org>") + + QString::fromLatin1( "
" ); + setText( txt ); +} + +void InfoPage::setSource ( const QString& name ) +{ +#ifdef QT_ONLY + mimeSourceFactory()->setFilePath( QStringList() << QString::fromLatin1("manual/")); + QString nm = name; + if ( nm.endsWith("/") ) + nm = nm.left( nm.length()-1); + + if ( nm.startsWith("mailto:") ) { + QMessageBox::information( this, tr("Support mail"), tr("Please send the mail to blackie@kde.org") ); + return; + } + if ( nm.startsWith( "http:" ) ) + return; + + + if ( nm == "doc://" ) + nm = "doc://index"; + + if ( nm.startsWith( QString::fromLocal8Bit("doc://") ) ) { + nm = nm.mid(6) + ".html"; + } + + QTextBrowser::setSource( nm ); +#else + if ( name.startsWith( QString::fromLocal8Bit("doc://") ) ) { + kapp->invokeHelp( name.mid(6, name.length()-7), QString::fromLocal8Bit("KRegExpEditor") ); + } + else { + KTextBrowser::setSource( name ); // handle mailto and other links + } +#endif +} diff --git a/kregexpeditor/infopage.h b/kregexpeditor/infopage.h new file mode 100644 index 0000000..b518979 --- /dev/null +++ b/kregexpeditor/infopage.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef infopage_h +#define infopage_h + +#ifdef QT_ONLY + #include "compat.h" + #include +#else + # include +#endif + +class InfoPage :public KTextBrowser +{ +public: + InfoPage( QWidget* parent, const char* name ); + virtual void setSource ( const QString& name ); +}; + + + +#endif diff --git a/kregexpeditor/kregexpeditor.desktop b/kregexpeditor/kregexpeditor.desktop new file mode 100644 index 0000000..ebffee5 --- /dev/null +++ b/kregexpeditor/kregexpeditor.desktop @@ -0,0 +1,76 @@ +[Desktop Entry] +Name=KRegExpEditor +Name[cs]=Editor regulárních výrazů +Name[et]=Regulaaravaldiste redaktor +Name[fa]=KRegExp ویرایشگر +Name[hi]=के-रेग-एक्सप-एडीटर +Name[pa]=KRegExp ਸੰਪਾਦਕ +Name[pl]=Edytor wyrażeń regularnych +Name[sv]=Kregexpeditor +Name[ta]= KRegExp தொகுப்பி +Name[tg]=KМуҳаррири Ифодаҳои Муқаррарӣ +Name[wa]=Aspougneu d' erîlêyès ratourneures +Name[zh_TW]=正規表示式編輯器 +Exec=kregexpeditor +DocPath=KRegExpEditor/index.html +GenericName=Regular Expression Editor +GenericName[ar]=محرّر التعابير النظامية +GenericName[bg]=Редактор на регулярни изрази +GenericName[br]=Aozer an troiennoù reolataet +GenericName[bs]=Editor regularnih izraza +GenericName[ca]=Editor d'expressions regulars +GenericName[cs]=Editor regulárních výrazů +GenericName[cy]=Golygydd Mynegiadau Rheolaidd +GenericName[da]=Editor for regulære udtryk +GenericName[de]=Editor für reguläre Ausdrücke +GenericName[el]=Επεξεργαστής κανονικών εκφράσεων +GenericName[eo]=Redaktilo por regulesprimoj +GenericName[es]=Editor de expresiones regulares +GenericName[et]=Regulaaravaldiste redaktor +GenericName[eu]=Adierazpen Erregularren Editorea +GenericName[fa]=ویرایشگر عبارت منظم +GenericName[fi]=Säännöllisten lausekkeiden muokkain +GenericName[fr]=Éditeur d'expressions régulières +GenericName[ga]=Eagarthóir Sloinn Ionadaíochta +GenericName[he]=עורך ביטויים רגולריים +GenericName[hi]=रेगुलर एक्सप्रेशन संपादक +GenericName[hu]=Kifejezésszerkesztő +GenericName[is]=Ritill fyrir reglulegar segðir +GenericName[it]=Editor di espressioni regolari +GenericName[ja]=正規表現エディタ +GenericName[ka]=მარტივი გამოსახულების რედაქტორი +GenericName[kk]=Үлгі өрнегінің редакторы +GenericName[km]=កម្មវិធី​និពន្ធ​កន្សោម​ធម្មតា +GenericName[lt]=Įprastųjų išraiškų redaktorius +GenericName[mk]=Уредувач на регуларни изрази +GenericName[ms]=Penyunting Ungkapan Nalar (regexp) +GenericName[nb]=Tekstbehandler for regulære uttrykk +GenericName[nds]=Editor för Regulere Utdrück +GenericName[ne]=नियमित अभिव्यक्ति सम्पादक +GenericName[nl]=Editor voor regular expressions +GenericName[nn]=Program for skriving av regulære uttrykk +GenericName[pa]=ਨਿਯਮਤ ਸਮੀਕਰਨ ਸੰਪਾਦਕ +GenericName[pl]=Edytor wyrażeń regularnych +GenericName[pt]=Editor de Expressões Regulares +GenericName[pt_BR]=Editor de Expressões Regulares +GenericName[ro]=Editor de expresii regulate +GenericName[ru]=Редактор регулярных выражений +GenericName[sk]=Editor regulárnych výrazov +GenericName[sl]=Urejevalnik regularnih izrazov +GenericName[sr]=Уређивач регуларних израза +GenericName[sr@Latn]=Uređivač regularnih izraza +GenericName[sv]=Editor för reguljära uttryck +GenericName[ta]=இயல்பான கூற்று தொகுப்பான் +GenericName[tg]=Муҳаррири Ифодаҳои Муқаррарӣ +GenericName[tr]=Tam İfade Düzenleyici +GenericName[uk]=Редактор формальних виразів +GenericName[uz]=Doimiy ifoda tahrirchi +GenericName[uz@cyrillic]=Доимий ифода таҳрирчи +GenericName[wa]=Aspougneu d' erîlêyès ratourneures +GenericName[zh_CN]=正规表达式编辑器 +GenericName[zh_TW]=正規表示式編輯器 +Terminal=false +Type=Application +X-KDE-StartupNotify=true +Categories=Qt;KDE;Utility;X-KDE-More; +Icon=kregexpeditor diff --git a/kregexpeditor/kregexpeditor.svgz b/kregexpeditor/kregexpeditor.svgz new file mode 100644 index 0000000..a91263c Binary files /dev/null and b/kregexpeditor/kregexpeditor.svgz differ diff --git a/kregexpeditor/kregexpeditorfactory.cpp b/kregexpeditor/kregexpeditorfactory.cpp new file mode 100644 index 0000000..bcddd63 --- /dev/null +++ b/kregexpeditor/kregexpeditorfactory.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef QT_ONLY +#include +#include "kregexpeditorgui.h" +typedef K_TYPELIST_2( KRegExpEditorGUI, KRegExpEditorGUIDialog ) Products; +K_EXPORT_COMPONENT_FACTORY( libkregexpeditorgui, + KGenericFactory( "kregexpeditor" ) ) +#endif diff --git a/kregexpeditor/kregexpeditorgui.cpp b/kregexpeditor/kregexpeditorgui.cpp new file mode 100644 index 0000000..e8f8051 --- /dev/null +++ b/kregexpeditor/kregexpeditorgui.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include + #include + #include "kregexpeditorgui.moc" +#endif + +#include "kregexpeditorgui.h" +// #include // DO I need this? +#include +#include "kregexpeditorprivate.h" +#include + +const QString KRegExpEditorGUI::version = QString::fromLocal8Bit("1.0"); + + +KRegExpEditorGUI::KRegExpEditorGUI(QWidget *parent, const char *name, + const QStringList & ) + : QWidget( parent, name) +{ + QHBoxLayout* layout = new QHBoxLayout( this, 6 ); + _editor = new KRegExpEditorPrivate( this, "_editor" ); + layout->addWidget( _editor ); + connect( _editor, SIGNAL( canUndo(bool) ), this, SIGNAL( canUndo(bool) ) ); + connect( _editor, SIGNAL( canRedo(bool) ), this, SIGNAL( canRedo(bool) ) ); + connect( _editor, SIGNAL( changes(bool) ), this, SIGNAL( changes(bool) ) ); +} + +QString KRegExpEditorGUI::regExp() const +{ + return _editor->regexp(); +} + +void KRegExpEditorGUI::redo() +{ + _editor->slotRedo(); +} + +void KRegExpEditorGUI::undo() +{ + _editor->slotUndo(); +} + +void KRegExpEditorGUI::setRegExp( const QString ®exp ) +{ + _editor->slotSetRegexp( regexp ); +} + +KRegExpEditorGUIDialog::KRegExpEditorGUIDialog( QWidget *parent, + const char *name, + const QStringList & ) + : KDialogBase( KDialogBase::Plain, i18n("Regular Expression Editor"), + KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Help, KDialogBase::Ok, + parent, name ? name : "KRegExpDialog" ) +{ + QFrame* frame = plainPage(); + QVBoxLayout* layout = new QVBoxLayout( frame, 6 ); + layout->setAutoAdd( true ); + _editor = new KRegExpEditorGUI( frame ); + + connect( _editor, SIGNAL( canUndo(bool) ), this, SIGNAL( canUndo(bool) ) ); + connect( _editor, SIGNAL( canRedo(bool) ), this, SIGNAL( canRedo(bool) ) ); + connect( _editor, SIGNAL( changes(bool) ), this, SIGNAL( changes(bool) ) ); + resize( 640, 400 ); + + setHelp( QString::null, QString::fromLocal8Bit( "KRegExpEditor" ) ); +#ifdef QT_ONLY + connect( this, SIGNAL( helpClicked() ), _editor, SLOT( showHelp() ) ); +#endif +} + + +QString KRegExpEditorGUIDialog::regExp() const +{ + return _editor->regExp(); +} + +void KRegExpEditorGUIDialog::setRegExp( const QString ®exp ) +{ + _editor->setRegExp( regexp ); +} + +void KRegExpEditorGUIDialog::redo() +{ + _editor->redo(); +} + +void KRegExpEditorGUIDialog::undo() +{ + _editor->undo(); +} + +void KRegExpEditorGUIDialog::doSomething( QString method, void* arguments ) +{ + _editor->doSomething( method, arguments ); +} + +void KRegExpEditorGUI::doSomething( QString method, void* arguments ) +{ + if ( method == QString::fromLatin1( "setCaseSensitive" ) ) { + _editor->setCaseSensitive( (bool) arguments ); + } + else if ( method == QString::fromLatin1("setMinimal") ) { + _editor->setMinimal( (bool) arguments ); + } + else if ( method == QString::fromLatin1("setSyntax") ) { + _editor->setSyntax( *((QString*) arguments) ); + } + else if ( method == QString::fromLatin1("setAllowNonQtSyntax") ) { + _editor->setAllowNonQtSyntax( (bool) arguments ); + } + else { + qFatal( "%s", tr("Method '%1' is not valid!").arg(method).latin1() ); + } +} + +void KRegExpEditorGUIDialog::setMatchText( const QString& txt ) +{ + _editor->setMatchText( txt ); +} + +void KRegExpEditorGUI::setMatchText( const QString& txt ) +{ + _editor->setMatchText( txt ); +} + + +void KRegExpEditorGUI::showHelp() +{ +#ifdef QT_ONLY + _editor->showHelp(); +#else + kapp->invokeHelp( QString::null, QString::fromLocal8Bit( "KRegExpEditor" ) ); +#endif +} + +#ifndef QT_ONLY +typedef K_TYPELIST_2( KRegExpEditorGUI, KRegExpEditorGUIDialog ) Products; +K_EXPORT_COMPONENT_FACTORY( libkregexpeditorgui, + KGenericFactory( "kregexpeditor" ) ) +#endif diff --git a/kregexpeditor/kregexpeditorgui.desktop b/kregexpeditor/kregexpeditorgui.desktop new file mode 100644 index 0000000..23e3896 --- /dev/null +++ b/kregexpeditor/kregexpeditorgui.desktop @@ -0,0 +1,62 @@ +[Desktop Entry] +Type=Service +Name=RegExp Editor Widget +Name[af]=Regexp Redigeerder Gui-element +Name[ar]=أداة محرر التعابير النظامية +Name[az]=Qaydalıİfadə Editor Pəncərəsi +Name[bg]=Редактор на регулярни изрази +Name[ca]=Estri editor RegExp +Name[cs]=Editor regulárních výrazů +Name[cy]=Teclyn Golygydd RegExp +Name[da]=RegExp Editor-kontrol +Name[de]=RegExp-Bedienelement +Name[el]=Γραφικό συστατικό επεξεργασίας κανονικών εκφράσεων +Name[eo]=Redaktilo por regulesprimoj +Name[es]=Ventana de edición RegExp +Name[et]=Regulaaravaldiste redaktori komponent +Name[eu]=RegExp Editore Widgeta +Name[fa]=RegExp عنصر ویرایشگر +Name[fi]=Säännöllisten lauseiden muokkain +Name[fr]=Composant éditeur d'exp. rég. +Name[ga]=Giuirléid Eagarthóireachta Sloinn Ionadaíochta +Name[he]=פריט עורך הביטויים הסדירים +Name[hi]=रेग-एक्सपी संपादक विजेट +Name[hr]=Widget za uređivanje RegExp-a (regularnih izraza) +Name[hu]=Grafikus objektum reguláris kifejezések szerkesztéséhez +Name[it]=Elemento grafico dell'editor di espressioni regolari +Name[ja]=正規表現エディタウィジェット +Name[kk]=Үлгі өрнегінің өңдеу бөлшегі +Name[km]=វត្ថុ​មើល​ឃើញកម្មវិធី​និពន្ធ RegExp +Name[lt]=RegExp redaktoriaus valdiklis +Name[lv]=RegExp Redaktora Widžets +Name[mk]=графичка контрола за уредување RegExp +Name[ms]=Wijet Penyunting RegExp +Name[mt]=Editur ta' RegExp +Name[nb]=Skjermelement RegExp tekstbehandler +Name[nds]=RegExp Editor-Bedeenelement +Name[ne]=RegExp सम्पादक विजेट +Name[nn]=Skjermelement for redigering av regulære uttrykk +Name[pl]=Edytor wyrażeń regularnych +Name[pt]=Item de Edição de Expressões Regulares +Name[pt_BR]=Widget do Editor de Expressões Regulares +Name[ro]=Componentă editare expresii regulate +Name[ru]=Виджет редактора регулярных выражений +Name[sk]=Prvok Editor regulárnych výrazov +Name[sl]=Gradnik urejevalnika RegExp +Name[sr]=Контрола уређивача регуларних израза +Name[sr@Latn]=Kontrola uređivača regularnih izraza +Name[sv]=Grafisk komponent för att redigera reguljära uttryck +Name[ta]= RegExp தொகுப்பான் சாளரம் +Name[tg]=Ҷузъи Муҳаррири Ифодаҳои Муқаррарӣ +Name[th]=คอนโทรลแก้ไข RegExp +Name[tr]=RegExp Düzenleyici Aleti +Name[uk]=Віджет редактору регулярних виразів +Name[ven]=Widget ya musengulusi wa RegExp +Name[wa]=Ahesse aspougneu d' erîlêyès ratourneures +Name[xh]=RegExp Umhleli we Widget +Name[zh_CN]=正则表达式编辑器部件 +Name[zh_TW]=正規表示式編輯小程式 +Name[zu]=RegExp Umhleli we-widget +X-KDE-Library=libkregexpeditorgui +InitialPreference=2 +ServiceTypes=KRegExpEditor/KRegExpEditor diff --git a/kregexpeditor/kregexpeditorgui.h b/kregexpeditor/kregexpeditorgui.h new file mode 100644 index 0000000..6bcd5e6 --- /dev/null +++ b/kregexpeditor/kregexpeditorgui.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef kregexpeditorgui_h +#define kregexpeditorgui_h + +#ifdef QT_ONLY + #include "compat.h" +#else + #include +#endif + +#include + +class KRegExpEditorPrivate; + +/** + Regular Expression Editor. + + @author Jesper Kjr Pedersen + @version 0.1 + **/ +class KDE_EXPORT KRegExpEditorGUI :public QWidget, public KRegExpEditorInterface +{ + Q_OBJECT + Q_PROPERTY( QString regexp READ regExp WRITE setRegExp ) +public: + KRegExpEditorGUI( QWidget *parent, const char *name = 0, + const QStringList & = QStringList() ); + virtual QString regExp() const; + + static const QString version; + +signals: + /** This signal tells whether undo is available. */ + virtual void canRedo( bool ); + virtual void canUndo( bool ); + virtual void changes( bool ); + +public slots: + virtual void redo(); + virtual void undo(); + virtual void setRegExp( const QString ®exp ); + virtual void doSomething( QString method, void* arguments ); + virtual void setMatchText( const QString& ); + void showHelp(); + +private: + KRegExpEditorPrivate* _editor; +}; + +class KDE_EXPORT KRegExpEditorGUIDialog : public KDialogBase, public KRegExpEditorInterface +{ + Q_OBJECT + Q_PROPERTY( QString regexp READ regExp WRITE setRegExp ) +public: + KRegExpEditorGUIDialog( QWidget *parent, const char *name, const QStringList &args ); + + virtual QString regExp() const; + +signals: + /** This signal tells whether undo is available. */ + virtual void canRedo( bool ); + virtual void canUndo( bool ); + virtual void changes( bool ); + +public slots: + virtual void redo(); + virtual void undo(); + virtual void setRegExp( const QString ®exp ); + virtual void doSomething( QString method, void* arguments ); + virtual void setMatchText( const QString& ); + +private: + KRegExpEditorGUI *_editor; +}; + +#endif + diff --git a/kregexpeditor/kregexpeditorprivate.cpp b/kregexpeditor/kregexpeditorprivate.cpp new file mode 100644 index 0000000..b13a655 --- /dev/null +++ b/kregexpeditor/kregexpeditorprivate.cpp @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include + #include + #include + #include "kregexpeditorprivate.moc" +#endif + +#include +#include +#include +#include "kregexpeditorprivate.h" +#include "scrollededitorwindow.h" +#include "regexpbuttons.h" +//#include // What do I need this for? +#include +#include "infopage.h" +#include +#include +#include "userdefinedregexps.h" +#include "auxbuttons.h" +#include +#include +#include "verifier.h" +#include +#include "verifybuttons.h" +#include + +KRegExpEditorPrivate::KRegExpEditorPrivate(QWidget *parent, const char *name) + : QWidget(parent, name), _updating( false ), _autoVerify( true ) +{ + setMinimumSize(730,300); + QDockArea* area = new QDockArea( Horizontal, QDockArea::Normal, this ); + area->setMinimumSize(2,2); + QDockArea* verArea1 = new QDockArea( Vertical, QDockArea::Normal, this ); + verArea1->setMinimumSize(2,2); + QDockArea* verArea2 = new QDockArea( Vertical, QDockArea::Reverse, this ); + verArea2->setMinimumSize(2,2); + + // The DockWindows. + _regExpButtons = new RegExpButtons( area, "KRegExpEditorPrivate::regExpButton" ); + _verifyButtons = new VerifyButtons( area, "KRegExpEditorPrivate::VerifyButtons" ); + _auxButtons = new AuxButtons( area, "KRegExpEditorPrivate::AuxButtons" ); + _userRegExps = new UserDefinedRegExps( verArea1, "KRegExpEditorPrivate::userRegExps" ); + _userRegExps->setResizeEnabled( true ); + QWhatsThis::add( _userRegExps, i18n( "In this window you will find predefined regular expressions. Both regular expressions " + "you have developed and saved, and regular expressions shipped with the system." )); + + // Editor window + _editor = new QSplitter( Vertical, this, "KRegExpEditorPrivate::_editor" ); + + _scrolledEditorWindow = + new RegExpScrolledEditorWindow( _editor, "KRegExpEditorPrivate::_scrolledEditorWindow" ); + QWhatsThis::add( _scrolledEditorWindow, i18n( "In this window you will develop your regular expressions. " + "Select one of the actions from the action buttons above, and click the mouse in this " + "window to insert the given action.")); + + _info = new InfoPage( this, "_info" ); + _verifier = new Verifier( _editor, "KRegExpEditorPrivate::_verifier" ); + connect( _verifier, SIGNAL( textChanged() ), this, SLOT( maybeVerify() ) ); + QWhatsThis::add( _verifier, i18n("Type in some text in this window, and see what the regular expression you have developed matches.

" + "Each second match will be colored in red and each other match will be colored blue, simply so you " + "can distinguish them from each other.

" + "If you select part of the regular expression in the editor window, then this part will be " + "highlighted - This allows you to debug your regular expressions") ); + + _editor->hide(); + _editor->setSizes( QValueList() << _editor->height()/2 << _editor->height()/2 ); + + QVBoxLayout *topLayout = new QVBoxLayout( this, 0, 6, "KRegExpEditorPrivate::topLayout" ); + topLayout->addWidget( area ); + QHBoxLayout* rows = new QHBoxLayout; // I need to cal addLayout explicit to get stretching right. + topLayout->addLayout( rows, 1 ); + + rows->addWidget( verArea1 ); + rows->addWidget( _editor, 1 ); + rows->addWidget( _info, 1 ); + rows->addWidget( verArea2 ); + + // Connect the buttons + connect( _regExpButtons, SIGNAL( clicked( int ) ), _scrolledEditorWindow, SLOT( slotInsertRegExp( int ) ) ); + connect( _regExpButtons, SIGNAL( doSelect() ), _scrolledEditorWindow, SLOT( slotDoSelect() ) ); + connect( _userRegExps, SIGNAL( load( RegExp* ) ), _scrolledEditorWindow, SLOT( slotInsertRegExp( RegExp* ) ) ); + + connect( _regExpButtons, SIGNAL( clicked( int ) ), _userRegExps, SLOT( slotUnSelect() ) ); + connect( _regExpButtons, SIGNAL( doSelect() ), _userRegExps, SLOT( slotUnSelect() ) ); + connect( _userRegExps, SIGNAL( load( RegExp* ) ), _regExpButtons, SLOT( slotUnSelect() ) ); + + connect( _scrolledEditorWindow, SIGNAL( doneEditing() ), _regExpButtons, SLOT( slotSelectNewAction() ) ); + connect( _scrolledEditorWindow, SIGNAL( doneEditing() ), _userRegExps, SLOT( slotSelectNewAction() ) ); + + connect( _regExpButtons, SIGNAL( clicked( int ) ), this, SLOT( slotShowEditor() ) ); + connect( _userRegExps, SIGNAL( load( RegExp* ) ), this, SLOT( slotShowEditor() ) ); + connect( _regExpButtons, SIGNAL( doSelect() ), this, SLOT( slotShowEditor() ) ); + + connect( _scrolledEditorWindow, SIGNAL( savedRegexp() ), _userRegExps, SLOT( slotPopulateUserRegexps() ) ); + + connect( _auxButtons, SIGNAL( undo() ), this, SLOT( slotUndo() ) ); + connect( _auxButtons, SIGNAL( redo() ), this, SLOT( slotRedo() ) ); + connect( _auxButtons, SIGNAL( cut() ), _scrolledEditorWindow, SLOT( slotCut() ) ); + connect( _auxButtons, SIGNAL( copy() ), _scrolledEditorWindow, SLOT( slotCopy() ) ); + connect( _auxButtons, SIGNAL( paste() ), _scrolledEditorWindow, SLOT( slotPaste() ) ); + connect( _auxButtons, SIGNAL( save() ), _scrolledEditorWindow, SLOT( slotSave() ) ); + connect( _verifyButtons, SIGNAL( autoVerify( bool ) ), this, SLOT( setAutoVerify( bool ) ) ); + connect( _verifyButtons, SIGNAL( verify() ), this, SLOT( doVerify() ) ); + connect( _verifyButtons, SIGNAL( changeSyntax( const QString& ) ), this, SLOT( setSyntax( const QString& ) ) ); + + connect( this, SIGNAL( canUndo( bool ) ), _auxButtons, SLOT( slotCanUndo( bool ) ) ); + connect( this, SIGNAL( canRedo( bool ) ), _auxButtons, SLOT( slotCanRedo( bool ) ) ); + connect( _scrolledEditorWindow, SIGNAL( anythingSelected( bool ) ), _auxButtons, SLOT( slotCanCut( bool ) ) ); + connect( _scrolledEditorWindow, SIGNAL( anythingSelected( bool ) ), _auxButtons, SLOT( slotCanCopy( bool ) ) ); + connect( _scrolledEditorWindow, SIGNAL( anythingOnClipboard( bool ) ), _auxButtons, SLOT( slotCanPaste( bool ) ) ); + connect( _scrolledEditorWindow, SIGNAL( canSave( bool ) ), _auxButtons, SLOT( slotCanSave( bool ) ) ); + + connect( _scrolledEditorWindow, SIGNAL( verifyRegExp() ), this, SLOT( maybeVerify() ) ); + + connect( _verifyButtons, SIGNAL( loadVerifyText( const QString& ) ), this, SLOT( setVerifyText( const QString& ) ) ); + + // connect( _verifier, SIGNAL( countChanged( int ) ), _verifyButtons, SLOT( setMatchCount( int ) ) ); + + // Qt anchors do not work for

...
, thefore scrolling to next/prev match + // do not work. Enable this when they work. + // connect( _verifyButtons, SIGNAL( gotoFirst() ), _verifier, SLOT( gotoFirst() ) ); + // connect( _verifyButtons, SIGNAL( gotoPrev() ), _verifier, SLOT( gotoPrev() ) ); + // connect( _verifyButtons, SIGNAL( gotoNext() ), _verifier, SLOT( gotoNext() ) ); + // connect( _verifyButtons, SIGNAL( gotoLast() ), _verifier, SLOT( gotoLast() ) ); + // connect( _verifier, SIGNAL( goForwardPossible( bool ) ), _verifyButtons, SLOT( enableForwardButtons( bool ) ) ); + // connect( _verifier, SIGNAL( goBackwardPossible( bool ) ), _verifyButtons, SLOT( enableBackwardButtons( bool ) ) ); + + _auxButtons->slotCanPaste( false ); + _auxButtons->slotCanCut( false ); + _auxButtons->slotCanCopy( false ); + _auxButtons->slotCanSave( false ); + + + // Line Edit + QHBoxLayout* layout = new QHBoxLayout( topLayout, 6 ); + QLabel* label = new QLabel( i18n("ASCII syntax:"), this ); + layout->addWidget( label ); + clearButton = new QToolButton( this ); + const QString icon( QString::fromLatin1( QApplication::reverseLayout() ? "clear_left" : "locationbar_erase" ) ); + QIconSet clearIcon = SmallIconSet( icon ); + clearButton->setIconSet( clearIcon ); + layout->addWidget( clearButton ); + QToolTip::add( clearButton, i18n("Clear expression") ); + _regexpEdit = new QLineEdit( this ); + layout->addWidget( _regexpEdit ); + QWhatsThis::add( _regexpEdit, i18n( "This is the regular expression in ASCII syntax. You are likely only " + "to be interested in this if you are a programmer, and need to " + "develop a regular expression using QRegExp.

" + "You may develop your regular expression both by using the graphical " + "editor, and by typing the regular expression in this line edit.") ); + +#ifdef QT_ONLY + QPixmap pix( "icons/error.png" ); +#else + QPixmap pix = KGlobal::iconLoader()->loadIcon(locate("data", QString::fromLatin1("kregexpeditor/pics/error.png") ), KIcon::Toolbar ); +#endif + _error = new QLabel( this ); + _error->setPixmap( pix ); + layout->addWidget( _error ); + _error->hide(); + + _timer = new QTimer(this); + + connect( _scrolledEditorWindow, SIGNAL( change() ), this, SLOT( slotUpdateLineEdit() ) ); + connect( _regexpEdit, SIGNAL(textChanged( const QString& ) ), this, SLOT( slotTriggerUpdate() ) ); + connect( _timer, SIGNAL( timeout() ), this, SLOT( slotTimeout() ) ); + connect( clearButton, SIGNAL( clicked() ), _regexpEdit, SLOT( clear() ) ); + + // Push an initial empty element on the stack. + _undoStack.push( _scrolledEditorWindow->regExp() ); + _redoStack.setAutoDelete( true ); + + QAccel* accel = new QAccel( this ); + accel->connectItem( accel->insertItem( CTRL+Key_Z ), this, SLOT( slotUndo() ) ); + accel->connectItem( accel->insertItem( CTRL+Key_R ), this, SLOT( slotRedo() ) ); + + setSyntax( QString::fromLatin1( "Qt" ) ); +} + +QString KRegExpEditorPrivate::regexp() +{ + RegExp* regexp = _scrolledEditorWindow->regExp(); + QString res = RegExpConverter::current()->toStr( regexp, false ); + delete regexp; + return res; +} + +void KRegExpEditorPrivate::slotUpdateEditor( const QString & txt) +{ + _updating = true; + bool ok; + if ( !RegExpConverter::current()->canParse() ) { + // This can happend if the application set a text through the API. + } + else { + RegExp* result = RegExpConverter::current()->parse( txt, &ok ); + if ( ok ) { + QPtrList list = _userRegExps->regExps(); + for ( QPtrListIterator it( list ); *it; ++it ) { + result->replacePart( *it ); + } + + _scrolledEditorWindow->slotSetRegExp( result ); + _error->hide(); + maybeVerify( ); + recordUndoInfo(); + result->check( _errorMap ); + } + else { + _error->show(); + if ( _autoVerify ) + _verifier->clearRegexp(); + } + delete result; + } + _updating = false; +} + +void KRegExpEditorPrivate::slotUpdateLineEdit() +{ + if ( _updating ) + return; + _updating = true; + + RegExp* regexp = _scrolledEditorWindow->regExp(); + regexp->check( _errorMap ); + + QString str = RegExpConverter::current()->toStr( regexp, false ); + _regexpEdit->setText( str ); + delete regexp; + + recordUndoInfo(); + + _updating = false; +} + +void KRegExpEditorPrivate::recordUndoInfo() +{ + Q_ASSERT( _updating ); + + // Update undo/redo stacks + RegExp* regexp = _scrolledEditorWindow->regExp(); + if ( regexp->toXmlString() != _undoStack.top()->toXmlString() ) { + _undoStack.push( regexp ); + _redoStack = QPtrStack(); + emitUndoRedoSignals(); + } +} + +void KRegExpEditorPrivate::slotRedo() +{ + if ( _redoStack.count() != 0 ) { + _undoStack.push(_redoStack.pop()); + _scrolledEditorWindow->slotSetRegExp( _undoStack.top() ); + slotUpdateLineEdit(); + emitUndoRedoSignals(); + maybeVerify(); + } +} + +void KRegExpEditorPrivate::slotUndo() +{ + if ( _undoStack.count() > 1 ) { + _redoStack.push(_undoStack.pop()); + _scrolledEditorWindow->slotSetRegExp( _undoStack.top() ); + slotUpdateLineEdit(); + emitUndoRedoSignals(); + maybeVerify(); + } +} + +void KRegExpEditorPrivate::slotShowEditor() +{ + _info->hide(); + _editor->show(); +} + +void KRegExpEditorPrivate::emitUndoRedoSignals() +{ + emit canUndo( _undoStack.count() > 1 ); + emit changes( _undoStack.count() > 1 ); + emit canRedo( _redoStack.count() > 0 ); +} + +void KRegExpEditorPrivate::slotSetRegexp( QString regexp ) +{ + _regexpEdit->setText( regexp ); +} + +void KRegExpEditorPrivate::slotTriggerUpdate() +{ + /* ### Guess this timeout value should be configurable somewhere, or (even + * better: do some kind of benchmark each time the editor view gets updated + * to measure how long it takes on the client system to render the editor + * with the current complexity. That way we'd get good response times for + * simple regexps, and flicker-free display for complex regexps. + * - Frerich + */ + if ( !_updating ) { + _timer->start( 300, true ); + slotShowEditor(); + } +} + +void KRegExpEditorPrivate::slotTimeout() +{ + slotUpdateEditor( _regexpEdit->text() ); +} + +void KRegExpEditorPrivate::setMatchText( const QString& text ) +{ + bool autoVerify = _autoVerify; + _autoVerify = false; + _verifier->setText( text ); + _autoVerify = autoVerify; +} + +void KRegExpEditorPrivate::maybeVerify() +{ + if ( _autoVerify ) + doVerify(); + else + _verifyButtons->setMatchCount(-1); +} + +void KRegExpEditorPrivate::doVerify() +{ + bool autoVerify = _autoVerify; // prevent loop due to verify emit changed, which calls maybeVerify + _autoVerify = false; + RegExp* regexp = _scrolledEditorWindow->regExp(); + + _verifier->verify( RegExpConverter::current()->toStr( regexp, true ) ); + delete regexp; + _autoVerify = autoVerify; +} + +void KRegExpEditorPrivate::setAutoVerify( bool on ) +{ + _autoVerify = on; + if ( !_autoVerify ) + _verifier->clearRegexp(); + else + doVerify(); +} + +void KRegExpEditorPrivate::setVerifyText( const QString& fileName ) +{ + bool autoVerify = _autoVerify; + _autoVerify = false; + QFile file( fileName ); + if ( !file.open( IO_ReadOnly ) ) { + KMessageBox::sorry(0, i18n("Could not open file '%1' for reading").arg( fileName ) ); + } + else { + QTextStream s( &file ); + QString txt = s.read(); + file.close(); + RegExp* regexp = _scrolledEditorWindow->regExp(); + _verifier->setText( txt ); + _verifier->verify( RegExpConverter::current()->toStr( regexp, true ) ); + delete regexp; + } + _autoVerify = autoVerify; +} + +void KRegExpEditorPrivate::setCaseSensitive( bool b ) +{ + _verifier->setCaseSensitive( b ); +} + +void KRegExpEditorPrivate::setMinimal( bool b ) +{ + _verifier->setMinimal( b ); +} + +void KRegExpEditorPrivate::setSyntax( const QString& syntax ) +{ + RegExpConverter* converter = _verifyButtons->setSyntax( syntax ); + RegExpConverter::setCurrent( converter ); + if ( converter->canParse() ) { + _regexpEdit->setReadOnly( false ); + _regexpEdit->setBackgroundMode( Qt::PaletteBase ); + } + else { + _regexpEdit->setReadOnly( true ); + _regexpEdit->setBackgroundMode( Qt::PaletteBackground ); + } + _regExpButtons->setFeatures( converter->features() ); + _verifier->setHighlighter( converter->highlighter(_verifier) ); + slotUpdateLineEdit(); +} + +void KRegExpEditorPrivate::showHelp() +{ + _info->show(); + _editor->hide(); +} + +void KRegExpEditorPrivate::setAllowNonQtSyntax( bool b ) +{ + _verifyButtons->setAllowNonQtSyntax( b ); +} diff --git a/kregexpeditor/kregexpeditorprivate.h b/kregexpeditor/kregexpeditorprivate.h new file mode 100644 index 0000000..2e40fad --- /dev/null +++ b/kregexpeditor/kregexpeditorprivate.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef kregexpeditorprivate_h +#define kregexpeditorprivate_h + +#include +#include +#include "regexp.h" +#include "errormap.h" +class QTimer; + +class RegExpScrolledEditorWindow; +class QLineEdit; +class InfoPage; +class UserDefinedRegExps; +class QSplitter; +class Verifier; +class VerifyButtons; +class AuxButtons; +class RegExpLineEdit; +class RegExpConverter; +class RegExpButtons; +class QToolButton; + +/** + Widget used to build a regular expression + + @author Jesper K. Pedersen + @version 0.1 +**/ +class KRegExpEditorPrivate :public QWidget +{ + Q_OBJECT + +public: + KRegExpEditorPrivate( QWidget *parent, const char *name = 0 ); + QString regexp(); + void setMinimal( bool ); + void setCaseSensitive( bool ); + void setAllowNonQtSyntax( bool ); + +protected slots: + void slotUpdateEditor( const QString & ); + void slotUpdateLineEdit(); + void slotShowEditor(); + void slotTriggerUpdate(); + void slotTimeout(); + void maybeVerify(); + void doVerify(); + void setAutoVerify( bool ); + void setVerifyText( const QString& fileName ); + +public slots: + void slotUndo(); + void slotRedo(); + void slotSetRegexp( QString regexp ); + void setMatchText( const QString& text ); + void setSyntax( const QString& ); + void showHelp(); + +signals: + void canUndo( bool ); + void canRedo( bool ); + void changes( bool ); + +protected: + void recordUndoInfo(); + void emitUndoRedoSignals(); + +private: + RegExpScrolledEditorWindow* _scrolledEditorWindow; + RegExpButtons* _regExpButtons; + VerifyButtons* _verifyButtons; + AuxButtons *_auxButtons; + InfoPage* _info; + QLineEdit* _regexpEdit; + QSplitter* _editor; + bool _updating; + QLabel* _error; + QPtrStack _undoStack; + QPtrStack _redoStack; + UserDefinedRegExps* _userRegExps; + QTimer* _timer; + Verifier* _verifier; + bool _autoVerify; + ErrorMap _errorMap; + QToolButton *clearButton; +}; + +#endif + diff --git a/kregexpeditor/limitedcharlineedit.cpp b/kregexpeditor/limitedcharlineedit.cpp new file mode 100644 index 0000000..9631603 --- /dev/null +++ b/kregexpeditor/limitedcharlineedit.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "limitedcharlineedit.h" +#include + +/** + @internal + A Validator for the @ref LimitedCharLineEdit +*/ +class Validator :public QValidator +{ +public: + Validator( LimitedCharLineEdit::Mode mode, QWidget* parent ) + :QValidator( parent, "Validator" ), _mode(mode) + { + } + + virtual QValidator::State validate( QString& txt, int & /*pos*/ ) const + { + if ( _mode == LimitedCharLineEdit::NORMAL || + (_mode == LimitedCharLineEdit::HEX && + QRegExp(QString::fromLocal8Bit("^[0-9A-Fa-f]*$")).search( txt ) != -1) || + (_mode == LimitedCharLineEdit::OCT && + QRegExp(QString::fromLocal8Bit("^[0-7]*$")).search( txt ) != -1 ) ) { + return QValidator::Acceptable; + } + else { + return QValidator::Invalid; + } + } + +private: + LimitedCharLineEdit::Mode _mode; +}; + + +void LimitedCharLineEdit::keyPressEvent ( QKeyEvent *event ) +{ + QLineEdit::keyPressEvent( event ); + if ( text().length() == _count && !event->text().isNull() ) + focusNextPrevChild(true); +} + +LimitedCharLineEdit::LimitedCharLineEdit( Mode mode, QWidget* parent, const char* name ) + :QLineEdit( parent, name ), _mode(mode) +{ + if ( mode == NORMAL ) + _count = 1; + else if ( mode == HEX ) + _count = 4; + else + _count = 4; + + setMaxLength( _count ); + setFixedSize( fontMetrics().width('A')*5+5, sizeHint().height()); + + setValidator( new Validator( mode, this ) ); +} + + diff --git a/kregexpeditor/limitedcharlineedit.h b/kregexpeditor/limitedcharlineedit.h new file mode 100644 index 0000000..d4654c6 --- /dev/null +++ b/kregexpeditor/limitedcharlineedit.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __limitedcharlineedit +#define __limitedcharlineedit + +#include + +/** + QLineEdit which only accepts a prespecified number of character. + @internal +*/ +class LimitedCharLineEdit :public QLineEdit +{ +public: + enum Mode { NORMAL = 0, HEX = 1, OCT = 2 }; + + LimitedCharLineEdit(Mode mode, QWidget* parent, const char *name = 0); + +protected: + virtual void keyPressEvent ( QKeyEvent * ); + +private: + Mode _mode; + unsigned int _count; +}; + +#endif + diff --git a/kregexpeditor/lookaheadregexp.cpp b/kregexpeditor/lookaheadregexp.cpp new file mode 100644 index 0000000..7415ca4 --- /dev/null +++ b/kregexpeditor/lookaheadregexp.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "lookaheadregexp.h" +#include "errormap.h" + +LookAheadRegExp::LookAheadRegExp( bool selected, TYPE tp, RegExp* child ) + : RegExp( selected ), _child( child ), _tp( tp ) +{ + if ( child ) + addChild( child ); +} + +bool LookAheadRegExp::check( ErrorMap& map, bool , bool last ) +{ + if ( !last ) { + map.lookAheadError(); + } + return true; +} + + +QDomNode LookAheadRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top; + if ( _tp == POSITIVE ) + top = doc->createElement( QString::fromLocal8Bit("PositiveLookAhead") ); + else + top = doc->createElement( QString::fromLocal8Bit("NegativeLookAhead") ); + + top.appendChild( _child->toXml( doc ) ); + return top; +} + +bool LookAheadRegExp::load( QDomElement top, const QString& version ) +{ + _child = readRegExp( top, version ); + if ( _child ) { + addChild( _child ); + return true; + } + else + return false; +} + + +bool LookAheadRegExp::operator==( const RegExp& other ) const +{ + if ( type() != other.type() ) + return false; + + const LookAheadRegExp& theOther = dynamic_cast( other ); + + if ( lookAheadType() != theOther.lookAheadType() ) + return false; + + return ( *_child == *(theOther._child) ); +} diff --git a/kregexpeditor/lookaheadregexp.h b/kregexpeditor/lookaheadregexp.h new file mode 100644 index 0000000..9021710 --- /dev/null +++ b/kregexpeditor/lookaheadregexp.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __LOOKAHEADREGEXP_H +#define __LOOKAHEADREGEXP_H + +#include "regexp.h" + +/** + Abstract syntax node for `repeated content' regular expression + @internal +*/ +class LookAheadRegExp :public RegExp +{ +public: + enum TYPE { POSITIVE, NEGATIVE }; + + LookAheadRegExp( bool selected, TYPE tp, RegExp* child = 0); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 4;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + RegExp* child() const { return _child; } + TYPE lookAheadType() const { return _tp; } + virtual RegExpType type() const { return LOOKAHEAD;} + virtual bool operator==( const RegExp& other ) const; + virtual void replacePart( CompoundRegExp* replacement ) { _child->replacePart( replacement ); } + +private: + RegExp* _child; + TYPE _tp; +}; + +#endif // __LOOKAHEADREGEXP_H diff --git a/kregexpeditor/lookaheadwidget.cpp b/kregexpeditor/lookaheadwidget.cpp new file mode 100644 index 0000000..b724a3c --- /dev/null +++ b/kregexpeditor/lookaheadwidget.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include "lookaheadwidget.moc" +#endif + +#include "lookaheadwidget.h" +#include "lookaheadregexp.h" +#include "concwidget.h" +#include + +LookAheadWidget::LookAheadWidget( RegExpEditorWindow* editorWindow, RegExpType tp, QWidget* parent, const char* name ) + :SingleContainerWidget(editorWindow, parent, name ? name : "LookAheadWidget" ), _tp(tp) +{ + _child = new ConcWidget( editorWindow, this ); + init(); +} + +LookAheadWidget::LookAheadWidget( LookAheadRegExp* regexp, RegExpEditorWindow* editorWindow, RegExpType tp, + QWidget* parent, const char* name ) + :SingleContainerWidget( editorWindow, parent, name ? name : "LookAheadWidget" ), _tp(tp) +{ + RegExpWidget* child = WidgetFactory::createWidget( regexp->child(), editorWindow, this ); + if ( ! (_child = dynamic_cast( child ) ) ) + _child = new ConcWidget( editorWindow, child, this ); + + init(); +} + +void LookAheadWidget::init() +{ + if ( _tp == POSLOOKAHEAD ) + _text = i18n("Pos. Look Ahead"); + else + _text = i18n("Neg. Look Ahead"); +} + +RegExp* LookAheadWidget::regExp() const +{ + return new LookAheadRegExp( isSelected(), ( (_tp == POSLOOKAHEAD) ? LookAheadRegExp::POSITIVE : LookAheadRegExp::NEGATIVE), + _child->regExp() ); +} + +QSize LookAheadWidget::sizeHint() const +{ + // TODO: Merge with RepeatWidget::sizeHint + QFontMetrics metrics = fontMetrics(); + _textSize = metrics.size( 0, _text ); + + _childSize = _child->sizeHint(); + + int height = _textSize.height() + bdSize + _childSize.height() + bdSize + 2*pw; + int width = 2 * pw + QMAX(_childSize.width(), 4*bdSize + _textSize.width()); + return QSize(width,height); +} + +void LookAheadWidget::paintEvent( QPaintEvent *e ) +{ + // TODO: Merge with RepeatWidget::paintEvent + QSize mySize = sizeHint(); + QPainter painter(this); + + drawPossibleSelection( painter, mySize ); + + // move the child to its position and resize it. + _child->move(pw,_textSize.height()+bdSize); + _child->resize(mySize.width() - 2*pw, _childSize.height()); + + // Draw the border and the text. + int startY = _textSize.height()/2; + + // Top lines and text + painter.drawLine(pw,startY,bdSize,startY); + painter.drawText(pw+2*bdSize,0,_textSize.width(), _textSize.height(),0, _text); + int offset = pw + 3*bdSize + _textSize.width(); + painter.drawLine(offset,startY,mySize.width()-pw,startY); + + // horizontal lines + painter.drawLine(0,startY,0,mySize.height()-pw); + painter.drawLine(mySize.width()-pw,startY,mySize.width()-pw, mySize.height()-pw); + + // buttom line + painter.drawLine(0, mySize.height()-pw, mySize.width()-pw, mySize.height()-pw); + + SingleContainerWidget::paintEvent(e); +} + +RegExpWidget* LookAheadWidget::findWidgetToEdit( QPoint globalPos ) +{ + return _child->findWidgetToEdit( globalPos ); +} diff --git a/kregexpeditor/lookaheadwidget.h b/kregexpeditor/lookaheadwidget.h new file mode 100644 index 0000000..5e244b8 --- /dev/null +++ b/kregexpeditor/lookaheadwidget.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __lookaheadwidget +#define __lookaheadwidget + +#include "singlecontainerwidget.h" +class LookAheadRegExp; + +class LookAheadWidget :public SingleContainerWidget +{ + Q_OBJECT +public: + LookAheadWidget( RegExpEditorWindow* editorWindow, RegExpType tp, QWidget* parent, const char* name = 0 ); + LookAheadWidget( LookAheadRegExp* regexp, RegExpEditorWindow* editorWindow, RegExpType tp, + QWidget* parent, const char* name = 0); + + virtual RegExp* regExp() const; + virtual RegExpType type() const { return _tp; } + virtual QSize sizeHint() const; + virtual RegExpWidget* findWidgetToEdit( QPoint globalPos ); + + +protected: + void init(); + virtual void paintEvent( QPaintEvent *e ); + + +private: + RegExpType _tp; + QString _text; + + mutable QSize _textSize; + mutable QSize _childSize; +}; + +#endif // __lookaheadwidget diff --git a/kregexpeditor/main.cpp b/kregexpeditor/main.cpp new file mode 100644 index 0000000..bde19e9 --- /dev/null +++ b/kregexpeditor/main.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" + #include +#else + #include + #include + #include + #include + #include +#endif + +#include "kregexpeditorgui.h" +#include + +int main( int argc, char* argv[] ) +{ +#ifdef QT_ONLY + QApplication myapp( argc, argv ); +#else + KAboutData aboutData( "kregexpeditor", I18N_NOOP("RegExp Editor"), + "1.0", I18N_NOOP("Editor for Regular Expressions"), + KAboutData::License_GPL, + "(c) 2002-2003 Jesper K. Pedersen"); + KCmdLineArgs::init(argc, argv, &aboutData); + KApplication myapp; +#endif + + QDialog* top = new QDialog( 0 ); + QVBoxLayout* lay = new QVBoxLayout( top, 6 ); + + KRegExpEditorGUI* iface = new KRegExpEditorGUI( top, "_editor", QStringList() ); + iface->doSomething( QString::fromLatin1("setAllowNonQtSyntax"), (bool*) true ); + lay->addWidget( iface ); + + QHBoxLayout* lay2 = new QHBoxLayout( lay, 6 ); + KPushButton* help = new KPushButton( KStdGuiItem::help(), top ); + KPushButton* quit = new KPushButton( KStdGuiItem::quit(), top ); + + lay2->addWidget( help ); + lay2->addStretch(1); + lay2->addWidget( quit ); + + QObject::connect( help, SIGNAL( clicked() ), iface, SLOT( showHelp() ) ); + QObject::connect( quit, SIGNAL( clicked() ), qApp, SLOT( quit() ) ); + + top->show(); + QObject::connect( qApp, SIGNAL( lastWindowClosed() ), qApp, SLOT( quit() ) ); + myapp.exec(); +} + diff --git a/kregexpeditor/multicontainerwidget.cpp b/kregexpeditor/multicontainerwidget.cpp new file mode 100644 index 0000000..b4ae399 --- /dev/null +++ b/kregexpeditor/multicontainerwidget.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "multicontainerwidget.h" +#include "dragaccepter.h" + +MultiContainerWidget::MultiContainerWidget( RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name) + :RegExpWidget( editorWindow, parent, name ) +{ +} + +void MultiContainerWidget::append( RegExpWidget* child ) +{ + child->reparent( this, QPoint(0,0), false ); + _children.append( child ); + _children.append( new DragAccepter( _editorWindow, this ) ); +} + +bool MultiContainerWidget::hasSelection() const +{ + if ( _isSelected ) + return true; + + QPtrListIterator it(_children); + ++it; // Move past the first dragAccepter + for ( ; *it; it += 2 ) { + if ( (*it)->hasSelection() ) { + return true; + } + } + return false; +} + +void MultiContainerWidget::clearSelection() +{ + _isSelected = false; + for ( unsigned int i = 0; i< _children.count(); i++ ) { + _children.at(i)->clearSelection(); + } +} + + +void MultiContainerWidget::deleteSelection() +{ + // run from the back to the front (which we do since we delete items on the run) + // When deleting children, delete the drag accepter to its right. + for ( int i = (int) _children.count()-2; i > 0; i -=2 ) { + + RegExpWidget* child = _children.at( i ); + if ( child->isSelected() ) { + delete _children.at( i+1 ); + _children.remove( i+1 ); + delete child; + _children.remove(i); + } + else if ( child->hasSelection() ) { + child->deleteSelection(); + } + } + _isSelected = false; + update(); +} + +void MultiContainerWidget::addNewChild(DragAccepter *accepter, RegExpWidget *child) +{ + for ( unsigned int i=0; i<_children.count(); i+= 2 ) { + RegExpWidget *ch = _children.at( i ); + if ( ch == accepter ) { + // Insert the new child + _children.insert( i+1, child ); + + // Insert an accepter as the next element. + DragAccepter *accepter = new DragAccepter( _editorWindow, this ); + + _children.insert( i+2, accepter ); + + // These two show's must come here otherwise a paintevent + // will be invoked, where the invariant, that a accepter is located at + // every second element. + child->show(); + accepter->show(); + + update(); + + return; + } + } + qFatal("Accepter not found in list"); +} + +bool MultiContainerWidget::updateSelection(bool parentSelected) +{ + bool changed = false; + bool isSel = _isSelected; + QMemArray oldState(_children.count()); + QMemArray newState(_children.count()); + + for (int i = 0; i< (int)_children.count();i++) { + oldState[i] = _children.at(i)->isSelected(); + } + + RegExpWidget::updateSelection( parentSelected ); + + int first; + int last; + + // scan for the first selected item. + for (first = 1; first < (int) _children.count(); first+= 2 ) { + RegExpWidget* child = _children.at(first); + changed = child->updateSelection( _isSelected ) || changed; + newState[first] = child->isSelected(); + if ( child->isSelected() ) + break; + } + + // scan for the last selected item + for (last = _children.count()-2; last>first; last -= 2) { + RegExpWidget* child = _children.at(last); + changed = child->updateSelection( _isSelected ) || changed; + newState[last] = child->isSelected(); + if ( child->isSelected() ) + break; + } + + // everything between first and last must be selected. + for (int j = first+2; jupdateSelection( true ) || changed; + newState[j] = true; + } + + // update drag accepters. + for (int k = 0; k< (int) _children.count(); k+=2) { + RegExpWidget* child = _children.at(k); + bool select; + if ( k == 0 || k == (int)_children.count()-1) { + // The elements at the border is only selected if the parent is selected. + select = _isSelected; + } + else { + // Drag accepters in the middle is selected if the elements at both + // sides are selected. + select = newState[k-1] && newState[k+1]; + } + + bool isChildSel = child->isSelected(); + DragAccepter *accepter = dynamic_cast(child); + if (accepter) + accepter->_isSelected = select; + if ( select != isChildSel ) + child->repaint(); + } + + changed = changed || isSel != _isSelected; + if ( changed ) { + repaint(); + } + + return changed; +} + + + +QRect MultiContainerWidget::selectionRect() const +{ + if ( _isSelected ) + return QRect( mapToGlobal( QPoint(0,0) ), size() ); + else { + QRect res; + QPtrListIterator it(_children); + ++it; // Move past the first dragAccepter + for ( ; *it; it +=2 ) { + if ( (*it)->hasSelection() ) { + QRect childSel = (*it)->selectionRect(); + if ( res.isNull() ) + res = childSel; + else { + QRect newRes; + newRes.setLeft( QMIN( res.left(), childSel.left() ) ); + newRes.setTop( QMIN( res.top(), childSel.top() ) ); + newRes.setRight( QMAX( res.right(), childSel.right() ) ); + newRes.setBottom( QMAX( res.bottom(), childSel.bottom() ) ); + res = newRes; + } + } + } + return res; + } +} + +RegExpWidget* MultiContainerWidget::widgetUnderPoint( QPoint globalPos, bool justVisibleWidgets ) +{ + unsigned int start, incr; + if ( justVisibleWidgets ) { + start = 1; + incr = 2; + } + else { + start = 0; + incr = 1; + } + + for ( unsigned int i = start; i < _children.count(); i+=incr ) { + RegExpWidget* wid = _children.at(i)->widgetUnderPoint( globalPos, justVisibleWidgets ); + if ( wid ) + return wid; + } + if ( justVisibleWidgets ) + return 0; + else { + return RegExpWidget::widgetUnderPoint( globalPos, justVisibleWidgets ); + } +} + +RegExpWidget* MultiContainerWidget::findWidgetToEdit( QPoint globalPos ) +{ + for ( unsigned int i = 1; i < _children.count(); i+=2 ) { + RegExpWidget* wid = _children.at(i)->findWidgetToEdit( globalPos ); + if ( wid ) + return wid; + } + return 0; +} + +void MultiContainerWidget::selectWidget( bool sel ) +{ + RegExpWidget::selectWidget( sel ); + QPtrListIterator it(_children); + for ( ; *it ; ++it ) { + (*it)->selectWidget( sel ); + } + update(); +} + +void MultiContainerWidget::updateAll() +{ + for ( QPtrListIterator it(_children); *it ; ++it ) { + (*it)->updateAll(); + } + RegExpWidget::updateAll(); +} + +void MultiContainerWidget::updateCursorRecursively() +{ + for ( QPtrListIterator it(_children); *it ; ++it ) { + (*it)->updateCursorRecursively(); + } + updateCursorShape(); +} diff --git a/kregexpeditor/multicontainerwidget.h b/kregexpeditor/multicontainerwidget.h new file mode 100644 index 0000000..3fa4095 --- /dev/null +++ b/kregexpeditor/multicontainerwidget.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __multicontainerwidget +#define __multicontainerwidget + +#include "regexpwidget.h" + +/** + Abstract RegExp widget class representing widgets having multible children. + @internal +*/ +class MultiContainerWidget :public RegExpWidget +{ +public: + MultiContainerWidget( RegExpEditorWindow* editorWindow, QWidget* parent = 0, + const char* name = 0); + virtual bool hasSelection() const; + virtual void clearSelection(); + virtual void deleteSelection(); + virtual void addNewChild(DragAccepter *accepter, RegExpWidget *child); + virtual bool updateSelection(bool parentSelected); + virtual QRect selectionRect() const; + virtual RegExpWidget* widgetUnderPoint( QPoint globalPos, bool justVisibleWidgets ); + virtual RegExpWidget* findWidgetToEdit( QPoint globalPos ); + virtual void selectWidget( bool sel ); + virtual void updateAll(); + virtual void updateCursorRecursively(); + +protected: + void append( RegExpWidget* child ); + QPtrList _children; +}; + + +#endif // __multicontainerwidget diff --git a/kregexpeditor/myfontmetrics.cpp b/kregexpeditor/myfontmetrics.cpp new file mode 100644 index 0000000..cdf29b2 --- /dev/null +++ b/kregexpeditor/myfontmetrics.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "myfontmetrics.h" + +QSize HackCalculateFontSize(QFontMetrics fm, QString str ) +{ + QStringList list = QStringList::split( QString::fromLatin1("\n"), str ); + int maxWidth = 0; + int height = 0; + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + QSize size = fm.size( 0, *it ); + maxWidth = QMAX( maxWidth, size.width() ); + height += size.height(); + } + return QSize( maxWidth, height ); +} diff --git a/kregexpeditor/myfontmetrics.h b/kregexpeditor/myfontmetrics.h new file mode 100644 index 0000000..649d32b --- /dev/null +++ b/kregexpeditor/myfontmetrics.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __MYFONTMETRICS_H +#define __MYFONTMETRICS_H +#include +#include + +// QFontMetrics::size is broken, therefore I need this hack until it works in QT3 + +QSize HackCalculateFontSize(QFontMetrics fm, QString str ); + +#endif diff --git a/kregexpeditor/pair.h b/kregexpeditor/pair.h new file mode 100644 index 0000000..b7296c5 --- /dev/null +++ b/kregexpeditor/pair.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __pair_h +#define __pair_h + +/** + @internal +*/ +template class Pair +{ +public: + Pair() {} + Pair(F first, S second) : _first(first), _second(second) {} + F first() { return _first; } + S second() { return _second; } +private: + F _first; + S _second; + +}; + +#endif // __pair_h diff --git a/kregexpeditor/picts/Makefile.am b/kregexpeditor/picts/Makefile.am new file mode 100644 index 0000000..32b5061 --- /dev/null +++ b/kregexpeditor/picts/Makefile.am @@ -0,0 +1,2 @@ +pics_DATA= altn.png begline.png compound.png neglookahead.png poslookahead.png select.png wordboundary.png anychar.png characters.png endline.png nonwordboundary.png repeat.png text.png error.png autoverify.png verify.png +picsdir = $(kde_datadir)/kregexpeditor/pics diff --git a/kregexpeditor/picts/altn.png b/kregexpeditor/picts/altn.png new file mode 100644 index 0000000..900a1e9 Binary files /dev/null and b/kregexpeditor/picts/altn.png differ diff --git a/kregexpeditor/picts/anychar.png b/kregexpeditor/picts/anychar.png new file mode 100644 index 0000000..11048ca Binary files /dev/null and b/kregexpeditor/picts/anychar.png differ diff --git a/kregexpeditor/picts/autoverify.png b/kregexpeditor/picts/autoverify.png new file mode 100644 index 0000000..af68612 Binary files /dev/null and b/kregexpeditor/picts/autoverify.png differ diff --git a/kregexpeditor/picts/begline.png b/kregexpeditor/picts/begline.png new file mode 100644 index 0000000..3465a9e Binary files /dev/null and b/kregexpeditor/picts/begline.png differ diff --git a/kregexpeditor/picts/characters.png b/kregexpeditor/picts/characters.png new file mode 100644 index 0000000..7f218bf Binary files /dev/null and b/kregexpeditor/picts/characters.png differ diff --git a/kregexpeditor/picts/compound.png b/kregexpeditor/picts/compound.png new file mode 100644 index 0000000..a56c9bb Binary files /dev/null and b/kregexpeditor/picts/compound.png differ diff --git a/kregexpeditor/picts/endline.png b/kregexpeditor/picts/endline.png new file mode 100644 index 0000000..29b512e Binary files /dev/null and b/kregexpeditor/picts/endline.png differ diff --git a/kregexpeditor/picts/error.png b/kregexpeditor/picts/error.png new file mode 100644 index 0000000..4738f60 Binary files /dev/null and b/kregexpeditor/picts/error.png differ diff --git a/kregexpeditor/picts/neglookahead.png b/kregexpeditor/picts/neglookahead.png new file mode 100644 index 0000000..3cc0291 Binary files /dev/null and b/kregexpeditor/picts/neglookahead.png differ diff --git a/kregexpeditor/picts/nonwordboundary.png b/kregexpeditor/picts/nonwordboundary.png new file mode 100644 index 0000000..b22f4d4 Binary files /dev/null and b/kregexpeditor/picts/nonwordboundary.png differ diff --git a/kregexpeditor/picts/poslookahead.png b/kregexpeditor/picts/poslookahead.png new file mode 100644 index 0000000..492692b Binary files /dev/null and b/kregexpeditor/picts/poslookahead.png differ diff --git a/kregexpeditor/picts/repeat.png b/kregexpeditor/picts/repeat.png new file mode 100644 index 0000000..2646111 Binary files /dev/null and b/kregexpeditor/picts/repeat.png differ diff --git a/kregexpeditor/picts/select.png b/kregexpeditor/picts/select.png new file mode 100644 index 0000000..e04ab17 Binary files /dev/null and b/kregexpeditor/picts/select.png differ diff --git a/kregexpeditor/picts/text.png b/kregexpeditor/picts/text.png new file mode 100644 index 0000000..8b256ca Binary files /dev/null and b/kregexpeditor/picts/text.png differ diff --git a/kregexpeditor/picts/verify.png b/kregexpeditor/picts/verify.png new file mode 100644 index 0000000..dd76b7c Binary files /dev/null and b/kregexpeditor/picts/verify.png differ diff --git a/kregexpeditor/picts/wordboundary.png b/kregexpeditor/picts/wordboundary.png new file mode 100644 index 0000000..0e89a6b Binary files /dev/null and b/kregexpeditor/picts/wordboundary.png differ diff --git a/kregexpeditor/positionregexp.cpp b/kregexpeditor/positionregexp.cpp new file mode 100644 index 0000000..df5311f --- /dev/null +++ b/kregexpeditor/positionregexp.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "positionregexp.h" +#include "errormap.h" + +PositionRegExp::PositionRegExp( bool selected, PositionType tp ) :RegExp( selected ) +{ + _tp = tp; +} + +bool PositionRegExp::check( ErrorMap& map, bool first , bool last ) +{ + if ( _tp == BEGLINE && !first) { + map.lineStartError(); + } + else if ( _tp == ENDLINE && !last ) { + map.lineEndError(); + } + return true; +} + +QDomNode PositionRegExp::toXml( QDomDocument* doc ) const +{ + switch (_tp) { + case BEGLINE: return doc->createElement(QString::fromLocal8Bit( "BegLine" ) ); + case ENDLINE: return doc->createElement(QString::fromLocal8Bit( "EndLine" ) ); + case WORDBOUNDARY: return doc->createElement(QString::fromLocal8Bit( "WordBoundary" ) ); + case NONWORDBOUNDARY: return doc->createElement(QString::fromLocal8Bit( "NonWordBoundary" ) ); + } + return QDomNode(); +} + +bool PositionRegExp::load( QDomElement /* top */, const QString& /*version*/ ) +{ + // Nothing to do. + return true; +} + diff --git a/kregexpeditor/positionregexp.h b/kregexpeditor/positionregexp.h new file mode 100644 index 0000000..db90f93 --- /dev/null +++ b/kregexpeditor/positionregexp.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __POSITIONREGEXP_H +#define __POSITIONREGEXP_H + +#include "regexp.h" + +/** + Abstract syntax node for `positions' regular expression + @internal +*/ +class PositionRegExp :public RegExp +{ +public: + enum PositionType { BEGLINE, ENDLINE, WORDBOUNDARY, NONWORDBOUNDARY }; + + PositionRegExp( bool selected, PositionType tp ); + PositionType position() const { return _tp; } + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 4;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + virtual RegExpType type() const { return POSITION ;} + +private: + PositionType _tp; + +}; + +#endif // __POSITIONREGEXP_H diff --git a/kregexpeditor/predefined/General/Makefile.am b/kregexpeditor/predefined/General/Makefile.am new file mode 100644 index 0000000..338481b --- /dev/null +++ b/kregexpeditor/predefined/General/Makefile.am @@ -0,0 +1,5 @@ +pkg_DATA = spaces.regexp anything.regexp + +pkgdir = $(kde_datadir)/kregexpeditor/predefined/general + +EXTRA_DIST = $(pkg_DATA) diff --git a/kregexpeditor/predefined/General/anything.regexp b/kregexpeditor/predefined/General/anything.regexp new file mode 100644 index 0000000..d016906 --- /dev/null +++ b/kregexpeditor/predefined/General/anything.regexp @@ -0,0 +1,11 @@ + + + + + anything + This regular expression matches anything. + + + + + diff --git a/kregexpeditor/predefined/General/spaces.regexp b/kregexpeditor/predefined/General/spaces.regexp new file mode 100644 index 0000000..5bf8696 --- /dev/null +++ b/kregexpeditor/predefined/General/spaces.regexp @@ -0,0 +1,11 @@ + + + + + spaces + Matches an arbitrary amount of whitespace. + + + + + diff --git a/kregexpeditor/predefined/Makefile.am b/kregexpeditor/predefined/Makefile.am new file mode 100644 index 0000000..05812f8 --- /dev/null +++ b/kregexpeditor/predefined/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=General diff --git a/kregexpeditor/predefined/README b/kregexpeditor/predefined/README new file mode 100644 index 0000000..7740948 --- /dev/null +++ b/kregexpeditor/predefined/README @@ -0,0 +1,2 @@ +This directory contains the predefined regular expressions. +Only one level of sub directories is supported. diff --git a/kregexpeditor/qregexpparser.l b/kregexpeditor/qregexpparser.l new file mode 100644 index 0000000..4fb90cc --- /dev/null +++ b/kregexpeditor/qregexpparser.l @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +%option noyywrap + +%{ + #include + #include "textrangeregexp.h" + #include "gen_qregexpparser.hh" +#ifdef QT_ONLY + #include "compat.h" +#endif + void parseRange( char* txt, int* min, int* max ); + RegExp* parseCharClass( char* match ); +%} + +Escape \\. +BackRef \\[1-9][0-9]* +CharClass \[^?\]?[^]]*\] +Range \{[0-9]*(,[0-9]*)?\} +HexChar \\x[0-9a-fA-F]{1,4} +OctChar \\0[0-7]{1,4} +SpecialEsc \\[afnrtv] +%% +"\\b" return TOK_PosWordChar; +"\\B" return TOK_PosNonWordChar; +"\\d" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setDigit( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"\\D" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonDigit( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"\\s" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setSpace( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"\\S" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonSpace( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"\\w" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setWordChar( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"\\W" { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->setNonWordChar( true ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +{SpecialEsc} { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit( yytext ) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } + +{HexChar} { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit(yytext) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +{OctChar} { + TextRangeRegExp* regexp = new TextRangeRegExp( false ); + regexp->addCharacter( QString::fromLocal8Bit(yytext) ); + qregexplval.regexp = regexp; + return TOK_CharClass; + } +"." return TOK_Dot; +"$" return TOK_Dollar; +"^" return TOK_Carat; +"(?:" return TOK_MagicLeftParent; +"(?=" return TOK_PosLookAhead; +"(?!" return TOK_NegLookAhead; +"(" return TOK_LeftParen; +")" return TOK_RightParent; +"|" return TOK_Bar; +"*" { qregexplval.range.min = 0; qregexplval.range.max=-1; return TOK_Quantifier; } +"?" { qregexplval.range.min = 0; qregexplval.range.max=1; return TOK_Quantifier; } +"+" { qregexplval.range.min = 1; qregexplval.range.max=-1; return TOK_Quantifier; } +{Range} { parseRange( yytext, &qregexplval.range.min, &qregexplval.range.max ); return TOK_Quantifier; } +{CharClass} { qregexplval.regexp = parseCharClass(yytext); return TOK_CharClass; } +{BackRef} { qregexplval.backRef = atoi( yytext+1 ); return TOK_BackRef; } +{Escape} { qregexplval.ch = yytext[1]; return TOK_EscapeChar; } +. { qregexplval.ch = yytext[0]; return TOK_Char; } + +%% + +void setParseData( QString qstr ) { + const char* cstr; + if ( qstr.isNull() ) + cstr = ""; + else + cstr = qstr.latin1(); + yy_switch_to_buffer( yy_scan_string( cstr ) ); +} + +/** + This function parses a range in a form similar to "{3,4}", "{,7}" + etc. and returns the value in the integers pointed to by min and max. +*/ +void parseRange( char* txt, int* min, int* max ) +{ + + /* + case txt min max + 1 {} 0 -1 + 2 {,} 0 -1 + 3 {5} 5 5 + 4 {5,} 5 -1 + 5 {,7} 0 7 + 6 {5,7} 5 7 + */ + char c; + int i = 1; + int minimum=0, maximum=0; + int minFound=0, maxFound=0, commaFound = 0; + + while ( (c = txt[i++]) != ',' && c != '}') { + minimum = minimum*10+ c-'0'; + minFound=1; + } + + if ( c == ',' ) + commaFound = 1; + + if ( c != '}' ) { + while ( (c = txt[i++]) != '}') { + maximum = maximum*10+ c-'0'; + maxFound = 1; + } + } + + *min = minimum; + if ( maxFound ) + *max = maximum; /* case 5,6 */ + else if ( !minFound ) + *max = -1; /* case 1,2 */ + else if ( commaFound ) + *max = -1; /* case 4 */ + else + *max = minimum; /* case 3 */ +} + + +/** + This function parses a character range like "[^ab1-4]". +*/ +RegExp* parseCharClass( char* match ) +{ + TextRangeRegExp* res = new TextRangeRegExp( false ); + QString txt = QString::fromLocal8Bit( match ); + txt = txt.mid(1,txt.length()-2); + + unsigned int i = 0; + QChar ch = txt.at(i++); + QString pendingChar; + QString thisChar; + bool charPending = false; + bool rangePending = false; + bool flushPending = false; + + if ( ch == QChar('^') ) { + res->setNegate( true ); + ch = txt.at(i++); + } + + do { + // If a character is pending, and the next char is '-' then we are + // possible looking at a range. + if ( ch == QChar('-') && charPending ) { + rangePending = true; + ch = txt.at(i++); + continue; + } + + // If we have a pending character, but do not also have a pending + // range, then the pending character was not part of a range, and + // should therefore just be added as a single character. + if ( charPending && !rangePending ) { + res->addCharacter( pendingChar ); + charPending = false; + } + + if ( ch == QChar('\\') ) { + // Handle the cases where an escape character is specified. + ch = txt.at(i++); + + if ( ch == QChar('a') || ch == QChar('f') || ch == QChar('n') || ch == QChar('r') || ch == QChar('t') || ch == QChar('v') ) { + // These are just seen as normal characters. + thisChar = QString::fromLocal8Bit("\\") + ch; + } + else if ( ch == QChar('d') ) { + // The following characters represent character groups. If any of + // these are seen in a range, then the range is ignored, thus [a-\s] + // matches an 'a', a '-', and a space (\s means space). + res->setDigit( true ); + flushPending = true; + } + else if ( ch == QChar('D') ) { + res->setNonDigit( true ); + flushPending = true; + } + else if ( ch == QChar('s') ) { + res->setSpace( true ); + flushPending = true; + } + else if ( ch == QChar('S') ) { + res->setNonSpace( true ); + flushPending = true; + } + else if ( ch == QChar('w') ) { + res->setWordChar( true ); + flushPending = true; + } + else if ( ch == QChar('W') ) { + res->setNonWordChar( true ); + flushPending = true; + } + else if ( ch == QChar('x') || ch == QChar('X') ) { + // This is a hexidecimal character: \xHHHH + QString str; + for ( int j=0; j<4; j++) { + ch = txt.at(i++); + if ( ch == 'a' || ch == 'A' || ch == 'b' || ch == 'B' || ch == 'c' || ch == 'C' || ch == 'd' || ch == 'D' || + ch == 'e' || ch == 'E' || ch == 'f' || ch == 'F' || + ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || + ch == '8' || ch == '9' ) + str += ch; + else + i--; + } + thisChar = QString::fromLocal8Bit("\\x") + str; + } + else if ( ch == QChar('0') ) { + // This is an octal character + QString str; + for ( int j=0; j<4; j++) { + ch = txt.at(i++); + if ( ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' ) + str += ch; + else + i--; + } + thisChar = QString::fromLocal8Bit("\\x") + str ; + } + else { + // Anything else escaped just means the character itself. + thisChar = ch; + } + } + else { + // A non escaped character. + thisChar = ch; + } + + // The characters \s,\S,\w,\W,\d or \D, can not be part of a range, + // thus if they are meet in what looks like a range, then the + // characters of the range is justed seen as normal non range + // characters. thus [a-\s] matches an 'a', a '-', and a space (\s means + // space). + if ( flushPending ) { + if ( charPending ) + res->addCharacter( pendingChar ); + if ( rangePending ) + res->addCharacter( QString::fromLocal8Bit("-") ); + flushPending = false; + charPending = false; + rangePending = false; + } + else { + if ( rangePending ) { + res->addRange( pendingChar, thisChar ); + charPending = false; + rangePending = false; + } + else { + pendingChar = thisChar; + charPending = true; + } + } + ch = txt.at(i++); + } + while ( ch != QChar(']') && i <= txt.length() ); + + if ( charPending ) + res->addCharacter( pendingChar ); + if ( rangePending ) + res->addCharacter( QString::fromLocal8Bit("-") ); + + return res; +} diff --git a/kregexpeditor/qregexpparser.y b/kregexpeditor/qregexpparser.y new file mode 100644 index 0000000..0faaf98 --- /dev/null +++ b/kregexpeditor/qregexpparser.y @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +%{ +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include +#endif + + #include + #include + + #include "regexp.h" + #include "textregexp.h" + #include "textrangeregexp.h" + #include "repeatregexp.h" + #include "lookaheadregexp.h" + #include "concregexp.h" + #include "altnregexp.h" + #include "positionregexp.h" + #include "dotregexp.h" + #include "compoundregexp.h" + + extern int yylex(); + extern void setParseData( QString str ); + int yyerror (const char *); + void setParseResult( RegExp* ); + RegExp* parseQtRegExp( QString qstr, bool* ok ); + static RegExp* parseResult; + static int _index; +%} + +%union { + struct { + int min; + int max; + } range; + int backRef; + RegExp* regexp; + char ch; +} + +%token TOK_Dot +%token TOK_Dollar +%token TOK_Carat +%token TOK_MagicLeftParent +%token TOK_PosLookAhead +%token TOK_NegLookAhead +%token TOK_LeftParen +%token TOK_RightParent +%token TOK_Bar +%token TOK_Quantifier +%token TOK_BackRef +%token TOK_CharClass +%token TOK_Char +%token TOK_EscapeChar +%token TOK_PosWordChar +%token TOK_PosNonWordChar + +%start regexp + +%% + +empty : /* nothing */ ; + +regexp : expression { setParseResult( $1) ; } + | empty { setParseResult( new ConcRegExp( false ) ); } + ; + +expression : expression TOK_Bar term { + if ( dynamic_cast( $1 ) ) { + $$ = $1; + } + else { + $$ = new AltnRegExp( false ); + dynamic_cast( $$ )->addRegExp( $1 ); + } + dynamic_cast( $$ )->addRegExp( $3 ); + } + | term { $$ = $1; } + | expression TOK_Bar { + if ( dynamic_cast( $1 ) ) { + $$ = $1; + } + else { + $$ = new AltnRegExp( false ); + dynamic_cast( $$ )->addRegExp( $1 ); + } + dynamic_cast( $$ )->addRegExp( new TextRegExp( false, QString::fromLatin1("") ) ); + } + | TOK_Bar term { + $$ = new AltnRegExp( false ); + dynamic_cast( $$ )->addRegExp( new TextRegExp( false, QString::fromLatin1("") ) ); + dynamic_cast( $$ )->addRegExp( $2 ); + } + | TOK_Bar { $$ = new AltnRegExp( false ); } + ; + +term : term factor { + RegExp* last = dynamic_cast( $1 )->lastRegExp(); + TextRegExp *reg1, *reg2; + + if ( last && ( reg1 = dynamic_cast( last ) ) && + ( reg2 = dynamic_cast( $2 ) ) ) { + reg1->append( reg2->text() ); + delete reg2; + } + else { + dynamic_cast($$)->addRegExp( $2 ); + } + $$ = $1; + } + | factor { + ConcRegExp* reg = new ConcRegExp( false ); + reg->addRegExp( $1 ); + $$ = reg; + } + ; + +factor : atom TOK_Quantifier { + $$ = new RepeatRegExp( false, $2.min, $2.max, $1 ); + } + | atom { $$ = $1; } + ; + +atom : TOK_LeftParen expression TOK_RightParent { + $$ = $2; + } + | TOK_MagicLeftParent expression TOK_RightParent { $$ = $2; } + | TOK_PosLookAhead expression TOK_RightParent { + $$ = new LookAheadRegExp( false, LookAheadRegExp::POSITIVE, $2 ); + } + | TOK_NegLookAhead expression TOK_RightParent { + $$ = new LookAheadRegExp( false, LookAheadRegExp::NEGATIVE, $2 ); + } + | TOK_CharClass { $$ = $1; } + | char { $$ = $1; } + | TOK_Dollar { $$ = new PositionRegExp( false, PositionRegExp::ENDLINE ); } + | TOK_Carat { $$ = new PositionRegExp( false, PositionRegExp::BEGLINE ); } + | TOK_Dot { $$ = new DotRegExp( false ); } + | TOK_BackRef { + QString match = QString::fromLocal8Bit("\\%1").arg( $1 ); + $$ = new TextRegExp( false, match ); + KMessageBox::information(0,i18n("Back reference regular expressions are not supported.

" + "\\1, \\2, ... are back references, meaning they refer to " + "previous matches. " + "Unfortunately this is not supported in the current version of this editor.

" + "In the graphical area the text %1 has been inserted. This is however " + "just a workaround to ensure that the application handles the regexp at all. " + "Therefore, as soon as you edit the regular expression in the graphical area, " + "the back reference will be replaced by matching the text %2 literally.") + .arg( match ).arg( match ), + i18n("Back reference regular expressions not supported"), + QString::fromLocal8Bit("backReferenceNotSupported") ); + } + | TOK_PosWordChar { $$ = new PositionRegExp( false, PositionRegExp::WORDBOUNDARY ); } + | TOK_PosNonWordChar { $$ = new PositionRegExp( false, PositionRegExp::NONWORDBOUNDARY ); } + ; + +char : TOK_Char { + if ( $1 == '{' || $1 == '}' || $1 == '[' || $1 == ']' || $1 == '\\' ) { + yyerror( "illigal character - needs escaping" ); + } + $$ = new TextRegExp( false, QString::fromLocal8Bit("%1").arg($1)); + } + | TOK_EscapeChar { $$ = new TextRegExp( false, QString::fromLocal8Bit("%1").arg($1)); } + ; + +%% + +RegExp* parseQtRegExp( QString qstr, bool* ok ) { + _index = 0; + parseResult = 0; + setParseData( qstr ); + yyparse(); + *ok = ( yynerrs == 0 ); + return parseResult; +} + +void setParseResult( RegExp* regexp ) { + parseResult = regexp; +} + +int yyerror(const char *) { + yynerrs++; + return 0; +} diff --git a/kregexpeditor/qt-only/clean b/kregexpeditor/qt-only/clean new file mode 100755 index 0000000..57e9a6d --- /dev/null +++ b/kregexpeditor/qt-only/clean @@ -0,0 +1,14 @@ +#!/bin/sh +rm *.o +rm *.obj +rm -rf manual +rm -rf predefined +rm -rf icons +rm unistd.h +find -lname \* -maxdepth 1 | xargs rm +rm moc_* +rm images.h +rm gen_* +rm -rf kregexpeditor* +rm Makefile +rm kregexpeditor.zip diff --git a/kregexpeditor/qt-only/compat.cpp b/kregexpeditor/qt-only/compat.cpp new file mode 100644 index 0000000..7dbc7b4 --- /dev/null +++ b/kregexpeditor/qt-only/compat.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "compat.h" + +QString i18n( const QString& a) { + return QObject::tr(a); +} + +QString i18n( const QString& a, const QString& b) { + return QObject::tr(b,a); +} + +KDialogBase::KDialogBase( int /*dialogFace*/, const QString &caption, int buttonMask, + ButtonCode defaultButton, QWidget *parent, const char *name, + bool modal ) + :QDialog( parent, name, modal ) +{ + init( buttonMask, defaultButton, caption ); +} + +KDialogBase::KDialogBase( QWidget* parent, const char* name, bool modal, + const QString& caption, int buttonMask ) + : QDialog( parent, name, modal ) +{ + init( buttonMask, Ok, caption ); +} + +void KDialogBase::init( int buttonMask, ButtonCode /*defaultButton*/, const QString& caption ) +{ + setCaption( caption ); + _layout = new QVBoxLayout( this, 6 ); + QHBoxLayout* buts = new QHBoxLayout( _layout, 6 ); + QPushButton* but; + if ( buttonMask & Help ) { + but = new QPushButton( tr("Help"), this ); + buts->addWidget( but ); + connect( but, SIGNAL( clicked() ), this, SIGNAL( helpClicked() ) ); + } + buts->addStretch(1); + if ( buttonMask & Ok ) { + but = new QPushButton( tr("OK"), this ); + buts->addWidget( but ); + connect( but, SIGNAL( clicked() ), this, SLOT( slotOk() ) ); + } + if ( buttonMask & Cancel ) { + but = new QPushButton( tr("Cancel"), this ); + buts->addWidget( but ); + connect( but, SIGNAL( clicked() ), this, SLOT( slotCancel() ) ); + } +} + +void KDialogBase::setMainWidget( QWidget* top ) +{ + top->reparent( this, 0, QPoint(0,0) ); + _layout->insertWidget( 0, top ); +} + +QFrame* KDialogBase::plainPage() +{ + QFrame* frame = new QFrame( this ); + setMainWidget( frame ); + return frame; +} + +void KDialogBase::slotOk() +{ + accept(); + emit okClicked(); + emit finished(); +} + +void KDialogBase::slotCancel() +{ + reject(); + emit cancelClicked(); + emit finished(); +} + +int KMessageBox::warningYesNo(QWidget *parent, const QString &text, const QString &caption ) +{ + int code = warning( parent, caption, text, tr("No"), tr("Yes") ); + if ( code == 0 ) + return Yes; + else + return No; +} + +int KMessageBox::information( QWidget* parent, const QString& text, const QString& caption, + const QString& /*dontShowAgainName*/ ) +{ + return QMessageBox::information( parent, caption, text ); +} + +int KMessageBox::sorry( QWidget* parent, const QString& text, const QString& caption ) +{ + return QMessageBox::information( parent, caption, text ); +} + + diff --git a/kregexpeditor/qt-only/compat.h b/kregexpeditor/qt-only/compat.h new file mode 100644 index 0000000..edf9ced --- /dev/null +++ b/kregexpeditor/qt-only/compat.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef COMPAT_H +#define COMPAT_H +#include +#include +#include +#include +#include +#include + +QString i18n( const QString& a); +QString i18n( const QString& a, const QString& b); +#define isatty(x) 0 + +#define KTextBrowser QTextBrowser +#define KListBox QListBox +#define KFileDialog QFileDialog +#define KPushButton QPushButton + +class KDialogBase :public QDialog +{ + Q_OBJECT + +public: + enum ButtonCode {Ok = 1, Cancel, Help}; + enum DialogType { Plain }; + + KDialogBase ( int dialogFace, const QString &caption, int buttonMask, + ButtonCode defaultButton, + QWidget *parent=0, const char *name=0, bool modal=true ); + + KDialogBase( QWidget* parent, const char* name = 0, bool modal = true, + const QString& caption = QString::null, + int buttonMask = 0 ); + + void init( int buttonMask, ButtonCode /*defaultButton*/, const QString& caption ); + void setMainWidget( QWidget* top ); + QFrame* plainPage(); + void setHelp( const QString&, const QString& ) {} + +public slots: + void slotOk(); + void slotCancel(); + +signals: + void okClicked(); + void cancelClicked(); + void finished(); + void helpClicked(); + +private: + QVBoxLayout* _layout; +}; + +class KMessageBox :public QMessageBox +{ + Q_OBJECT +public: + enum ButtonCode { Ok = 1, Cancel = 2, Yes = 3, No = 4, Continue = 5 }; + static int warningYesNo (QWidget *parent, const QString &text, + const QString &caption = QString::null ); + static int information( QWidget* parent, const QString& text, const QString& caption = QString::null, + const QString& /*dontShowAgainName*/ = QString::null ); + static int sorry( QWidget* parent, const QString& text, const QString& caption = QString::null ); +}; + +#endif /* COMPAT_H */ + diff --git a/kregexpeditor/qt-only/compile b/kregexpeditor/qt-only/compile new file mode 100755 index 0000000..d6fb6c6 --- /dev/null +++ b/kregexpeditor/qt-only/compile @@ -0,0 +1,28 @@ +#!/bin/bash +# On Linux do this +ln -s ../*.{cpp,h,y,l} . +ln -s ../{KMultiFormListBox,KWidgetStreamer}/*.{cpp,h} . +ln -s $KDESRC/kdelibs/interfaces/kregexpeditor/kregexpeditorinterface.h . +ln -s gen_qregexpparser.cc gen_qregexpparser.cpp +touch unistd.h +mkdir icons +cp ../picts/* icons +cp $KDEDIR/share/icons/crystalsvg/22x22/actions/{undo,redo,editcut,editcopy,editpaste,fileopen,filesave,contexthelp,1downarrow,1uparrow}.png icons +mkdir predefined +mkdir predefined/General +cp ../predefined/General/*.regexp predefined/General + +flex -Pqregexp -ogen_qregexplexer.cpp qregexpparser.l +bison -d -p qregexp -o gen_qregexpparser.cc qregexpparser.y + +mkdir manual +cd manual +meinproc $KDESRC/kdeutils/doc/KRegExpEditor/index.docbook +for x in *.html; do sed 's/children(); + for ( RegExpListIt it(list); *it; ++it ) { + if ( !first ) { + res += QString::fromLatin1( "|" ); + } + first = false; + if ( markSelection && !regexp->isSelected() && (*it)->isSelected() ) { + res += QString::fromLatin1("(") + toStr( *it, markSelection ) + QString::fromLatin1(")"); + } + else { + res += toStr( *it, markSelection ); + } + } + return res; +} + +QString QtRegExpConverter::toString( ConcRegExp* regexp, bool markSelection ) +{ + QString res; + bool childSelected = false; + + RegExpList list = regexp->children(); + for ( RegExpListIt it(list); *it; ++it ) { + QString startPar = QString::fromLocal8Bit(""); + QString endPar = QString::fromLocal8Bit(""); + if ( (*it)->precedence() < regexp->precedence() ) { + if ( markSelection ) + startPar = QString::fromLocal8Bit("(?:"); + else + startPar = QString::fromLatin1( "(" ); + endPar = QString::fromLatin1( ")" ); + } + + // Note these two have different tests! They are activated in each their iteration of the loop. + if ( markSelection && !childSelected && !regexp->isSelected() && (*it)->isSelected() ) { + res += QString::fromLatin1("("); + childSelected = true; + } + + if ( markSelection && childSelected && !regexp->isSelected() && !(*it)->isSelected() ) { + res += QString::fromLatin1(")"); + childSelected= false; + } + + res += startPar + toStr( *it, markSelection ) + endPar; + } + if ( markSelection && childSelected && !regexp->isSelected() ) { + res += QString::fromLatin1(")"); + } + return res; +} + +QString QtRegExpConverter::toString( LookAheadRegExp* regexp, bool markSelection ) +{ + if ( regexp->lookAheadType() == LookAheadRegExp::POSITIVE ) + return QString::fromLatin1( "(?=" ) + toStr( regexp->child(), markSelection ) + QString::fromLocal8Bit( ")" ); + else + return QString::fromLatin1( "(?!" ) + toStr( regexp->child(), markSelection ) + QString::fromLocal8Bit( ")" ); +} + +QString QtRegExpConverter::toString( TextRangeRegExp* regexp, bool /*markSelection*/ ) +{ + QString txt; + + bool foundCarrot = false; + bool foundDash = false; + bool foundParenthesis = false; + + // Now print the rest of the single characters, but keep "^" as the very + // last element of the characters. + QStringList chars = regexp->chars(); + for (unsigned int i = 0; i< chars.count(); i++) { + if ( *chars.at(i) == QChar( ']' ) ) { + foundParenthesis = true; + } + else if ( *chars.at(i) == QChar( '-' ) ) { + foundDash = true; + } + else if ( *chars.at(i) == QChar( '^' ) ) { + foundCarrot = true; + } + else { + txt.append( *chars.at(i) ); + } + } + + // Now insert the ranges. + QPtrList ranges = regexp->range(); + for ( QPtrListIterator it(ranges); *it; ++it ) { + txt.append((*it)->first()+ QString::fromLatin1("-")+ (*it)->second()); + } + + // Ok, its time to build each part of the regexp, here comes the rule: + // if a ']' is one of the characters, then it must be the first one in the + // list (after then opening '[' and eventually negation '^') + // Next if a '-' is one of the characters, then it must come + // finally if '^' is one of the characters, then it must not be the first + // one! + + QString res = QString::fromLatin1("["); + + if ( regexp->negate() ) + res.append(QString::fromLatin1("^")); + + + // a ']' must be the first character in teh range. + if ( foundParenthesis ) { + res.append(QString::fromLatin1("]")); + } + + // a '-' must be the first character ( only coming after a ']') + if ( foundDash ) { + res.append(QString::fromLatin1("-")); + } + + res += txt; + + // Insert \s,\S,\d,\D,\w, and \W + if ( regexp->digit() ) + res += QString::fromLocal8Bit("\\d"); + if ( regexp->nonDigit() ) + res += QString::fromLocal8Bit("\\D"); + if ( regexp->space() ) + res += QString::fromLocal8Bit("\\s"); + if ( regexp->nonSpace() ) + res += QString::fromLocal8Bit("\\S"); + if ( regexp->wordChar() ) + res += QString::fromLocal8Bit("\\w"); + if ( regexp->nonWordChar() ) + res += QString::fromLocal8Bit("\\W"); + + + if ( foundCarrot ) { + res.append( QChar( '^' ) ); + } + + res.append(QString::fromLatin1("]")); + + return res; +} + +QString QtRegExpConverter::toString( CompoundRegExp* regexp, bool markSelection ) +{ + if ( markSelection && !regexp->isSelected() && regexp->child()->isSelected() ) + return QString::fromLatin1( "(" ) + toStr( regexp->child(), markSelection ) + QString::fromLatin1( ")" ); + else + return toStr( regexp->child(), markSelection ); +} + +QString QtRegExpConverter::toString( DotRegExp* /*regexp*/, bool /*markSelection*/ ) +{ + return QString::fromLatin1( "." ); +} + +QString QtRegExpConverter::toString( PositionRegExp* regexp, bool /*markSelection*/ ) +{ + switch (regexp->position()) { + case PositionRegExp::BEGLINE: + return QString::fromLatin1("^"); + case PositionRegExp::ENDLINE: + return QString::fromLatin1("$"); + case PositionRegExp::WORDBOUNDARY: + return QString::fromLatin1("\\b"); + case PositionRegExp::NONWORDBOUNDARY: + return QString::fromLatin1("\\B"); + } + Q_ASSERT( false ); + return QString::fromLatin1(""); +} + +QString QtRegExpConverter::toString( RepeatRegExp* regexp, bool markSelection ) +{ + RegExp* child = regexp->child(); + QString cText = toStr( child, markSelection ); + QString startPar; + QString endPar; + + if ( markSelection ) { + if ( !regexp->isSelected() && child->isSelected()) { + startPar = QString::fromLatin1( "(" ); + endPar = QString::fromLatin1( ")" ); + } + else if ( child->precedence() < regexp->precedence() ) { + startPar = QString::fromLatin1( "(?:" ); + endPar = QString::fromLatin1( ")" ); + } + } + else if ( child->precedence() < regexp->precedence() ) { + startPar = QString::fromLatin1( "(" ); + endPar = QString::fromLatin1( ")" ); + } + + if ( regexp->min() == 0 && regexp->max() == -1) { + return startPar + cText +endPar + QString::fromLocal8Bit("*"); + } + else if ( regexp->min() == 0 && regexp->max() == 1 ) { + return startPar + cText + endPar + QString::fromLocal8Bit("?"); + } + else if ( regexp->min() == 1 && regexp->max() == -1 ) { + return startPar + cText + endPar + QString::fromLocal8Bit("+"); + } + else if ( regexp->max() == -1 ) { + return startPar + cText + endPar + QString::fromLocal8Bit("{") + + QString::number( regexp->min() ) + QString::fromLocal8Bit(",") + + QString::fromLocal8Bit("}"); + } + else { + return startPar + cText + endPar + QString::fromLocal8Bit("{") + + QString::number( regexp->min() ) + QString::fromLocal8Bit(",") + + QString::number( regexp->max() ) + QString::fromLocal8Bit("}"); + } +} + +QString QtRegExpConverter::toString( TextRegExp* regexp, bool /*markSelection*/ ) +{ + QValueList list; + list << QChar('$') + << QChar('^') + << QChar('.') + << QChar('*') + << QChar('+') + << QChar('?') + << QChar('[') + << QChar(']') + << QChar('\\') + << QChar('{') + << QChar('}') + << QChar('(') + << QChar(')') + << QChar('|'); + + QString res = escape( regexp->text(), list, QChar('\\') ); + return res; +} + +QString QtRegExpConverter::name() +{ + return QString::fromLatin1( "Qt" ); +} + +int QtRegExpConverter::features() +{ + return WordBoundary | NonWordBoundary | PosLookAhead | NegLookAhead | CharacterRangeNonItems | ExtRange; +} + +RegexpHighlighter* QtRegExpConverter::highlighter( QTextEdit* edit ) +{ + return new QtRegexpHighlighter( edit ); +} diff --git a/kregexpeditor/qtregexpconverter.h b/kregexpeditor/qtregexpconverter.h new file mode 100644 index 0000000..100dcf3 --- /dev/null +++ b/kregexpeditor/qtregexpconverter.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef QTREGEXPCONVERTER_H +#define QTREGEXPCONVERTER_H +#include "regexpconverter.h" + +class QtRegExpConverter :public RegExpConverter +{ +public: + virtual bool canParse(); + virtual RegExp* parse( const QString&, bool* ok ); + virtual QString name(); + virtual int features(); + virtual QString toString( AltnRegExp*, bool markSelection ); + virtual QString toString( ConcRegExp*, bool markSelection ); + virtual QString toString( LookAheadRegExp*, bool markSelection ); + virtual QString toString( TextRangeRegExp*, bool markSelection ); + virtual QString toString( CompoundRegExp*, bool markSelection ); + virtual QString toString( DotRegExp*, bool markSelection ); + virtual QString toString( PositionRegExp*, bool markSelection ); + virtual QString toString( RepeatRegExp*, bool markSelection ); + virtual QString toString( TextRegExp*, bool markSelection ); + RegexpHighlighter* highlighter( QTextEdit* edit ); +}; + +#endif /* QTREGEXPCONVERTER_H */ + diff --git a/kregexpeditor/qtregexphighlighter.cpp b/kregexpeditor/qtregexphighlighter.cpp new file mode 100644 index 0000000..1983b89 --- /dev/null +++ b/kregexpeditor/qtregexphighlighter.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "qtregexphighlighter.h" +#include +QtRegexpHighlighter::QtRegexpHighlighter( QTextEdit* editor ) + :RegexpHighlighter( editor ), _editor( editor ) +{ +} + +int QtRegexpHighlighter::highlightParagraph( const QString & text, int endStateOfLastPara ) +{ + QRegExp regexp( _regexp ); + regexp.setCaseSensitive( _caseSensitive ); + regexp.setMinimal( _minimal ); + + setFormat( 0, text.length(), _editor->font(), Qt::black ); + + if ( !regexp.isValid() || regexp.isEmpty() ) { + return 0; + } + + // ------------------------------ Process with the regular expression. + QColor colors[] = { Qt::red, Qt::blue }; + int color = endStateOfLastPara; + if ( color < 0 || color > 1 ) + color = 0; + + int index = 0; + int start, length; + while ( (index = regexp.search( text, index ) ) != -1 && index < (int) text.length()) { + if ( regexp.pos(1) != -1 ) { + start = regexp.pos(1); + length = regexp.cap(1).length(); + } + else { + start = index; + length = regexp.matchedLength(); + } + + if ( start != index ) + setFormat( index, start-index, colors[color] ); + + QFont font = _editor->font(); + font.setUnderline( true ); + font.setPointSize( (int) (font.pointSize() * 1.3) ); + setFormat( start, length, font, colors[color] ); + + if ( length + (start-index) != regexp.matchedLength() ) + setFormat( start+length, regexp.matchedLength()-length-(start-index), colors[color] ); + + index += QMAX( 1, regexp.matchedLength() ); // ensure progress when matching for example ^ or \b + color = (color+1)%2; + } + return color; +} + diff --git a/kregexpeditor/qtregexphighlighter.h b/kregexpeditor/qtregexphighlighter.h new file mode 100644 index 0000000..bb57bda --- /dev/null +++ b/kregexpeditor/qtregexphighlighter.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef QTREGEXPHIGHLIGHTER_H +#define QTREGEXPHIGHLIGHTER_H +#include "regexphighlighter.h" +#include + +class QtRegexpHighlighter :public RegexpHighlighter +{ +public: + QtRegexpHighlighter( QTextEdit* verifier ); + virtual int highlightParagraph ( const QString & text, int endStateOfLastPara ); + +private: + QTextEdit* _editor; +}; + +#endif /* QTREGEXPHIGHLIGHTER_H */ + diff --git a/kregexpeditor/regexp.cpp b/kregexpeditor/regexp.cpp new file mode 100644 index 0000000..31450f1 --- /dev/null +++ b/kregexpeditor/regexp.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include "regexp.h" +#include "widgetfactory.h" +#include "kregexpeditorgui.h" +#include "errormap.h" + +RegExp::RegExp( bool selected ) : _parent(0), _destructing( false ), _selected( selected ) +{ + // Nothing to do +} + +RegExp::~RegExp() +{ + _destructing = true; + for ( QPtrListIterator it(_children); *it; ++it ) { + delete *it; + } + if ( _parent ) + _parent->removeChild( this ); + _parent = 0; +} + +void RegExp::addChild( RegExp* child ) +{ + _children.append( child ); + child->setParent( this ); +} + +void RegExp::removeChild( RegExp* child ) +{ + if ( ! _destructing ) { + _children.remove( child ); + } +} + +void RegExp::setParent( RegExp* parent ) +{ + _parent = parent; +} + +RegExp* RegExp::readRegExp( QDomElement top, const QString& version ) +{ + for ( QDomNode node = top.firstChild(); !node.isNull(); node = node.nextSibling() ) { + if (!node.isElement() ) + continue; // skip past comments + RegExp* regexp = WidgetFactory::createRegExp(node.toElement(), version ); + return regexp; + } + return 0; +} + +QString RegExp::toXmlString() const +{ + QDomDocument doc; + doc.setContent( QString::fromLatin1( "" ) ); + QDomNode top = doc.documentElement(); + top.toElement().setAttribute(QString::fromLocal8Bit("version"), KRegExpEditorGUI::version); + + QDomNode elm = toXml( &doc ); + + top.appendChild( elm ); + QString xmlString = QString::fromLocal8Bit("\n\n") + doc.toString(); + + return xmlString; +} + +RegExp* RegExp::clone() const +{ + return WidgetFactory::createRegExp( toXmlString() ); +} + +void RegExp::check( ErrorMap& map ) +{ + map.start(); + check( map, true, true ); + map.end(); +} + + diff --git a/kregexpeditor/regexp.h b/kregexpeditor/regexp.h new file mode 100644 index 0000000..86bd796 --- /dev/null +++ b/kregexpeditor/regexp.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef REGEXP_H +#define REGEXP_H + +#include +#include + +class CompoundRegExp; +class ErrorMap; + +/** + Abstract syntax tree for regular expressions. + @internal +*/ +class RegExp +{ +public: + RegExp( bool selected ); + virtual ~RegExp(); + + virtual int precedence() const = 0; + virtual QDomNode toXml( QDomDocument* doc ) const = 0; + virtual bool load( QDomElement, const QString& version ) = 0; + QString toXmlString() const; + + void check( ErrorMap& ); + virtual bool check( ErrorMap&, bool first, bool last ) = 0; + + void addChild( RegExp* child ); + void removeChild( RegExp* child ); + void setParent( RegExp* parent ); + RegExp* clone() const; + virtual bool operator==( const RegExp& other ) const { return ( type() == other.type() ); } + + enum RegExpType { CONC, TEXT, DOT, POSITION, REPEAT, ALTN, COMPOUND, LOOKAHEAD, TEXTRANGE }; + virtual RegExpType type() const = 0; + virtual void replacePart( CompoundRegExp* /* replacement */ ) {} + bool isSelected() const { return _selected; } + void setSelected( bool b ) { _selected = b; } + +protected: + RegExp* readRegExp( QDomElement top, const QString& version ); + +private: + RegExp() {} // disable + QPtrList _children; + RegExp* _parent; + bool _destructing; + bool _selected; +}; + +typedef QPtrList RegExpList; +typedef QPtrListIterator RegExpListIt; + +#endif // REGEXP_H + diff --git a/kregexpeditor/regexpbuttons.cpp b/kregexpeditor/regexpbuttons.cpp new file mode 100644 index 0000000..eae7da0 --- /dev/null +++ b/kregexpeditor/regexpbuttons.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" + #include "images.h" +#else + #include + #include + #include + #include "regexpbuttons.moc" +#endif + +#include "regexpbuttons.h" +#include "dcbutton.h" +#include +#include +#include +#include +#include +#include "regexpconverter.h" + +RegExpButtons::RegExpButtons( QWidget *parent, const char *name ) + : QDockWindow( QDockWindow::InDock, parent, name), _keepMode(false) +{ + QBoxLayout *layout = boxLayout(); + + _grp = new QButtonGroup(this); + _grp->hide(); + _grp->setExclusive( true ); + + _mapper = new QSignalMapper( this, "RegExpButtons::_mapper" ); + connect( _mapper, SIGNAL( mapped(int) ), this, SIGNAL( clicked(int) ) ); + + // The "select" button. + _selectBut = new QToolButton( this); + +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage( "select" ) ); +#else + QPixmap pix = KGlobal::iconLoader()->loadIcon(locate("data", QString::fromLatin1("kregexpeditor/pics/select.png") ), KIcon::Toolbar ); +#endif + + _selectBut->setPixmap( pix ); + layout->addWidget( _selectBut ); + _grp->insert(_selectBut); + _selectBut->setToggleButton( true ); + connect( _selectBut, SIGNAL(clicked()), SIGNAL(doSelect())); + connect( _selectBut, SIGNAL(clicked()), this, SLOT(slotSetNonKeepMode()) ); + + QToolTip::add( _selectBut, i18n("Selection tool")); + QWhatsThis::add( _selectBut, i18n("This will change the state of the editor to selection state.

" + "In this state you will not be inserting regexp items, but instead select them. " + "To select a number of items, press down the left mouse button and drag it over the items.

" + "When you have selected a number of items, you may use cut/copy/paste. These functions are " + "found in the right mouse button menu.")); + + // Insert buttons. + DoubleClickButton* but; + + but = insert(TEXT, "text", i18n("Text"), + i18n( "This will insert a text field, where you may write text. The text you write will " + "be matched literally. (i.e. you do not need to escape any characters)" ) ); + layout->addWidget( but ); + + + but = insert(CHARSET, "characters", i18n("A single character specified in a range"), + i18n("This will match a single character from a predefined range.

" + "When you insert this widget a dialog box will appear, which lets you specify " + "which characters this regexp item will match.") ); + layout->addWidget( but ); + + + but = insert(DOT, "anychar", i18n("Any character"), + i18n("This will match any single character") ); + layout->addWidget( but ); + + + but = insert(REPEAT, "repeat", i18n("Repeated content"), + i18n("This regexp item will repeat the regexp items it surrounds " + "a specified number of times.

" + "The number of times to repeat may be specified using ranges. e.g. You may specify " + "that it should match from 2 to 4 times, that it should match exactly 5 times, or " + "that it should match at least one time.

" + "Examples:
" + "If you specify that it should match any time, and the content it surrounds " + "is abc, then this regexp item will match the empty string, " + "the string abc, the string abcabc, the string abcabcabcabc, " + "etc.") ); + layout->addWidget( but ); + + + but = insert(ALTN, "altn", i18n("Alternatives"), + i18n("This regexp item will match any of its alternatives.

" + "You specify alternatives by placing regexp items on top of " + "each other inside this widget.") ); + layout->addWidget( but ); + + + but = insert(COMPOUND, "compound", i18n("Compound regexp"), + i18n("This regexp item serves two purposes:" + "
  • It makes it possible for you to collapse a huge regexp item into " + "a small box. This makes it easier for you to get an overview of large " + "regexp items. This is especially useful if you load a predefined regexp item " + "you perhaps don't care about the inner workings of.") ); + layout->addWidget( but ); + + + but = insert(BEGLINE, "begline", i18n("Beginning of line"), + i18n("This will match the beginning of a line.") ); + layout->addWidget( but ); + + + but = insert(ENDLINE, "endline", i18n("End of line"), + i18n("This will match the end of a line.") ); + layout->addWidget( but ); + + + _wordBoundary = insert(WORDBOUNDARY, "wordboundary", i18n("Word boundary"), + i18n("This asserts a word boundary (This part does not actually match any characters)") ); + layout->addWidget( _wordBoundary ); + + _nonWordBoundary = insert(NONWORDBOUNDARY, "nonwordboundary", i18n("Non Word boundary"), + i18n("This asserts a non-word boundary " + "(This part does not actually match any characters)") ); + layout->addWidget( _nonWordBoundary ); + + _posLookAhead = insert(POSLOOKAHEAD, "poslookahead", i18n("Positive Look Ahead"), + i18n("This asserts a regular expression (This part does not actually match any characters). " + "You can only use this at the end of a regular expression.") ); + layout->addWidget( _posLookAhead ); + + _negLookAhead = insert(NEGLOOKAHEAD, "neglookahead", i18n("Negative Look Ahead"), + i18n("This asserts a regular expression that must not match " + "(This part does not actually match any characters). " + "You can only use this at the end of a regular expression.") ); + layout->addWidget( _negLookAhead ); +} + +DoubleClickButton* RegExpButtons::insert(RegExpType tp, const char* name, QString tooltip, QString whatsthis) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage( QString::fromLatin1( name ) ) ); +#else + QPixmap pix = KGlobal::iconLoader()->loadIcon(locate("data", QString::fromLatin1("kregexpeditor/pics/")+QString::fromLatin1(name) + + QString::fromLatin1(".png") ), KIcon::Toolbar ); +#endif + + DoubleClickButton* but = new DoubleClickButton( pix, this, "RegExpButtons::but"); + + _mapper->setMapping( but, tp ); + + connect( but, SIGNAL( clicked() ), _mapper, SLOT( map() ) ); + connect( but, SIGNAL( clicked() ), this, SLOT( slotSetNonKeepMode() ) ); + connect( but, SIGNAL( doubleClicked() ), this, SLOT( slotSetKeepMode() ) ); + + _grp->insert( but ); + but->setToggleButton( true ); + QToolTip::add( but, tooltip ); + QWhatsThis::add( but, whatsthis ); + + return but; +} + +void RegExpButtons::slotUnSelect() +{ + if ( _grp->selected() ) { + QToolButton *pb = static_cast(_grp->selected()); + if (pb) { + pb->setOn( false ); + } + } +} + +void RegExpButtons::slotSetKeepMode( ) +{ + _keepMode = true; +} + +void RegExpButtons::slotSetNonKeepMode( ) +{ + _keepMode = false; +} + +void RegExpButtons::slotSelectNewAction() +{ + if ( ! _keepMode ) { + emit doSelect(); + _grp->setButton(_grp->id(_selectBut)); + } +} + +void RegExpButtons::setFeatures( int features ) +{ + _wordBoundary->setShown( features & RegExpConverter::WordBoundary ); + _nonWordBoundary->setShown( features & RegExpConverter::NonWordBoundary ); + _posLookAhead->setShown( features & RegExpConverter::PosLookAhead ); + _negLookAhead->setShown( features & RegExpConverter::NegLookAhead ); + +} + diff --git a/kregexpeditor/regexpbuttons.h b/kregexpeditor/regexpbuttons.h new file mode 100644 index 0000000..5671810 --- /dev/null +++ b/kregexpeditor/regexpbuttons.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __REGEXPBUTTONS_H +#define __REGEXPBUTTONS_H + +#include +#include "widgetfactory.h" +class DoubleClickButton; +class QButtonGroup; +class QToolButton; +class QSignalMapper; + + +class RegExpButtons :public QDockWindow +{ + Q_OBJECT + +public: + RegExpButtons( QWidget *parent, const char *name = 0 ); + void setFeatures( int features ); + +protected: + DoubleClickButton* insert(RegExpType tp, const char* file, QString tooltip, QString whatsthis); + +public slots: + void slotSelectNewAction(); + void slotUnSelect(); + +protected slots: + void slotSetKeepMode(); + void slotSetNonKeepMode(); + +signals: + void clicked( int ); + void doSelect(); + +private: + QButtonGroup* _grp; + QToolButton* _selectBut; + QToolButton* _wordBoundary; + QToolButton* _nonWordBoundary; + QToolButton* _posLookAhead; + QToolButton* _negLookAhead; + QSignalMapper* _mapper; // single click Mapper. + + /** + This variable is true if the use wishes to continue editing in the + selected mode after the previous editing is completed (that is, if the + user has double clicked the buttons). + */ + bool _keepMode; +}; + + +#endif // __REGEXPBUTTON_H diff --git a/kregexpeditor/regexpconverter.cpp b/kregexpeditor/regexpconverter.cpp new file mode 100644 index 0000000..2d53e20 --- /dev/null +++ b/kregexpeditor/regexpconverter.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "regexpconverter.h" + +#include "altnregexp.h" +#include "concregexp.h" +#include "lookaheadregexp.h" +#include "textrangeregexp.h" +#include "compoundregexp.h" +#include "dotregexp.h" +#include "positionregexp.h" +#include "repeatregexp.h" +#include "textregexp.h" +#include +#include "regexphighlighter.h" + +RegExpConverter* RegExpConverter::_current = 0; +RegExp* RegExpConverter::parse( const QString&, bool* ok ) +{ + ok = false; + return new DotRegExp( false ); // This method should never be called. +} + +// This function needs to be called toStr rather than toString, as it is not possible to +// over load function across inheritance! +QString RegExpConverter::toStr( RegExp* regexp, bool markSelection ) +{ + switch (regexp->type()) { + case RegExp::CONC: return toString( static_cast( regexp ), markSelection); + case RegExp::TEXT: return toString( static_cast( regexp ), markSelection ); + case RegExp::DOT: return toString( static_cast( regexp ), markSelection ); + case RegExp::POSITION: return toString( static_cast( regexp ), markSelection ); + case RegExp::REPEAT: return toString( static_cast( regexp ), markSelection ); + case RegExp::ALTN: return toString( static_cast( regexp ), markSelection ); + case RegExp::COMPOUND: return toString( static_cast( regexp ), markSelection ); + case RegExp::LOOKAHEAD: return toString( static_cast( regexp ), markSelection ); + case RegExp::TEXTRANGE: return toString( static_cast( regexp ), markSelection ); + } + qWarning("We shouldn't get here!"); + return QString::fromLatin1( "" ); +} + + +QString RegExpConverter::escape( QString text, QValueList chars, QChar escapeChar) const +{ + QString res; + for (unsigned int i=0; i + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef REGEXPCONVERTER_H +#define REGEXPCONVERTER_H + +#include +#include + +class QTextEdit; +class AltnRegExp; +class ConcRegExp; +class LookAheadRegExp; +class TextRangeRegExp; +class CompoundRegExp; +class DotRegExp; +class PositionRegExp; +class RepeatRegExp; +class TextRegExp; +class RegexpHighlighter; +class RegExp; + +class RegExpConverter +{ +public: + enum Features { + WordBoundary = 0x01, + NonWordBoundary = 0x02, + WordStart = 0x04, + WordEnd = 0x08, + PosLookAhead = 0x10, + NegLookAhead = 0x20, + CharacterRangeNonItems = 0x40, + ExtRange = 0x80 + }; + + virtual bool canParse() = 0; + virtual QString name() = 0; + virtual int features() = 0; + virtual RegExp* parse( const QString&, bool* ok ); + QString toStr( RegExp*, bool markSelection ); + virtual RegexpHighlighter* highlighter( QTextEdit* ); + + static void setCurrent( RegExpConverter* ); + static RegExpConverter* current(); + +protected: + virtual QString toString( AltnRegExp*, bool markSelection ) = 0; + virtual QString toString( ConcRegExp*, bool markSelection ) = 0; + virtual QString toString( LookAheadRegExp*, bool markSelection ) = 0; + virtual QString toString( TextRangeRegExp*, bool markSelection ) = 0; + virtual QString toString( CompoundRegExp*, bool markSelection ) = 0; + virtual QString toString( DotRegExp*, bool markSelection ) = 0; + virtual QString toString( PositionRegExp*, bool markSelection ) = 0; + virtual QString toString( RepeatRegExp*, bool markSelection ) = 0; + virtual QString toString( TextRegExp*, bool markSelection ) = 0; + QString escape( QString text, QValueList chars, QChar escapeChar) const; + +private: + static RegExpConverter* _current; +}; + +#endif /* REGEXPCONVERTER_H */ + diff --git a/kregexpeditor/regexphighlighter.cpp b/kregexpeditor/regexphighlighter.cpp new file mode 100644 index 0000000..3034ee1 --- /dev/null +++ b/kregexpeditor/regexphighlighter.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "regexphighlighter.h" + +RegexpHighlighter::RegexpHighlighter( QTextEdit* edit ) + :QSyntaxHighlighter( edit ), _caseSensitive( false ), _minimal( false ) +{ +} + +void RegexpHighlighter::setRegExp( const QString& regexp ) +{ + _regexp = regexp; +} + +void RegexpHighlighter::setCaseSensitive( bool b ) +{ + _caseSensitive = b; +} + +void RegexpHighlighter::setMinimal( bool b ) +{ + _minimal = b; +} + + + + + diff --git a/kregexpeditor/regexphighlighter.h b/kregexpeditor/regexphighlighter.h new file mode 100644 index 0000000..92219b1 --- /dev/null +++ b/kregexpeditor/regexphighlighter.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef REGEXPHIGHLIGHTER_H +#define REGEXPHIGHLIGHTER_H +#include + +class RegexpHighlighter :public QSyntaxHighlighter +{ +public: + RegexpHighlighter( QTextEdit* edit ); + void setRegExp( const QString& regexp ); + void setCaseSensitive( bool ); + void setMinimal( bool ); + +protected: + QString _regexp; + bool _caseSensitive, _minimal; + +}; + +#endif /* REGEXPHIGHLIGHTER_H */ + diff --git a/kregexpeditor/regexpwidget.cpp b/kregexpeditor/regexpwidget.cpp new file mode 100644 index 0000000..2ee2aa7 --- /dev/null +++ b/kregexpeditor/regexpwidget.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include "regexpwidget.moc" +#endif + +#include "regexpwidget.h" +#include +#include +#include +#include "concwidget.h" +#include "dragaccepter.h" + +const int RegExpWidget::pw = 1; +const int RegExpWidget::bdSize = 5; +const int RegExpWidget::space = 5; + +RegExpWidget::RegExpWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : QWidget(parent, name ? name : "RegExpWidget", WNoMousePropagation ), + _editorWindow( editorWindow ), _isSelected( false ), _isToplevel( false ) +{ +} + + +void RegExpWidget::addNewChild(DragAccepter *, RegExpWidget *) +{ + qFatal("This widget should not expect any children"); +} + +void RegExpWidget::addNewConcChild(DragAccepter *, ConcWidget *) +{ + qFatal("This widget should not expect any children"); +} + +void RegExpWidget::setConcChild(ConcWidget *) +{ + qFatal("This widget should not expect any children"); +} + +bool RegExpWidget::updateSelection(bool parentSelected) +{ + bool selected = ( parentSelected || + _editorWindow->selectionOverlap( mapToGlobal( QPoint(0,0) ), size() ) ) + && !_isToplevel; + + if ( _isSelected != selected ) { + // Selection state changed + _isSelected = selected; + repaint(); + return true; + } + return false; +} + +void RegExpWidget::drawPossibleSelection( QPainter& painter, QSize mySize ) +{ + if ( _isSelected ) { + painter.fillRect( 0, 0, mySize.width(), mySize.height(), QBrush( gray ) ); + } +} + +bool RegExpWidget::isSelected() const +{ + return _isSelected; +} + +bool RegExpWidget::hasSelection() const +{ + return _isSelected; +} + +void RegExpWidget::clearSelection() +{ + _isSelected = false; +} + +void RegExpWidget::applyRegExpToSelection( RegExpType ) +{ + qFatal("This method should not be called for this widget"); +} + +void RegExpWidget::deleteSelection() +{ + qFatal("This method should be overridden if needed!"); +} + +RegExp* RegExpWidget::selection() const +{ + return regExp(); +} + +int RegExpWidget::edit() +{ + qFatal("This method should be overridden if needed!"); + return 0; // Compiler shut up +} + +void RegExpWidget::mousePressEvent ( QMouseEvent* event ) +{ + if ( _editorWindow->isPasteing() || _editorWindow->isInserting() ) + return; + + if ( event->button() == LeftButton ) { + if ( ! _editorWindow->pointSelected( QCursor::pos() ) ) { + _editorWindow->clearSelection( true ); + if ( dynamic_cast(this) == 0 && dynamic_cast(this) == 0 ) { + selectWidget( true ); + } + } + + QMouseEvent ev( event->type(), mapTo(_editorWindow, event->pos()), + event->button(), event->state()); + QApplication::sendEvent( _editorWindow, &ev ); + } + else if ( event->button() == RightButton ) { + _editorWindow->showRMBMenu( true ); + } + + // currently (Qt3.0) it seems like qt do not accept that the accept flag is set, + // and thus sends the event to the parent - given that the following line is in. + // It doesn't make any change to leave it out. + // 25 Oct. 2001 19:03 -- Jesper K. Pedersen + // QWidget::mousePressEvent( event ); +} + +void RegExpWidget::mouseReleaseEvent( QMouseEvent* ) +{ + if ( _editorWindow->isInserting() && acceptWidgetInsert( _editorWindow->insertType() ) ) { + if ( !_editorWindow->hasSelection() ) + _isSelected = true; + + _editorWindow->applyRegExpToSelection( _editorWindow->insertType() ); + _editorWindow->clearSelection( true ); + _editorWindow->updateContent( this ); + _editorWindow->slotEndActions(); + _editorWindow->updateCursorUnderPoint(); + } +} + +QRect RegExpWidget::selectionRect() const +{ + return QRect( mapToGlobal( QPoint(0,0) ), size() ); +} + + +void RegExpWidget::enterEvent( QEvent * ) +{ + updateCursorShape(); +} + +void RegExpWidget::updateCursorShape() +{ + QCursor cursor; + + if ( _editorWindow->isPasteing() ) { + if ( acceptWidgetPaste() ) + cursor = CrossCursor; + else + cursor = ForbiddenCursor; + } + else if ( _editorWindow->isInserting() ) { + if ( acceptWidgetInsert( _editorWindow->insertType() ) ) + cursor = CrossCursor; + else + cursor = ForbiddenCursor; + } + else + cursor = arrowCursor; + + setCursor( cursor ); +} + +void RegExpWidget::updateCursorRecursively() +{ + updateCursorShape(); +} + + +bool RegExpWidget::acceptWidgetPaste() const +{ + return false; +} + +bool RegExpWidget::acceptWidgetInsert( RegExpType tp ) const +{ + return WidgetFactory::isContainer( tp ); +} + +RegExpWidget* RegExpWidget::widgetUnderPoint( QPoint globalPos, bool ) +{ + if ( QRect(mapToGlobal( QPoint(0,0) ), size() ).contains( globalPos ) ) + return this; + else + return 0; +} + +void RegExpWidget::selectWidget( bool sel) +{ + _isSelected = sel; + update(); +} + +void RegExpWidget::updateAll() +{ + update(); +} + + diff --git a/kregexpeditor/regexpwidget.h b/kregexpeditor/regexpwidget.h new file mode 100644 index 0000000..e0c038d --- /dev/null +++ b/kregexpeditor/regexpwidget.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __regexpwidget +#define __regexpwidget + +#include "editorwindow.h" + +class DragAccepter; +class RegExp; +class ConcWidget; +class RegExpEditorWindow; + +/** + Base class for all regular expression widgets. + @internal +*/ +class RegExpWidget :public QWidget +{ +Q_OBJECT + +public: + RegExpWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *label = 0); + + /*====================================================================== + Construction, child management + ======================================================================*/ + /** + Add `child' to the parent of this widget in place of `accepter' + This method only applies to container widgets (see @ref + SingleContainerWidget, and @ref MultiContainerWidget). + */ + virtual void addNewChild(DragAccepter *accepter, RegExpWidget *child); + + /** + Inserts all the children of `child' into this widget in place of + `accepter'. + This method only applies to container widgets (see @ref + SingleContainerWidget, and @ref MultiContainerWidget). + */ + virtual void addNewConcChild(DragAccepter *accepter, ConcWidget *child); + + /** + Set `child' as the ConcWidget. This method should only be invoked when + the widget has just been constructed. + This method only applies to container widgets (see @ref + SingleContainerWidget, and @ref MultiContainerWidget). + */ + virtual void setConcChild(ConcWidget *child); + + /* ====================================================================== + Selection + ======================================================================*/ + + /** + Marks this widget as being the immediate child of the editor + window. That is the topmost regular expression widget. + + This information is necessary when drawing the widget, and when + drawing the selection. + */ + void setToplevel() { _isToplevel = true; } + + /** + Returns true if this widget is selected. + */ + virtual bool isSelected() const; + + /** + Returns true if this widget or one of its children is selected. + */ + virtual bool hasSelection() const; + + virtual void updateAll(); + + /** + Update selection information for this widget. + @param parentSelected indicates whether the parent is selected. + @return true if the selection state has changed for the widget since + the last time the widget was painted. `repaint' is invoked on the widget if + selection state is changed, to ensure that selection is visible. + */ + virtual bool updateSelection(bool parentSelected); + + /** + Clears the selection and repaints the widget if `update' is true. + */ + virtual void clearSelection(); + + /** + Deletes the regexp widgets containing selection. + */ + virtual void deleteSelection(); + + /** + See @ref RegExpEditorWindow::applyRegExpToSelection + */ + virtual void applyRegExpToSelection( RegExpType type ); + + /** + Validate that selection is OK. Returns false if not. + + Only one alternative may be selected in @ref AltnWidget. This + limitation is to make implementation of a number of functions simpler. + */ + virtual bool validateSelection() const { return true; } + + /** + Returns the rectangle which makes up the selection. + */ + virtual QRect selectionRect() const; + + /** Selects the RegExp widget and all its chidlren*/ + virtual void selectWidget( bool sel ); + + /*====================================================================== + Misc + ======================================================================*/ + + /** Returns the RegExp widget, which is rooted in this regexp widget. */ + virtual RegExp* regExp() const = 0; + + /** returns the current selection */ + virtual RegExp* selection() const; + + /** returns the type of this regular expression widget. */ + virtual RegExpType type() const = 0; + + /** + updates the cursor to be one of + @li normal selection cursor + @li accept cursor for insert/paste + @li reject cursor for insert/paste + */ + void updateCursorShape(); + + virtual void updateCursorRecursively(); + + /** + Returns the regexp widget under point. If `justVisibleWidgets' is + true, @ref ConcWidget is ignored. That is, a ConcWidget will not be returned. + */ + virtual RegExpWidget* widgetUnderPoint( QPoint globalPos, bool justVisibleWidgets ); + + /** + Returns the widget under point which can be edited. That is the + "innermost" widget editable. + */ + virtual RegExpWidget* findWidgetToEdit( QPoint /* globalPos */) { return 0; } + + /** + Edits the current widget. That is, bring up the dialog, which is + available for @ref ConcWidget, @ref CompoundWidget, and @ref + CharactersWidget. + */ + virtual int edit(); + +protected: + /** Draws a selection rectangle for the current widget. */ + virtual void drawPossibleSelection( QPainter& painter, QSize mySize); + + /** Returns true if the widget accepts paste actions. */ + virtual bool acceptWidgetPaste() const; + + /** + Returns true if the widget accept the given RegExpType to be inserted + */ + virtual bool acceptWidgetInsert( RegExpType ) const; + + virtual void mousePressEvent ( QMouseEvent* event ); + + virtual void mouseReleaseEvent( QMouseEvent* ); + virtual void enterEvent( QEvent * ); + + RegExpEditorWindow* _editorWindow; + + /** True if the widget is selected. */ + bool _isSelected; + + /** See @ref setToplevel */ + bool _isToplevel; + + static const int pw; // width of pen + static const int bdSize; // width between borders and text etc. + static const int space; // TODO. +}; + +#endif // __regexpwidget diff --git a/kregexpeditor/repeatregexp.cpp b/kregexpeditor/repeatregexp.cpp new file mode 100644 index 0000000..d58736c --- /dev/null +++ b/kregexpeditor/repeatregexp.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include "kmessagebox.h" + #include +#endif + +#include "repeatregexp.h" + +RepeatRegExp::RepeatRegExp( bool selected, int lower, int upper, RegExp* child) : RegExp( selected ) +{ + _lower = lower; + _upper = upper; + _child = child; + if (child) + addChild( child ); +} + +bool RepeatRegExp::check( ErrorMap& map, bool first, bool last ) +{ + _child->check( map, first, last ); + return ( _lower == 0 ); +} + +QDomNode RepeatRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement( QString::fromLocal8Bit("Repeat") ); + top.setAttribute( QString::fromLocal8Bit("lower"), _lower ); + top.setAttribute( QString::fromLocal8Bit("upper"), _upper ); + top.appendChild( _child->toXml( doc ) ); + return top; +} + +bool RepeatRegExp::load( QDomElement top, const QString& version ) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit( "Repeat" ) ); + QString lower = top.attribute( QString::fromLocal8Bit("lower"), QString::fromLocal8Bit("0") ); + QString upper = top.attribute( QString::fromLocal8Bit("upper"), QString::fromLocal8Bit("0") ); + bool ok; + _lower = lower.toInt( &ok ); + if ( !ok ) { + KMessageBox::sorry( 0, i18n("

    Value for attribute %1 was not an integer for element " + "%2

    It contained the value %3

    ") + .arg(QString::fromLatin1("lower")).arg(QString::fromLatin1("Repeat")).arg(lower), + i18n("Error While Loading From XML File") ) ; + _lower = 0; + } + _upper = upper.toInt( &ok ); + if ( !ok ) { + KMessageBox::sorry( 0, i18n("

    Value for attribute %1 was not an integer for element " + "%2

    It contained the value %3

    ") + .arg(QString::fromLatin1("upper")).arg(QString::fromLatin1("Repeat")).arg(upper), + i18n("Error While Loading From XML File") ) ; + _upper = -1; + } + + _child = readRegExp( top, version ); + if ( _child ) { + addChild( _child ); + return true; + } + else + return false; +} + +bool RepeatRegExp::operator==( const RegExp& other ) const +{ + if ( type() != other.type() ) + return false; + + const RepeatRegExp& theOther = dynamic_cast( other ); + if ( _lower != theOther._lower || _upper != theOther._upper ) + return false; + + return (*_child == *(theOther._child) ); +} + diff --git a/kregexpeditor/repeatregexp.h b/kregexpeditor/repeatregexp.h new file mode 100644 index 0000000..21e32cd --- /dev/null +++ b/kregexpeditor/repeatregexp.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __REPEATREGEXP_H +#define __REPEATREGEXP_H + +#include "regexp.h" + +/** + Abstract syntax node for `repeated content' regular expression + @internal +*/ +class RepeatRegExp :public RegExp +{ +public: + RepeatRegExp( bool selected, int lower = 0, int upper = 0, RegExp* child = 0); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 3;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + int min() const { return _lower; } + int max() const { return _upper; } + RegExp* child() const { return _child; } + virtual RegExpType type() const { return REPEAT;} + virtual bool operator==( const RegExp& other ) const; + virtual void replacePart( CompoundRegExp* replacement ) { _child->replacePart( replacement ); } + +private: + int _lower; + int _upper; + RegExp* _child; +}; + +#endif // __REPEATREGEXP_H diff --git a/kregexpeditor/repeatwidget.cpp b/kregexpeditor/repeatwidget.cpp new file mode 100644 index 0000000..27215e4 --- /dev/null +++ b/kregexpeditor/repeatwidget.cpp @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include + #include "repeatwidget.moc" +#endif + +#include "repeatwidget.h" +#include "concwidget.h" +#include "repeatregexp.h" +#include +#include +#include +#include +#include +#include +#include +#include "kwidgetstreamer.h" + +RepeatWidget::RepeatWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : SingleContainerWidget(editorWindow, parent, name ? name : "RepeatWidget") +{ + _child = new ConcWidget(editorWindow, this); + init(); +} + +RepeatWidget::RepeatWidget( RepeatRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name ) + :SingleContainerWidget( editorWindow, parent, name ) +{ + init(); + RegExpWidget* child = WidgetFactory::createWidget( regexp->child(), editorWindow, this ); + if ( ! (_child = dynamic_cast( child ) ) ) + _child = new ConcWidget( editorWindow, child, this ); + + if ( regexp->max() == -1 ) { + if ( regexp->min() == 0 ) { + _content->set( RepeatRangeWindow::ANY, regexp->min(), regexp->max() ); + } + else { + _content->set( RepeatRangeWindow::ATLEAST, regexp->min(), regexp->max() ); + } + } + else { + if ( regexp->min() == 0 ) { + _content->set( RepeatRangeWindow::ATMOST, regexp->min(), regexp->max() ); + } + else if ( regexp->min() == regexp->max() ) { + _content->set( RepeatRangeWindow::EXACTLY, regexp->min(), regexp->max() ); + } + else { + _content->set( RepeatRangeWindow::MINMAX, regexp->min(), regexp->max() ); + } + } +} + +void RepeatWidget::init() +{ + _configWindow = new KDialogBase( this, "_configWindow", true, + i18n("Number of Times to Repeat Content"), + KDialogBase::Ok | KDialogBase::Cancel); + _content = new RepeatRangeWindow( _configWindow ); + _configWindow->setMainWidget( _content ); + connect( _configWindow, SIGNAL( cancelClicked() ), this, SLOT( slotConfigCanceled() ) ); + connect(_configWindow, SIGNAL(finished()), this, SLOT(slotConfigWindowClosed())); +} + + +QSize RepeatWidget::sizeHint() const +{ + // TODO: Merge with LookAheadWidget::sizeHint + QFontMetrics metrics = fontMetrics(); + _textSize = metrics.size( 0, _content->text() ); + + _childSize = _child->sizeHint(); + + int height = _textSize.height() + bdSize + _childSize.height() + bdSize + 2*pw; + int width = 2 * pw + QMAX(_childSize.width(), 4*bdSize + _textSize.width()); + return QSize(width,height); +} + +void RepeatWidget::paintEvent( QPaintEvent *e ) +{ + // TODO: Merge with LookAheadWidget::paintEvent + QSize mySize = sizeHint(); + QPainter painter(this); + + drawPossibleSelection( painter, mySize ); + + // move the child to its position and resize it. + _child->move(pw,_textSize.height()+bdSize); + QSize curChildSize = _child->size(); + QSize newChildSize = QSize(mySize.width() - 2*pw, _childSize.height()); + if ( curChildSize != newChildSize ) { + _child->resize(newChildSize); + // I resized the child, so give it a chance to relect thus. + _child->update(); + } + + // Draw the border and the text. + int startY = _textSize.height()/2; + + // Top lines and text + painter.drawLine(pw,startY,bdSize,startY); + painter.drawText(pw+2*bdSize,0,_textSize.width(), _textSize.height(),0, + _content->text()); + int offset = pw + 3*bdSize + _textSize.width(); + painter.drawLine(offset,startY,mySize.width()-pw,startY); + + // horizontal lines + painter.drawLine(0,startY,0,mySize.height()-pw); + painter.drawLine(mySize.width()-pw,startY,mySize.width()-pw, mySize.height()-pw); + + // buttom line + painter.drawLine(0, mySize.height()-pw, mySize.width()-pw, mySize.height()-pw); + + SingleContainerWidget::paintEvent(e); +} + +RegExp* RepeatWidget::regExp() const +{ + return new RepeatRegExp( isSelected(), _content->min(), _content->max(), _child->regExp() ); +} + +void RepeatWidget::slotConfigWindowClosed() +{ + _editorWindow->updateContent( 0 ); + update(); +} + +void RepeatWidget::slotConfigCanceled() +{ + QDataStream stream( _backup, IO_ReadOnly ); + KWidgetStreamer streamer; + streamer.fromStream( stream, _content ); + repaint(); +} + +int RepeatWidget::edit() +{ + _configWindow->move(QCursor::pos() - QPoint(_configWindow->sizeHint().width()/2, + _configWindow->sizeHint().height()/2) ); + QDataStream stream( _backup, IO_WriteOnly ); + KWidgetStreamer streamer; + streamer.toStream( _content, stream ); + + return _configWindow->exec(); +} + +//-------------------------------------------------------------------------------- +RepeatRangeWindow::RepeatRangeWindow( QWidget* parent, const char* name ) + : QVBox( parent, name ? name : "RepeatRangeWindow" ) +{ + setSpacing( 6 ); + + _group = new QVButtonGroup( i18n("Times to Match"), this, "groupbox" ); + + // Any number of times + QRadioButton* radioBut = new QRadioButton(i18n("Any number of times (including zero times)"), + _group, + "RepeatRangeWindow::choice any times"); + + _group->insert(radioBut, ANY); + + QWidget* container = new QWidget( _group ); + QHBoxLayout* lay = new QHBoxLayout( container ); + QGrid* grid = new QGrid( 3, container ); + grid->setSpacing( 5 ); + + lay->addWidget( grid ); + lay->addStretch( 1 ); + + createLine( grid, i18n( "At least" ), &_leastTimes, ATLEAST ); + createLine( grid, i18n( "At most" ), &_mostTimes, ATMOST ); + createLine( grid, i18n( "Exactly" ), &_exactlyTimes, EXACTLY ); + + // from ___ to ___ times + radioBut = new QRadioButton(i18n( "From" ), grid, "RepeatRangeWindow::from"); + _group->insert( radioBut, MINMAX ); + + _rangeFrom = new QSpinBox( 1, 999, 1, grid); + + QHBox* box = new QHBox( grid ); + box->setSpacing( 5 ); + + (void) new QLabel(i18n( "to" ), box); + _rangeTo = new QSpinBox( 1, 999, 1, box ); + (void) new QLabel( i18n( "time(s)" ), box ); + + connect( _rangeFrom, SIGNAL( valueChanged( int ) ), this, SLOT( slotUpdateMaxVal( int ) ) ); + connect( _rangeTo, SIGNAL( valueChanged( int ) ), this, SLOT( slotUpdateMinVal( int ) ) ); + + // set a default button. + _group->setButton(ANY); + slotItemChange( ANY ); + + + connect( _group, SIGNAL( clicked( int ) ), this, SLOT( slotItemChange( int ) ) ); +} + + +void RepeatRangeWindow::createLine( QWidget* parent, QString text, QSpinBox** spin, REPEATTYPE tp ) +{ + + QRadioButton* radioBut = new QRadioButton(text, parent); + *spin = new QSpinBox( 1, 999, 1, parent); + (*spin)->setValue(1); + + (void) new QLabel(i18n("time(s)"), parent); + _group->insert(radioBut, tp); +} + +void RepeatRangeWindow::slotItemChange( int which ) +{ + _leastTimes->setEnabled( false ); + _mostTimes->setEnabled( false ); + _exactlyTimes->setEnabled( false ); + _rangeFrom->setEnabled( false ); + _rangeTo->setEnabled( false ); + + switch ( which ) { + case ANY: break; + case ATLEAST: _leastTimes->setEnabled( true ); break; + case ATMOST: _mostTimes->setEnabled( true ); break; + case EXACTLY: _exactlyTimes->setEnabled( true ); break; + case MINMAX: + _rangeFrom->setEnabled( true ); + _rangeTo->setEnabled( true ); + break; + } +} + +void RepeatRangeWindow::slotUpdateMinVal( int maxVal ) +{ + if ( _rangeFrom->value() > maxVal ) { + _rangeFrom->setValue( maxVal ); + } +} + +void RepeatRangeWindow::slotUpdateMaxVal( int minVal ) +{ + if ( _rangeTo->value() < minVal ) { + _rangeTo->setValue( minVal ); + } +} + +QString RepeatRangeWindow::text() +{ + switch ( _group->id(_group->selected()) ) { + case ANY: return i18n("Repeated Any Number of Times"); + case ATLEAST: return i18n("Repeated at Least 1 Time", "Repeated at Least %n Times", _leastTimes->value() ); + case ATMOST: return i18n("Repeated at Most 1 Time", "Repeated at Most %n Times", _mostTimes->value() ); + case EXACTLY: return i18n("Repeated Exactly 1 Time", "Repeated Exactly %n Times", _exactlyTimes->value() ); + case MINMAX: return i18n("Repeated From %1 to %2 Times") + .arg( _rangeFrom->value() ).arg( _rangeTo->value() ); + } + qFatal("Fall through!"); + return QString::fromLocal8Bit(""); +} + +int RepeatRangeWindow::min() +{ + switch ( _group->id(_group->selected()) ) { + case ANY: return 0; + case ATLEAST: return _leastTimes->value(); + case ATMOST: return 0; + case EXACTLY: return _exactlyTimes->value(); + case MINMAX: return _rangeFrom->value(); + } + qFatal("Fall through!"); + return -1; +} + +int RepeatRangeWindow::max() +{ + switch ( _group->id(_group->selected()) ) { + case ANY: return -1; + case ATLEAST: return -1; + case ATMOST: return _mostTimes->value(); + case EXACTLY: return _exactlyTimes->value(); + case MINMAX: return _rangeTo->value(); + } + qFatal("Fall through!"); + return -1; +} + +void RepeatRangeWindow::set( REPEATTYPE tp, int min, int max ) +{ + _group->setButton( tp ); + switch ( tp ) { + case ANY: + break; + case ATLEAST: + _leastTimes->setValue( min ); + break; + case ATMOST: + _mostTimes->setValue( max ); + break; + case EXACTLY: + _exactlyTimes->setValue( min ); + break; + case MINMAX: + _rangeFrom->setValue( min ); + _rangeTo->setValue( max ); + break; + } +} diff --git a/kregexpeditor/repeatwidget.h b/kregexpeditor/repeatwidget.h new file mode 100644 index 0000000..434b4cb --- /dev/null +++ b/kregexpeditor/repeatwidget.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __repeatwidget +#define __repeatwidget + +#include "singlecontainerwidget.h" +#include +class QButtonGroup; +class KDialogBase; +class QCheckBox; +class QSpinBox; +class RepeatRegExp; + +/** + Widget containging the configuration for a @ref RepeatWidget + @internal +*/ +class RepeatRangeWindow :public QVBox +{ +Q_OBJECT + +public: + enum REPEATTYPE {ANY, ATLEAST, ATMOST, EXACTLY, MINMAX}; + + RepeatRangeWindow( QWidget* parent, const char* name = 0 ); + QString text(); + int min(); + int max(); + void set( REPEATTYPE tp, int min, int max ); + +protected slots: + void slotItemChange( int which ); + void slotUpdateMinVal( int minVal ); + void slotUpdateMaxVal( int minVal ); + + +private: + void createLine( QWidget* parent, QString text, QSpinBox** spin, REPEATTYPE tp ); + + QSpinBox* _leastTimes; + QSpinBox* _mostTimes; + QSpinBox* _exactlyTimes; + QSpinBox* _rangeFrom; + QSpinBox* _rangeTo; + QButtonGroup* _group; +}; + + + + + +/** + RegExp widget for `repeated content' + @internal +*/ +class RepeatWidget :public SingleContainerWidget +{ +Q_OBJECT + +public: + RepeatWidget( RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + RepeatWidget( RepeatRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0); + void init(); + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual RegExpType type() const { return REPEAT; } + virtual int edit(); + +protected: + virtual void paintEvent( QPaintEvent *e ); + +protected slots: + void slotConfigCanceled(); + void slotConfigWindowClosed(); + +private: + KDialogBase* _configWindow; + RepeatRangeWindow* _content; + + mutable QSize _textSize; + mutable QSize _childSize; + QByteArray _backup; +}; + + +#endif // __repeatwidget diff --git a/kregexpeditor/scrollededitorwindow.cpp b/kregexpeditor/scrollededitorwindow.cpp new file mode 100644 index 0000000..8518db9 --- /dev/null +++ b/kregexpeditor/scrollededitorwindow.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef QT_ONLY + #include "scrollededitorwindow.moc" +#endif + +#include "scrollededitorwindow.h" +#include "editorwindow.h" + +RegExpScrolledEditorWindow::RegExpScrolledEditorWindow( QWidget* parent, const char* name) + : QWidget(parent, name) +{ + _scrollView = new QScrollView( this ); + _editorWindow = new RegExpEditorWindow( _scrollView->viewport()); + _scrollView->addChild( _editorWindow ); + _scrollView->setResizePolicy( QScrollView::Manual ); + + connect( _editorWindow, SIGNAL( contentChanged( QPoint ) ), + this, SLOT( slotUpdateContentSize( QPoint ) ) ); + + connect( _editorWindow, SIGNAL( scrolling( QPoint ) ), + this, SLOT( slotScroll( QPoint ) ) ); + + connect( _editorWindow, SIGNAL( doneEditing() ), this, SIGNAL( doneEditing() ) ); + + connect( _editorWindow, SIGNAL( change() ), this, SIGNAL( change() ) ); + connect( _editorWindow, SIGNAL( savedRegexp() ), this, SIGNAL( savedRegexp() ) ); + + connect( _editorWindow, SIGNAL( anythingSelected(bool) ), this, SIGNAL( anythingSelected(bool) ) ); + connect( _editorWindow, SIGNAL( anythingOnClipboard(bool) ), this, SIGNAL( anythingOnClipboard(bool) ) ); + connect( _editorWindow, SIGNAL( canSave(bool) ), this, SIGNAL( canSave(bool) ) ); + connect( _editorWindow, SIGNAL( verifyRegExp() ), this, SIGNAL( verifyRegExp() ) ); +} + +void RegExpScrolledEditorWindow::slotSetRegExp( RegExp* regexp ) +{ + _editorWindow->slotSetRegExp( regexp ); + slotUpdateContentSize(QPoint()); +} + +void RegExpScrolledEditorWindow::slotInsertRegExp( int tp) +{ + _editorWindow->slotInsertRegExp( (RegExpType) tp ); +} + +void RegExpScrolledEditorWindow::slotInsertRegExp( RegExp* regexp) +{ + _editorWindow->slotInsertRegExp( regexp ); +} + +void RegExpScrolledEditorWindow::slotDeleteSelection() +{ + _editorWindow->slotDeleteSelection(); +} + +void RegExpScrolledEditorWindow::slotDoSelect() +{ + _editorWindow->slotDoSelect(); +} + +void RegExpScrolledEditorWindow::slotCut() +{ + _editorWindow->slotCut(); +} + +void RegExpScrolledEditorWindow::slotCopy() +{ + _editorWindow->slotCopy(); +} + +void RegExpScrolledEditorWindow::slotPaste() +{ + _editorWindow->slotStartPasteAction(); +} + +void RegExpScrolledEditorWindow::slotSave() +{ + _editorWindow->slotSave(); +} + +RegExp* RegExpScrolledEditorWindow::regExp() +{ + return _editorWindow->regExp(); +} + +void RegExpScrolledEditorWindow::resizeEvent( QResizeEvent *event ) +{ + _scrollView->resize( event->size() ); + slotUpdateContentSize(QPoint()); +} + +void RegExpScrolledEditorWindow::slotUpdateContentSize( QPoint focusPoint ) +{ + QSize childSize = _editorWindow->sizeHint(); + QSize vpSize = _scrollView->viewportSize(10,10); + + bool change = false; + + if ( childSize.width() < vpSize.width() ) { + childSize.setWidth( vpSize.width() ); + change = true; + } + + if ( childSize.height() < vpSize.height() ) { + childSize.setHeight( vpSize.height() ); + change = true; + } + + if ( change || + _scrollView->contentsWidth() != childSize.width() || + _scrollView->contentsHeight() != childSize.height() ) { + _editorWindow->resize( childSize ); + _scrollView->resizeContents( childSize.width(), childSize.height() ); + } + + if ( !focusPoint.isNull() ) { + _scrollView->ensureVisible ( focusPoint.x(), focusPoint.y(), 250,250 ); + } + +} + + +// TODO: add timers, which will make the widget scroll when mouse is located +// outside the QScrollView. +void RegExpScrolledEditorWindow::slotScroll( QPoint focusPoint ) +{ + _scrollView->ensureVisible( focusPoint.x(), focusPoint.y() ); +} + diff --git a/kregexpeditor/scrollededitorwindow.h b/kregexpeditor/scrollededitorwindow.h new file mode 100644 index 0000000..725b224 --- /dev/null +++ b/kregexpeditor/scrollededitorwindow.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __scrolledEditorWindow +#define __scrolledEditorWindow + +#include +class QScrollView; +class RegExpEditorWindow; +class RegExp; + + +/** + Regular Expression editor window. +*/ +class RegExpScrolledEditorWindow :public QWidget +{ + Q_OBJECT +public: + RegExpScrolledEditorWindow( QWidget *parent = 0, const char* name = 0); + RegExp* regExp(); + +private: + RegExpScrolledEditorWindow() {}; // Dont use! + + +protected: + virtual void resizeEvent( QResizeEvent* ); + +public slots: + void slotSetRegExp( RegExp* ); + void slotInsertRegExp( int ); + void slotInsertRegExp( RegExp* ); + void slotDeleteSelection(); + void slotDoSelect(); + void slotCut(); + void slotCopy(); + void slotSave(); + void slotPaste(); + +protected slots: + void slotUpdateContentSize( QPoint focusPoint ); + void slotScroll( QPoint focusPoint ); + + signals: + /** + This signal is emited when the user has completed an editing + action. The application may chose to call @ref slotDoSelect as a + consequence to reset to selection mode. + */ + void doneEditing(); + + /** + This signal is emited whenever a change has taked place in the editor widget + */ + void change(); + + /** + This signal is emitted when the user saves a regular expression. + */ + void savedRegexp(); + + void anythingSelected( bool ); + void anythingOnClipboard( bool ); + void canSave( bool ); + + /** + This signal is emitted when the regular expression has changed, or + when the selection has changed. + */ + void verifyRegExp(); + +private: + RegExpEditorWindow* _editorWindow; + QScrollView* _scrollView; +}; + +#endif // __scrolledEditorWindow diff --git a/kregexpeditor/selectablelineedit.cpp b/kregexpeditor/selectablelineedit.cpp new file mode 100644 index 0000000..98aff72 --- /dev/null +++ b/kregexpeditor/selectablelineedit.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef QT_ONLY + #include "selectablelineedit.moc" +#endif + +#include "selectablelineedit.h" + +SelectableLineEdit::SelectableLineEdit( RegExpWidget* owner, QWidget* parent, const char* name) + : QLineEdit( parent, name ), _owner(owner) +{ + connect( this, SIGNAL( textChanged( const QString & ) ), this, + SLOT( slotKeyPressed() ) ); + setAcceptDrops( false ); +} + +void SelectableLineEdit::setSelected( bool selected ) +{ + if ( selected ) { + QPalette pal = palette().copy(); + pal.setBrush( QColorGroup::Base, gray ); + setPalette( pal ); + } + else { + unsetPalette(); + } + repaint(); +} + +QSize SelectableLineEdit::sizeHint() const +{ + int frameWidth = frame() ? 8 : 4; // from QLineEdit source + QFontMetrics metrics = fontMetrics(); + int actualSize = metrics.width( text() ); + int charWidth = metrics.maxWidth(); + int height = QLineEdit::sizeHint().height(); + + int width; + if ( hasFocus() ) + width = actualSize+6*charWidth + frameWidth; + else + width = QMAX(actualSize, charWidth) + frameWidth; + return QSize( width , height ); +} + +void SelectableLineEdit::slotKeyPressed() +{ + int frameWidth = frame() ? 8 : 4; // from QLineEdit source + + QFontMetrics metrics = fontMetrics(); + int actualSize = metrics.width( text() ); + + if ( actualSize > size().width()-frameWidth ) { + repaint(); + emit parentPleaseUpdate(); + } +} diff --git a/kregexpeditor/selectablelineedit.h b/kregexpeditor/selectablelineedit.h new file mode 100644 index 0000000..653d85c --- /dev/null +++ b/kregexpeditor/selectablelineedit.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __selectablelineedit +#define __selectablelineedit +#include +class RegExpWidget; + +/** + A specialized QLineEdit for use in @ref TextWidget. + + This widget has two main features: + @li when the @ref TextWidget which contains it is selected, then the + line edit is grayed like the rest of the widgets. + @li When the widget does not have the focus, it is resized to only be + large enough to contain the text written in it. + + @internal +*/ +class SelectableLineEdit :public QLineEdit +{ +Q_OBJECT + +public: + SelectableLineEdit( RegExpWidget* owner, QWidget* parent = 0, const char* name = 0); + void setSelected( bool selected ); + virtual QSize sizeHint() const; + +protected slots: + void slotKeyPressed(); + +signals: + void parentPleaseUpdate(); + +private: + RegExpWidget* _owner; +}; + +#endif diff --git a/kregexpeditor/singlecontainerwidget.cpp b/kregexpeditor/singlecontainerwidget.cpp new file mode 100644 index 0000000..4782dd9 --- /dev/null +++ b/kregexpeditor/singlecontainerwidget.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef QT_ONLY + #include "singlecontainerwidget.moc" +#endif + +#include "singlecontainerwidget.h" +#include "concwidget.h" + +SingleContainerWidget::SingleContainerWidget(RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name) + : RegExpWidget( editorWindow, parent, name ) +{ +} + +bool SingleContainerWidget::updateSelection( bool parentSelected ) +{ + bool changed = RegExpWidget::updateSelection( parentSelected ); + changed = _child->updateSelection( _isSelected ) && changed; + if (changed) + repaint(); + + return changed; +} + +bool SingleContainerWidget::hasSelection() const +{ + return _isSelected || _child->hasSelection(); +} + +void SingleContainerWidget::clearSelection() +{ + _isSelected = false; + _child->clearSelection(); +} + +void SingleContainerWidget::deleteSelection() +{ + _child->deleteSelection(); + update(); +} + +void SingleContainerWidget::applyRegExpToSelection( RegExpType type ) +{ + _child->applyRegExpToSelection( type ); +} + +RegExp* SingleContainerWidget::selection() const +{ + if ( isSelected() ) + return regExp(); + else + return _child->selection(); +} + +bool SingleContainerWidget::validateSelection() const +{ + return _child->validateSelection(); +} + +QRect SingleContainerWidget::selectionRect() const +{ + if ( _isSelected ) + return QRect( mapToGlobal( QPoint(0,0) ), size() ); + else + return _child->selectionRect(); +} + +RegExpWidget* SingleContainerWidget::widgetUnderPoint( QPoint globalPos, bool justVisibleWidgets ) +{ + RegExpWidget* wid = _child->widgetUnderPoint( globalPos, justVisibleWidgets ); + if ( wid ) + return wid; + else { + // The child didn't contain the point, then lets see if this widget + // itself does. + return RegExpWidget::widgetUnderPoint( globalPos, justVisibleWidgets ); + } +} + +RegExpWidget* SingleContainerWidget::findWidgetToEdit( QPoint globalPos ) +{ + RegExpWidget* wid = _child->findWidgetToEdit( globalPos ); + if ( wid ) + return wid; + else if ( QRect(mapToGlobal(QPoint(0,0)), size()).contains( globalPos ) ) + return this; + else + return 0; +} + +void SingleContainerWidget::setConcChild( ConcWidget* conc ) +{ + delete _child; + _child = conc; +} + +void SingleContainerWidget::selectWidget( bool sel ) +{ + RegExpWidget::selectWidget( sel ); + _child->selectWidget( sel ); + update(); +} + +void SingleContainerWidget::updateAll() +{ + _child->updateAll(); + RegExpWidget::updateAll(); +} + +void SingleContainerWidget::updateCursorRecursively() +{ + _child->updateCursorRecursively(); + updateCursorShape(); +} + + diff --git a/kregexpeditor/singlecontainerwidget.h b/kregexpeditor/singlecontainerwidget.h new file mode 100644 index 0000000..8f07e6a --- /dev/null +++ b/kregexpeditor/singlecontainerwidget.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __singlecontainer +#define __singlecontainer +#include "regexpwidget.h" + +/** + Abstract class representing RegExp widgets having a single child. +*/ +class SingleContainerWidget :public RegExpWidget +{ +Q_OBJECT + +public: + SingleContainerWidget( RegExpEditorWindow* editorWindow, QWidget* parent, + const char* name = 0); + + virtual bool updateSelection( bool parentSelected ); + virtual bool hasSelection() const; + virtual void clearSelection(); + virtual void deleteSelection(); + virtual void applyRegExpToSelection( RegExpType type ); + virtual RegExp* selection() const; + virtual bool validateSelection() const; + virtual QRect selectionRect() const; + virtual RegExpWidget* widgetUnderPoint( QPoint globalPos, bool justVisibleWidgets ); + virtual RegExpWidget* findWidgetToEdit( QPoint globalPos ); + virtual void setConcChild( ConcWidget* child ); + virtual void selectWidget( bool sel ); + virtual void updateAll(); + virtual void updateCursorRecursively(); + +protected: + ConcWidget *_child; +}; + + +#endif // __singlecontainer diff --git a/kregexpeditor/test-without-dl/Makefile.am b/kregexpeditor/test-without-dl/Makefile.am new file mode 100644 index 0000000..2162d09 --- /dev/null +++ b/kregexpeditor/test-without-dl/Makefile.am @@ -0,0 +1,8 @@ +check_PROGRAMS = regexptest +regexptest_SOURCES = main.cpp +regexptest_LDFLAGS = $(all_libraries) +regexptest_LDADD = ../libkregexpeditorgui.la $(LIB_KSYCOCA) +INCLUDES = $(all_includes) +KDE_CXXFLAGS = -g + +METASOURCES = AUTO diff --git a/kregexpeditor/test-without-dl/main.cpp b/kregexpeditor/test-without-dl/main.cpp new file mode 100644 index 0000000..54610ac --- /dev/null +++ b/kregexpeditor/test-without-dl/main.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#include +#include +#include +#include "../kregexpeditorgui.h" +class ShootABug :public QObject +{ +public: + virtual bool eventFilter( QObject* recv, QEvent* event ) + { + if ( event->type() == QEvent::MouseButtonPress && + dynamic_cast(event)->state() == Qt::ControlButton ) { + // Ctrl + left mouse click. + + qDebug("----------------------------------------------------"); + qDebug((QString("Widget name : ") + QString( recv->name() )).latin1() ); + qDebug((QString("Widget class: ") + QString( recv->className() )).latin1() ); + qDebug("\nObject info:"); + recv->dumpObjectInfo(); + qDebug("\nObject tree:"); + recv->dumpObjectTree(); + qDebug("----------------------------------------------------"); + return false; + } + return false; + } +}; + +int main( int argc, char* argv[] ) +{ + KCmdLineArgs::init(argc, argv, "RegExp Example","",""); + KApplication myapp( argc, argv ); + + qApp->installEventFilter( new ShootABug() ); + + KRegExpEditorGUIDialog* iface = new KRegExpEditorGUIDialog( 0, "_editor", QStringList() ); + iface->setRegExp( QString::fromLatin1( "#include" ) ); + iface->doSomething( "setMinimal", (void*) false ); + iface->doSomething( "setSyntax", (void*) new QString( QString::fromLatin1( "Emacs" ) ) ); + iface->doSomething( "setShowSyntaxCombo", (bool*) true ); + + QFile file("/packages/kde-src/kdeutils/kregexpeditor/test/main.cpp"); + file.open(IO_ReadOnly); + QTextStream stream( &file); + QString txt = stream.read(); + iface->setMatchText( txt ); + + iface->exec(); +} + diff --git a/kregexpeditor/textrangeregexp.cpp b/kregexpeditor/textrangeregexp.cpp new file mode 100644 index 0000000..73c2923 --- /dev/null +++ b/kregexpeditor/textrangeregexp.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include +#endif + +#include "textrangeregexp.h" +#include "regexpconverter.h" + +TextRangeRegExp::TextRangeRegExp( bool selected ) : RegExp( selected ), + _negate(false), _digit(false), _nonDigit(false), _space(false), _nonSpace(false), _wordChar(false), _nonWordChar(false) +{ +} + +TextRangeRegExp::~TextRangeRegExp() +{ +} + + +void TextRangeRegExp::addCharacter( QString str ) +{ + _chars.append( str ); +} + +void TextRangeRegExp::addRange(QString from, QString to) +{ + _ranges.append( new StringPair( from, to ) ); +} + +bool TextRangeRegExp::check( ErrorMap&, bool, bool ) +{ + return false; +} + +QDomNode TextRangeRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement( QString::fromLocal8Bit( "TextRange" ) ); + + if ( _negate ) + top.setAttribute( QString::fromLocal8Bit("negate"), true ); + if ( _digit ) + top.setAttribute( QString::fromLocal8Bit("digit"), true ); + if ( _nonDigit ) + top.setAttribute( QString::fromLocal8Bit("nonDigit"), true ); + if ( _space ) + top.setAttribute( QString::fromLocal8Bit("space"), true ); + if ( _nonSpace ) + top.setAttribute( QString::fromLocal8Bit("nonSpace"), true ); + if ( _wordChar ) + top.setAttribute( QString::fromLocal8Bit("wordChar"), true ); + if ( _nonWordChar ) + top.setAttribute( QString::fromLocal8Bit("nonWordChar"), true ); + + for ( QStringList::ConstIterator it = _chars.begin(); it != _chars.end(); ++it ) { + QDomElement elm = doc->createElement( QString::fromLocal8Bit( "Character" ) ); + elm.setAttribute( QString::fromLocal8Bit( "char" ), *it ); + top.appendChild( elm ); + } + + for ( QPtrListIterator it2(_ranges); *it2; ++it2 ) { + QDomElement elm = doc->createElement( QString::fromLocal8Bit( "Range" ) ); + elm.setAttribute( QString::fromLocal8Bit( "from" ), (*it2)->first() ); + elm.setAttribute( QString::fromLocal8Bit( "to" ), (*it2)->second() ); + top.appendChild( elm ); + } + return top; +} + +bool TextRangeRegExp::load( QDomElement top, const QString& /*version*/ ) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit( "TextRange" ) ); + QString str; + QString one = QString::fromLocal8Bit("1"); + QString zero = QString::fromLocal8Bit("0"); + + str = top.attribute( QString::fromLocal8Bit("negate"), zero ); + _negate = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("digit"), zero ); + _digit = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("nonDigit"), zero ); + _nonDigit = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("space"), zero ); + _space = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("nonSpace"), zero ); + _nonSpace = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("wordChar"), zero ); + _wordChar = ( str == one ); + + str = top.attribute( QString::fromLocal8Bit("nonWordChar"), zero ); + _nonWordChar = ( str == one ); + + for ( QDomNode node = top.firstChild(); !node.isNull(); node = node.nextSibling() ) { + if ( !node.isElement() ) + continue; // Skip comments. + QDomElement child = node.toElement(); + + if ( child.tagName() == QString::fromLocal8Bit( "Character" ) ) { + QString ch = child.attribute( QString::fromLocal8Bit( "char" ) ); + addCharacter( ch ); + } + else if ( child.tagName() == QString::fromLocal8Bit( "Range" ) ) { + QString from = child.attribute( QString::fromLocal8Bit( "from" ) ); + QString to = child.attribute( QString::fromLocal8Bit( "to" ) ); + addRange( from, to ); + } + else { + KMessageBox::sorry( 0, i18n("

    Invalid sub element to element TextRange. Tag was %1

    ").arg(child.tagName()), + i18n("Error While Loading From XML File") ) ; + return false; + } + } + return true; +} + +bool TextRangeRegExp::operator==( const RegExp& other ) const +{ + return ( RegExpConverter::current()->toStr( const_cast( this ), false ) == + RegExpConverter::current()->toStr( const_cast( &other ), false ) ); +} + diff --git a/kregexpeditor/textrangeregexp.h b/kregexpeditor/textrangeregexp.h new file mode 100644 index 0000000..de1785e --- /dev/null +++ b/kregexpeditor/textrangeregexp.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __TEXTRANGEREGEXP_H +#define __TEXTRANGEREGEXP_H + +#include "regexp.h" +#include "pair.h" +#include + +typedef Pair StringPair; + +/** + Abstract syntax node for `text range' regular expression + + @internal +*/ +class TextRangeRegExp :public RegExp +{ +public: + TextRangeRegExp( bool selected ); + virtual ~TextRangeRegExp(); + + void addCharacter( QString ch ); + QStringList chars() const { return _chars; } + void clearChars() { _chars.clear(); } + + void addRange( QString from, QString to ); + QPtrList range() const { return _ranges; } + void clearRange() { _ranges.clear(); } + + void setNegate( bool set ) { _negate = set; } + void setDigit( bool set ) { _digit = set; } + void setNonDigit( bool set ) { _nonDigit = set; } + void setSpace( bool set ) { _space = set; } + void setNonSpace( bool set ) { _nonSpace = set; } + void setWordChar( bool set ) { _wordChar = set; } + void setNonWordChar( bool set ) { _nonWordChar = set; } + + bool negate() const { return _negate; } + bool digit() const { return _digit; } + bool nonDigit() const { return _nonDigit; } + bool space() const { return _space; } + bool nonSpace() const { return _nonSpace; } + bool wordChar() const { return _wordChar; } + bool nonWordChar() const { return _nonWordChar; } + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { return 4;} + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + virtual RegExpType type() const { return TEXTRANGE;} + virtual bool operator==( const RegExp& other ) const; + +private: + bool _negate, _digit, _nonDigit, _space, _nonSpace, _wordChar, _nonWordChar; + QStringList _chars; + QPtrList _ranges; +}; + +#endif // __TEXTRANGEREGEXP_H diff --git a/kregexpeditor/textregexp.cpp b/kregexpeditor/textregexp.cpp new file mode 100644 index 0000000..7d5d02c --- /dev/null +++ b/kregexpeditor/textregexp.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include +#endif + +#include "textregexp.h" + +TextRegExp::TextRegExp( bool selected, QString text) :RegExp( selected ) +{ + _text = text; +} + +bool TextRegExp::check( ErrorMap&, bool, bool ) +{ + return false; +} + + +void TextRegExp::append( QString str ) +{ + _text.append( str ); +} + +QDomNode TextRegExp::toXml( QDomDocument* doc ) const +{ + QDomElement top = doc->createElement(QString::fromLocal8Bit("Text")); + QDomText text = doc->createTextNode( _text ); + top.appendChild( text ); + return top; +} + +bool TextRegExp::load( QDomElement top, const QString& /*version*/) +{ + Q_ASSERT( top.tagName() == QString::fromLocal8Bit( "Text" ) ); + if ( top.hasChildNodes() ) { + QDomNode child = top.firstChild(); + if ( ! child.isText() ) { + KMessageBox::sorry( 0, i18n("

    Element Text did not contain any textual data.

    "), + i18n("Error While Loading From XML File") ) ; + return false; + } + QDomText txtNode = child.toText(); + _text = txtNode.data(); + } + else { + _text = QString::fromLatin1( "" ); + } + + return true; +} + +bool TextRegExp::operator==( const RegExp& other ) const { + if ( other.type() != type() ) + return false; + + const TextRegExp& theOther = dynamic_cast( other ); + if ( text() == theOther.text() ) + return true; + + return false; +} + diff --git a/kregexpeditor/textregexp.h b/kregexpeditor/textregexp.h new file mode 100644 index 0000000..f98d0e9 --- /dev/null +++ b/kregexpeditor/textregexp.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __textregexp_h +#define __textregexp_h + +#include "regexp.h" + +/** + Abstract syntax node for `text' regular expression + @internal +*/ +class TextRegExp :public RegExp +{ +public: + TextRegExp( bool selected, QString text = QString::null); + + virtual bool check( ErrorMap&, bool first, bool last ); + virtual int precedence() const { + if ( _text.length() > 1 ) + return 2; + else + return 4; + } + QString text() const { return _text; } + virtual QDomNode toXml( QDomDocument* doc ) const; + virtual bool load( QDomElement, const QString& version ); + void append( QString str); + virtual RegExpType type() const { return TEXT;} + virtual bool operator==( const RegExp& other ) const; + +private: + QString _text; +}; + +#endif // __textregexp_h diff --git a/kregexpeditor/textwidget.cpp b/kregexpeditor/textwidget.cpp new file mode 100644 index 0000000..c36d1a8 --- /dev/null +++ b/kregexpeditor/textwidget.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef QT_ONLY + #include "textwidget.moc" +#endif + +#include "textwidget.h" +#include "textregexp.h" +#include "selectablelineedit.h" +#include + +TextWidget::TextWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + :RegExpWidget(editorWindow, parent, name) +{ + init( QString::fromLocal8Bit("") ); +} + +TextWidget::TextWidget( TextRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name ) + : RegExpWidget( editorWindow, parent, name ) +{ + init(regexp->text()); +} + +void TextWidget::init( const QString& txt ) +{ + QHBoxLayout *lay = new QHBoxLayout(this); + _edit = new SelectableLineEdit( this, this, "TextWidget::edit" ); + _edit->setDragEnabled( false ); //otherwise QLineEdit::mouseMoveEvent will set the cursor over and over again. + lay->addWidget(_edit); + + _edit->setText( txt ); + + connect( _edit, SIGNAL( parentPleaseUpdate() ), this, SLOT(slotUpdate()) ); + setFocusProxy( _edit ); + _edit->installEventFilter( this ); + connect( _edit, SIGNAL( textChanged( const QString & ) ), _editorWindow, SLOT( emitChange() ) ); +} + + +void TextWidget::slotUpdate() +{ + // I need to force the parent to repaint, as the size change of this + // widget may not be enough for the parent to change size, and in that + // case the parent would not repaint, and the text widget would not be + // resized. + QWidget *p = static_cast(parent()); + if (p) + p->repaint(); + _editorWindow->updateContent( this ); +} + +QSize TextWidget::sizeHint() const +{ + return _edit->sizeHint(); +} + +void TextWidget::paintEvent( QPaintEvent *e) +{ + RegExpWidget::paintEvent(e); +} + +void TextWidget::selectWidget( bool sel ) +{ + _edit->setSelected( sel ); +} + +bool TextWidget::updateSelection(bool parentSelected) +{ + bool changed = RegExpWidget::updateSelection( parentSelected ); + + // I need to call this function all the time, else the rubber band will + // not be correctly deleted in the line edit. + _edit->setSelected( _isSelected ); + return changed; +} +void TextWidget::updateAll() +{ + _edit->update(); + update(); +} + +void TextWidget::clearSelection() +{ + _isSelected = false; + _edit->setSelected( false ); +} + +RegExp* TextWidget::regExp() const +{ + return new TextRegExp( isSelected(), _edit->text() ); +} + +bool TextWidget::eventFilter( QObject*, QEvent* event) +{ + // This is an event filter (in contrast to methods in SelectableLineEdit), + // otherwise lots of functions would need to be exported from TextWidget. + if ( event->type() == QEvent::MouseButtonRelease ) { + if ( _editorWindow->isInserting() ) { + if ( acceptWidgetInsert( _editorWindow->insertType() ) ) { + mouseReleaseEvent( static_cast(event) ); + } + return true; + } + } + else if ( event->type() == QEvent::MouseButtonPress ) { + if ( _editorWindow->isInserting() ) { + return true; + } + else if ( isSelected() ) { + QMouseEvent* e = static_cast( event ); + QMouseEvent ev( event->type(), mapTo(_editorWindow, e->pos()), + e->button(), e->state()); + QApplication::sendEvent( _editorWindow, &ev ); + return true; + } + } + + else if ( event->type() == QEvent::Enter ) { + if ( _editorWindow->isInserting() ) { + if ( acceptWidgetInsert( _editorWindow->insertType() ) ) { + _edit->setCursor(crossCursor); + } + else { + _edit->setCursor(forbiddenCursor); + } + } + else if ( isSelected() ) { + _edit->setCursor( arrowCursor ); + } + else { + _edit->setCursor( ibeamCursor ); + } + } + else if ( event->type() == QEvent::MouseButtonDblClick && _editorWindow->isInserting() ) { + return true; + } + return false; +} + + diff --git a/kregexpeditor/textwidget.h b/kregexpeditor/textwidget.h new file mode 100644 index 0000000..9a5c0be --- /dev/null +++ b/kregexpeditor/textwidget.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __textwidget +#define __textwidget + +#include "regexpwidget.h" +class SelectableLineEdit; +class TextRegExp; + +/** + RegExp widget representing text. + + @internal +*/ +class TextWidget : public RegExpWidget +{ + Q_OBJECT + +public: + TextWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + TextWidget( TextRegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent, const char* name = 0); + virtual QSize sizeHint() const; + virtual RegExp* regExp() const; + virtual RegExpType type() const { return TEXT; } + virtual void updateAll(); + virtual void selectWidget( bool ); + +protected: + void init( const QString& text ); + virtual void paintEvent( QPaintEvent *e ); + virtual bool updateSelection( bool parentSelected ); + virtual void clearSelection(); + virtual bool eventFilter( QObject*, QEvent* ); + +protected slots: + void slotUpdate(); + +private: + QString text; + SelectableLineEdit *_edit; + QSize textSize, boxSize, editSize; +}; + + + +#endif // __textwidget diff --git a/kregexpeditor/triple.h b/kregexpeditor/triple.h new file mode 100644 index 0000000..c44276c --- /dev/null +++ b/kregexpeditor/triple.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __triple_h +#define __triple_h + +/** + @internal +*/ +template class Triple +{ +public: + Triple() {}; + Triple(F first, S second, T third) : _first(first), _second(second), + _third(third) {} + F first() { return _first; } + S second() { return _second; } + T third() { return _third; } +private: + F _first; + S _second; + T _third; + +}; + +#endif // __triple_h diff --git a/kregexpeditor/userdefinedregexps.cpp b/kregexpeditor/userdefinedregexps.cpp new file mode 100644 index 0000000..de2f675 --- /dev/null +++ b/kregexpeditor/userdefinedregexps.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include + #include + #include + #include + #include "userdefinedregexps.moc" +#endif + +#include "userdefinedregexps.h" +#include +#include +#include +#include "widgetfactory.h" +#include "compoundregexp.h" +#include +#include + +UserDefinedRegExps::UserDefinedRegExps( QWidget *parent, const char *name ) + : QDockWindow( QDockWindow::InDock, parent, name) +{ + QWidget* top = new QWidget( this ); + QVBoxLayout* lay = new QVBoxLayout( top, 6 ); + lay->setAutoAdd( true ); + + QLabel* label = new QLabel( i18n("Compound regular expressions:"), top ); + + // This is to avoid that the label set the minimum width for the window. + label->setMinimumSize(1,0); + + _userDefined = new QListView( top, "UserDefinedRegExps::_userDefined" ); + _userDefined->addColumn( QString::null ); + _userDefined->header()->hide(); + // _userDefined->setRootIsDecorated( true ); + setWidget( top ); + slotPopulateUserRegexps(); + + connect( _userDefined, SIGNAL(clicked(QListViewItem*)), this, SLOT(slotLoad(QListViewItem*)) ); + connect( _userDefined, SIGNAL(rightButtonPressed(QListViewItem*,const QPoint&, int )), + this, SLOT( slotEdit( QListViewItem*, const QPoint& ) ) ); +} + +void UserDefinedRegExps::slotPopulateUserRegexps() +{ + _userDefined->clear(); + _regExps.clear(); + + createItems( i18n("User Defined"), WidgetWinItem::path(), true ); + +#ifdef QT_ONLY + QStringList dirs; + dirs << QString::fromLatin1( "predefined" ); +#else + QStringList dirs = KGlobal::dirs()->findDirs( "data", QString::fromLocal8Bit("kregexpeditor/predefined/") ); +#endif + + for ( QStringList::iterator it1 = dirs.begin(); it1 != dirs.end(); ++it1 ) { + QDir dir( *it1, QString::null, QDir::Name, QDir::Dirs ); + QStringList subdirs = dir.entryList(); + for ( QStringList::iterator it2 = subdirs.begin(); it2 != subdirs.end(); ++it2 ) { + if ( *it2 == QString::fromLocal8Bit(".") || *it2 == QString::fromLocal8Bit("..") ) + continue; + createItems( *it2, *it1 + QString::fromLocal8Bit("/") + *it2, false ); + } + } + +} + +void UserDefinedRegExps::createItems( const QString& _title, const QString& dir, bool usersRegExp ) +{ + QString title = _title; + if (_title == QString::fromLatin1("general")) + title = i18n("General"); + + QListViewItem* lvItem = new QListViewItem( _userDefined, title ); + lvItem->setOpen( true ); + + QDir directory( dir ); + QStringList files = directory.entryList( QString::fromLocal8Bit("*.regexp") ); + for ( QStringList::Iterator it = files.begin(); it != files.end(); ++it ) { + QString fileName = dir + QString::fromLocal8Bit("/") + *it; + + QFile file( fileName ); + if ( ! file.open(IO_ReadOnly) ) { + KMessageBox::sorry( this, i18n("Could not open file for reading: %1").arg(fileName) ); + continue; + } + + QTextStream stream( &file ); + QString data = stream.read(); + file.close(); + + RegExp* regexp = WidgetFactory::createRegExp( data ); + if ( ! regexp ) { + KMessageBox::sorry( this, i18n("File %1 containing user defined regular expression contained an error").arg( fileName ) ); + continue; + } + + new WidgetWinItem( *it, regexp, usersRegExp, lvItem ); + + // Insert the regexp into the list of compound regexps + if ( regexp->type() == RegExp::COMPOUND ) { + CompoundRegExp* cregexp = dynamic_cast( regexp ); + if ( cregexp && cregexp->allowReplace() ) + _regExps.append( cregexp ); + } + } +} + +const QPtrList UserDefinedRegExps::regExps() const +{ + return _regExps; +} + + +void UserDefinedRegExps::slotUnSelect() +{ + _userDefined->clearSelection(); +} + +void UserDefinedRegExps::slotLoad(QListViewItem* item) +{ + if ( !item || ! dynamic_cast(item) ) { + // Mouse pressed outside a widget. + return; + } + + WidgetWinItem* wwi = dynamic_cast(item); + if (wwi) { + emit load( wwi->regExp() ); + } +} + +void UserDefinedRegExps::slotEdit( QListViewItem* item, const QPoint& pos ) +{ + QPopupMenu* menu = new QPopupMenu( this ); + menu->insertItem(i18n("Delete"), 1 ); + menu->insertItem(i18n("Rename..."), 2 ); + if ( !item || ! dynamic_cast( item ) ) { + // menu not selected on an item + menu->setItemEnabled( 1, false ); + menu->setItemEnabled( 2, false ); + } + else { + // Only allow rename and delete of users own regexps. + WidgetWinItem* winItem = dynamic_cast( item ); + if ( winItem && ! winItem->isUsersRegExp() ) { + menu->setItemEnabled( 1, false ); + menu->setItemEnabled( 2, false ); + } + } + + int which = menu->exec( pos ); + + if ( which == 1 ) { // Delete + WidgetWinItem* winItem = dynamic_cast( item ); + Q_ASSERT( winItem ); + QFile file( winItem->fileName() ); + Q_ASSERT( file.exists() ); + file.remove(); + delete item; + } + else if ( which == 2 ) { // Rename + WidgetWinItem* winItem = dynamic_cast( item ); + Q_ASSERT( winItem ); + + QString oldFile = winItem->fileName(); + QString oldName = winItem->name(); + + QString txt; +#ifdef QT_ONLY + txt = QInputDialog::getText( tr("Rename Regular Expression"), tr("New name:") ); +#else + KLineEditDlg dlg(i18n("New name:"), oldName, this); + dlg.setCaption(i18n("Rename Item")); + bool ok = dlg.exec(); + if ( ok ) + txt = dlg.text(); +#endif + if ( !txt.isNull() && oldName != txt ) { + QString fileName = WidgetWinItem::path() + QString::fromLocal8Bit("/") + txt + QString::fromLocal8Bit(".regexp"); + QFileInfo finfo( fileName ); + if ( finfo.exists() ) { + int answer = KMessageBox::warningYesNo( this, i18n("

    Overwrite named regular expression %1?

    ").arg(txt), QString::null, i18n("Overwrite"), i18n("Do Not Overwrite") ); + if ( answer != KMessageBox::Yes ) + return; + + // An item with this name already exists. + delete winItem; + } + else + winItem->setName( txt ); + QDir dir; + dir.rename( oldFile, fileName ); + } + } + + + delete menu; +} + +void UserDefinedRegExps::slotSelectNewAction() +{ + slotUnSelect(); +} + +WidgetWinItem::WidgetWinItem( QString fileName, RegExp* regexp, bool usersRegExp, QListViewItem* parent ) + :QListViewItem( parent ), _regexp( regexp ), _usersRegExp ( usersRegExp ) +{ + int index = fileName.findRev(QString::fromLocal8Bit(".regexp")); + _name = fileName.left(index); + + setText( 0, _name ); +} + +QString WidgetWinItem::fileName() const +{ + return path() + QString::fromLocal8Bit("/") +_name + QString::fromLocal8Bit(".regexp"); +} + +RegExp* WidgetWinItem::regExp() const +{ + return _regexp; +} + +QString WidgetWinItem::name() const +{ + return _name; +} + +void WidgetWinItem::setName( const QString& nm ) +{ + _name = nm; + setText( 0, nm ); +} + +QString WidgetWinItem::path() +{ +#ifdef QT_ONLY + return QString::fromLatin1( "predefined" ); +#else + return locateLocal("data", QString::fromLocal8Bit("KRegExpEditor/")); +#endif +} + + + diff --git a/kregexpeditor/userdefinedregexps.h b/kregexpeditor/userdefinedregexps.h new file mode 100644 index 0000000..358aa73 --- /dev/null +++ b/kregexpeditor/userdefinedregexps.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef __USERDEFINEDREGEXPS_H +#define __USERDEFINEDREGEXPS_H +#include +#include + +#include "compoundregexp.h" + +class QPoint; +class RegExp; + +class UserDefinedRegExps :public QDockWindow +{ +Q_OBJECT + +public: + UserDefinedRegExps( QWidget *parent, const char *name = 0 ); + const QPtrList regExps() const; + +public slots: + void slotSelectNewAction(); + +protected slots: + void slotLoad(QListViewItem* item); + void slotEdit( QListViewItem* item, const QPoint& pos ); + void slotPopulateUserRegexps(); + void slotUnSelect(); + +protected: + void createItems( const QString& title, const QString& dir, bool usersRegExp ); + +signals: + void load( RegExp* ); + +private: + QListView* _userDefined; + QPtrList _regExps; +}; + +class WidgetWinItem :public QListViewItem +{ +public: + WidgetWinItem( QString name, RegExp* regexp, bool users, QListViewItem* parent ); + static QString path(); + + QString fileName() const; + RegExp* regExp() const; + QString name() const; + void setName( const QString& ); + bool isUsersRegExp() const { return _usersRegExp; } + +private: + QString _name; + RegExp* _regexp; + bool _usersRegExp; +}; + + +#endif // __USERDEFINEDREGEXPS_H diff --git a/kregexpeditor/util.cpp b/kregexpeditor/util.cpp new file mode 100644 index 0000000..8bff5de --- /dev/null +++ b/kregexpeditor/util.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "util.h" +#include +#include +QPixmap Util::getKRegExpEditorIcon( const QString& name ) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage(name) ); + return pix; +#else + return KGlobal::iconLoader()->loadIcon(locate("data", QString::fromLatin1("kregexpeditor/pics/") +name ), + KIcon::Toolbar ); +#endif +} + +QPixmap Util::getSystemIcon( const QString& name ) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage( name ) ); + return pix; +#else + KIconLoader loader; + return loader.loadIcon( name, KIcon::Toolbar); +#endif + +} + +QIconSet Util::getSystemIconSet( const QString& name ) +{ +#ifdef QT_ONLY + QPixmap pix; + pix.convertFromImage( qembed_findImage( name ) ); + return QIconSet( pix ); +#else + KIconLoader loader; + return loader.loadIconSet( name, KIcon::Toolbar); +#endif + +} diff --git a/kregexpeditor/util.h b/kregexpeditor/util.h new file mode 100644 index 0000000..a3b406e --- /dev/null +++ b/kregexpeditor/util.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2002-2004 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef UTIL_H +#define UTIL_H + +#include +#include + +class Util +{ +public: + static QPixmap getKRegExpEditorIcon( const QString& name ); + static QPixmap getSystemIcon( const QString& name ); + static QIconSet getSystemIconSet( const QString& name ); +}; + +#endif // UTIL_H + diff --git a/kregexpeditor/verifier.cpp b/kregexpeditor/verifier.cpp new file mode 100644 index 0000000..322db12 --- /dev/null +++ b/kregexpeditor/verifier.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include + #include "verifier.moc" +#endif + +#include "verifier.h" + +Verifier::Verifier( QWidget* parent, const char* name ) : QTextEdit( parent, name ) + /* QT_ANCHOR_DO_NOT_WORK: ,_current( 0 ) */ +{ + _highlighter = 0; + setMinimumSize(1,1); +} + +/** + Update text edit to show matches of regular expression +*/ +void Verifier::verify( const QString& reg ) +{ + if ( _highlighter ) { + _highlighter->setRegExp( reg ); + _highlighter->rehighlight(); + } +} + + +/** + Make the text edit display the text without any matches. +*/ +void Verifier::clearRegexp() +{ + if ( _highlighter ) { + _highlighter->setRegExp( QString::null ); + _highlighter->rehighlight(); + } +} + +/** + Set case sensitive matching +*/ +void Verifier::setCaseSensitive( bool b ) +{ + if ( _highlighter ) + _highlighter->setCaseSensitive( b ); +} + + +/** + set minimal mathcing +*/ +void Verifier::setMinimal( bool b ) +{ + if ( _highlighter ) + _highlighter->setMinimal( b ); +} + +// Qt anchors do not work for
    ...
    , thefore scrolling to next/prev match +// do not work. Enable this when they work. +// void Verifier::gotoFirst() +// { +// gotoNum(1); +// } +// +// void Verifier::gotoLast() +// { +// gotoNum( _count-1 ); +// } +// +// void Verifier::gotoPrev() +// { +// gotoNum( _current-1 ); +// } +// +// void Verifier::gotoNext() +// { +// gotoNum( _current+1 ); +// } +// +// void Verifier::gotoNum( int which ) +// { +// QString anchor = QString::fromLatin1("match%1").arg(which); +// scrollToAnchor( anchor ); +// _current = which; +// emit currentChanged( _current ); +// emit goBackwardPossible( which != 0 ); +// emit goForwardPossible( which != _count -1 ); +// } + + +void Verifier::setHighlighter( RegexpHighlighter* highlighter ) +{ + delete _highlighter; + _highlighter = highlighter; + setEnabled( _highlighter != 0 ); + +} + + diff --git a/kregexpeditor/verifier.h b/kregexpeditor/verifier.h new file mode 100644 index 0000000..661abef --- /dev/null +++ b/kregexpeditor/verifier.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef VERIFIER_H +#define VERIFIER_H +#include +#include "regexphighlighter.h" +class QTimer; +class QProgressDialog; +class QLabel; +class SyntaxHighlighter; +class Verifier :public QTextEdit +{ +Q_OBJECT +public: + Verifier( QWidget* parent, const char* name = 0 ); + void setHighlighter( RegexpHighlighter* ); + +public slots: + void verify( const QString& regexp ); + void clearRegexp(); + void setCaseSensitive( bool ); + void setMinimal( bool ); + + // I have no way of telling the current paragrahp when highlighting - thefore scrolling to next/prev match + // do not work. Enable this when they work. + // void gotoFirst(); + // void gotoPrev(); + // void gotoNext(); + // void gotoLast(); + //signals: + // void countChanged( int ); + // void currentChanged( int ); + // void goBackwardPossible( bool ); + // void goForwardPossible( bool ); + + // protected: + // void gotoNum( int ); + +private: + int _count; + // int _current; + RegexpHighlighter* _highlighter; + +}; + +#endif // VERIFIER_H diff --git a/kregexpeditor/verifybuttons.cpp b/kregexpeditor/verifybuttons.cpp new file mode 100644 index 0000000..cd1b1ef --- /dev/null +++ b/kregexpeditor/verifybuttons.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY +#include "compat.h" +#include +#include "images.h" +#else +#include +#include "verifybuttons.moc" +#include +#include +#include +#include +#endif + +#include "verifybuttons.h" +#include +#include +#include +#include "qtregexpconverter.h" +#include "emacsregexpconverter.h" +#include +#include "util.h" +#include +#include + +VerifyButtons::VerifyButtons( QWidget* parent, const char* name ) + :QDockWindow( QDockWindow::InDock, parent, name ), _configMenu( 0 ) +{ + QBoxLayout* layout = boxLayout(); + + _verify = new QToolButton(this); + QIconSet icon = Util::getSystemIconSet( QString::fromLatin1("spellcheck")); + _verify->setIconSet( icon ); + QToolTip::add( _verify, i18n( "Verify regular expression" ) ); + QWhatsThis::add( _verify, i18n("Shows what part of the regular expression is being matched in the verifier window." + "(The window below the graphical editor window).")); + layout->addWidget( _verify ); + connect( _verify, SIGNAL( clicked() ), this, SIGNAL( verify() ) ); + + QToolButton* button = new QToolButton(this); + button->setPixmap( Util::getSystemIcon( QString::fromLatin1("fileopen")) ); + layout->addWidget( button ); + connect(button, SIGNAL(clicked()), this, SLOT(loadText())); + QToolTip::add( button, i18n("Load text in the verifier window") ); + + button = new QToolButton(this); + button->setPixmap( Util::getSystemIcon( QString::fromLatin1("package_settings")) ); + layout->addWidget( button ); + connect(button, SIGNAL(clicked()), this, SLOT(configure())); + QToolTip::add( button, i18n("Settings") ); + + // It is currently not possible to ask for the paragraph being highlighted, thefore scrolling to next/prev match + // do not work. Enable this when they work. + // _first = new QToolButton( QString::fromLatin1("<<"), this); + // layout->addWidget( _first ); + // connect(_first, SIGNAL(clicked()), this, SIGNAL( gotoFirst())); + // _first->setFixedWidth( 25 ); + // + // _prev = new QToolButton(QString::fromLatin1("<"), this); + // layout->addWidget( _prev ); + // connect(_prev, SIGNAL(clicked()), this, SIGNAL( gotoPrev())); + // _prev->setFixedWidth( 20 ); + // + // _next = new QToolButton(QString::fromLatin1(">"), this); + // layout->addWidget( _next ); + // connect(_next, SIGNAL(clicked()), this, SIGNAL( gotoNext())); + // _next->setFixedWidth( 20 ); + // + // _last = new QToolButton(QString::fromLatin1(">>"), this); + // layout->addWidget( _last ); + // connect(_last, SIGNAL(clicked()), this, SIGNAL( gotoLast())); + // _last->setFixedWidth( 25 ); + + // Same as above +// QLabel* label = new QLabel( i18n("Matches: "), this ); +// layout->addWidget( label ); +// _matches = new QLabel(i18n("-"), this ); +// layout->addWidget( _matches ); +// QString txt = i18n( "Shows number of times regular expression matches the text in the verifier window"); +// QToolTip::add( label, txt ); +// QToolTip::add( _matches, txt ); + + _verify->setEnabled( false ); + + // -------------------------------------------------- RegExp Converters + + // Qt + RegExpConverter* converter = new QtRegExpConverter(); + _converters.append( qMakePair( converter, static_cast( 0 ) ) ); + QString qtConverterName = converter->name(); + + // Emacs + converter = new EmacsRegExpConverter(); + _converters.append( qMakePair( converter, static_cast( 0 ) ) ); + + + // -------------------------------------------------- Initialize the config menu + _configMenu = new QPopupMenu( this, "config menu" ); + + // Auto Verify + QAction* autoVerify = new QAction( i18n("Verify on the Fly"), 0, this ); + autoVerify->setToggleAction( true ); + autoVerify->setOn( true ); + connect( autoVerify, SIGNAL( toggled( bool ) ), this, SLOT( updateVerifyButton( bool ) ) ); + connect( autoVerify, SIGNAL( toggled( bool ) ), this, SIGNAL( autoVerify( bool ) ) ); + autoVerify->addTo( _configMenu ); + autoVerify->setToolTip( i18n( "Toggle on-the-fly verification of regular expression" ) ); + autoVerify->setWhatsThis( i18n( "Enabling this option will make the verifier update for each edit. " + "If the verify window contains much text, or if the regular expression is either " + "complex or matches a lot of time, this may be very slow.")); + + // RegExp Languages + QPopupMenu* languages = new QPopupMenu( _configMenu ); + _languageId = _configMenu->insertItem( i18n("RegExp Language"), languages ); + + QActionGroup* grp = new QActionGroup( this ); + for( QValueList< QPair >::Iterator it = _converters.begin(); it != _converters.end(); ++it ) { + QString name = (*it).first->name(); + QAction* action = new QAction( name, 0, this ); + action->setToggleAction( true ); + grp->add( action ); + (*it).second = action; + } + grp->addTo( languages ); + connect( grp, SIGNAL( selected( QAction* ) ), this, SLOT( slotChangeSyntax( QAction* ) ) ); + _configMenu->setItemEnabled( _languageId, false ); + + // Select the Qt converter by default + setSyntax( qtConverterName ); +} + + + +void VerifyButtons::updateVerifyButton( bool b ) +{ + _verify->setEnabled( !b ); +} + +void VerifyButtons::loadText() +{ + QString fileName = KFileDialog::getOpenFileName(QString::null, QString::null, this); + if ( !fileName.isNull() ) { + emit loadVerifyText( fileName ); + } +} + +// Qt anchors do not work for
    ...
    , thefore scrolling to next/prev match +// do not work. Enable this when they work. +// void VerifyButtons::enableBackwardButtons( bool b ) +// { +// _first->setEnabled( b ); +// _prev->setEnabled( b ); +// } +// +// void VerifyButtons::enableForwardButtons( bool b ) +// { +// _next->setEnabled( b ); +// _last->setEnabled( b ); +// } + +void VerifyButtons::setMatchCount( int /*count*/ ) +{ +// currently this is not possible due to limitation in QSyntaxHighlighter +/* + if ( count == -1 ) + _matches->setText( QString::fromLatin1("-") ); + else + _matches->setText( QString::number( count ) ); +*/ +} + +void VerifyButtons::slotChangeSyntax( QAction* action ) +{ + emit changeSyntax( action->menuText() ); +} + +RegExpConverter* VerifyButtons::setSyntax( const QString& which) +{ + for( QValueList< QPair >::Iterator it = _converters.begin(); it != _converters.end(); ++it ) { + QString name = (*it).first->name(); + if ( name == which ) { + (*it).second->setOn( true ); + return (*it).first; + } + } + qWarning( "No such converter: '%s'", which.latin1() ); + return 0; +} + +void VerifyButtons::configure() +{ + _configMenu->exec( QCursor::pos() ); +} + +void VerifyButtons::setAllowNonQtSyntax( bool b ) +{ + _configMenu->setItemEnabled( _languageId, b ); +} diff --git a/kregexpeditor/verifybuttons.h b/kregexpeditor/verifybuttons.h new file mode 100644 index 0000000..aaf3593 --- /dev/null +++ b/kregexpeditor/verifybuttons.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef VERIFYBUTTONS_H +#define VERIFYBUTTONS_H + +#include +#include "regexpconverter.h" +class QToolButton; +class QLabel; +class QAction; +class QPopupMenu; + +class VerifyButtons :public QDockWindow +{ + Q_OBJECT + +public: + VerifyButtons( QWidget* parent, const char* name ); + RegExpConverter* setSyntax( const QString& ); + void setAllowNonQtSyntax( bool ); + +signals: + void verify(); + void autoVerify( bool ); + void loadVerifyText( const QString& ); + + // Qt anchors do not work for
    ...
    , thefore scrolling to next/prev match + // do not work. Enable this when they work. + // void gotoFirst(); + // void gotoPrev(); + // void gotoNext(); + // void gotoLast(); + + void changeSyntax( const QString& ); + +public slots: + // void enableForwardButtons( bool ); + // void enableBackwardButtons( bool ); + void setMatchCount( int ); + +protected slots: + void updateVerifyButton( bool ); + void loadText(); + void slotChangeSyntax( QAction* action ); + void configure(); + +private: + QToolButton* _verify; + QLabel* _matches; + QPopupMenu* _configMenu; + int _languageId; + + // Qt anchors do not work for
    ...
    , thefore scrolling to next/prev match + // do not work. Enable this when they work. + // QToolButton* _first; + // QToolButton* _prev; + // QToolButton* _next; + // QToolButton* _last; + + QValueList< QPair > _converters; +}; + + +#endif // VERIFYBUTTONS_H diff --git a/kregexpeditor/widgetfactory.cpp b/kregexpeditor/widgetfactory.cpp new file mode 100644 index 0000000..e2e860d --- /dev/null +++ b/kregexpeditor/widgetfactory.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifdef QT_ONLY + #include "compat.h" +#else + #include +#endif + +#include "widgetfactory.h" +#include "repeatwidget.h" +#include "textwidget.h" +#include "characterswidget.h" +#include "altnwidget.h" +#include "zerowidgets.h" +#include "compoundwidget.h" +#include "concwidget.h" +#include "lookaheadwidget.h" + +#include "textregexp.h" +#include "textrangeregexp.h" +#include "repeatregexp.h" +#include "lookaheadregexp.h" +#include "concregexp.h" +#include "altnregexp.h" +#include "positionregexp.h" +#include "dotregexp.h" +#include "kregexpeditorgui.h" + +bool WidgetFactory::isContainer( RegExpType tp ) +{ + return ( tp == REPEAT || tp == ALTN || tp == COMPOUND ); +} + +RegExpWidget* WidgetFactory::createWidget( RegExpEditorWindow* win, QWidget* parent, + RegExpType type ) +{ + RegExpWidget* widget = 0; + + switch (type) { + case TEXT: + return new TextWidget( win, parent ); break; + case ALTN: + return new AltnWidget( win, parent ); break; + case DOT: + return new AnyCharWidget( win, parent ); break; + case BEGLINE: + return new BegLineWidget( win, parent ); break; + case ENDLINE: + return new EndLineWidget( win, parent ); break; + case WORDBOUNDARY: + return new WordBoundaryWidget( win, parent ); break; + case NONWORDBOUNDARY: + return new NonWordBoundaryWidget( win, parent ); break; + case POSLOOKAHEAD: + case NEGLOOKAHEAD: + return new LookAheadWidget( win, type, parent ); break; + case REPEAT: + widget = new RepeatWidget( win, parent ); break; + case CHARSET: + widget = new CharactersWidget( win, parent ); break; + case COMPOUND: + widget = new CompoundWidget( win, parent ); break; + default: + qFatal("It should not be possible to get here!"); + return 0; + } + + if ( widget->edit() == QDialog::Rejected ) { + delete widget; + return 0; + } + return widget; +} + +RegExpWidget* WidgetFactory::createWidget( RegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent ) +{ + if ( regexp == 0 ) { + qFatal("%s:%d Regexp is 0", __FILE__, __LINE__ ); + } + else if ( TextRegExp* reg = dynamic_cast( regexp ) ) + return new TextWidget( reg, editorWindow, parent ); + else if ( TextRangeRegExp* reg = dynamic_cast( regexp ) ) + return new CharactersWidget( reg, editorWindow, parent ); + else if ( RepeatRegExp* reg = dynamic_cast( regexp ) ) + return new RepeatWidget( reg, editorWindow, parent ); + else if ( LookAheadRegExp* reg = dynamic_cast( regexp ) ) { + if ( reg->lookAheadType() == LookAheadRegExp::POSITIVE ) + return new LookAheadWidget( reg, editorWindow, POSLOOKAHEAD, parent ); + else + return new LookAheadWidget( reg, editorWindow, NEGLOOKAHEAD, parent ); + } + else if ( ConcRegExp* reg = dynamic_cast( regexp ) ) + return new ConcWidget( reg, editorWindow, parent ); + else if ( AltnRegExp* reg = dynamic_cast( regexp ) ) + return new AltnWidget( reg, editorWindow, parent ); + else if ( PositionRegExp* reg = dynamic_cast( regexp ) ) { + switch ( reg->position() ) { + case PositionRegExp::BEGLINE: + return new BegLineWidget( editorWindow, parent ); + case PositionRegExp::ENDLINE: + return new EndLineWidget( editorWindow, parent ); + case PositionRegExp::WORDBOUNDARY: + return new WordBoundaryWidget( editorWindow, parent ); + case PositionRegExp::NONWORDBOUNDARY: + return new NonWordBoundaryWidget( editorWindow, parent ); + } + } + else if ( dynamic_cast( regexp ) ) + return new AnyCharWidget( editorWindow, parent ); + else if ( CompoundRegExp* reg = dynamic_cast( regexp ) ) + return new CompoundWidget( reg, editorWindow, parent ); + else { + qFatal("%s:%d Internal Error: Unknown RegExp type", __FILE__, __LINE__); + } + return 0; +} + +RegExp* WidgetFactory::createRegExp( QDomElement node, const QString& version ) +{ + QString tag = node.tagName(); + RegExp* regexp; + if ( tag == QString::fromLocal8Bit( "TextRange" ) ) + regexp = new TextRangeRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "Text" ) ) + regexp = new TextRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "Concatenation" ) ) + regexp = new ConcRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "Alternatives" ) ) + regexp = new AltnRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "BegLine" ) ) + regexp = new PositionRegExp( false, PositionRegExp::BEGLINE ); + else if ( tag == QString::fromLocal8Bit( "EndLine" ) ) + regexp = new PositionRegExp( false, PositionRegExp::ENDLINE ); + else if ( tag == QString::fromLocal8Bit( "WordBoundary" ) ) + regexp = new PositionRegExp( false, PositionRegExp::WORDBOUNDARY ); + else if ( tag == QString::fromLocal8Bit( "NonWordBoundary" ) ) + regexp = new PositionRegExp( false, PositionRegExp::NONWORDBOUNDARY ); + else if ( tag == QString::fromLocal8Bit( "PositiveLookAhead" ) ) + regexp = new LookAheadRegExp( false, LookAheadRegExp::POSITIVE ); + else if ( tag == QString::fromLocal8Bit( "NegativeLookAhead" ) ) + regexp = new LookAheadRegExp( false, LookAheadRegExp::NEGATIVE ); + else if ( tag == QString::fromLocal8Bit( "Compound" ) ) + regexp = new CompoundRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "AnyChar" ) ) + regexp = new DotRegExp( false ); + else if ( tag == QString::fromLocal8Bit( "Repeat" ) ) + regexp = new RepeatRegExp( false ); + else { + KMessageBox::sorry( 0, i18n("

    Unknown tag while reading XML. Tag was %1

    ").arg(tag), + i18n("Error While Loading From XML File") ) ; + + return 0; + } + + bool ok = regexp->load( node, version ); + if (ok) + return regexp; + else { + delete regexp; + return 0; + } + return 0; +} + +RegExp* WidgetFactory::createRegExp( QString str ) +{ + QDomDocument doc; + bool ok = doc.setContent( str ); + if ( !ok ) { + KMessageBox::sorry( 0, i18n("Error while loading regular expression from XML. Most probably the regular expression had unmatched tags."), + i18n("Error While Loading Regular Expression From XML") ) ; + } + + + // Read the RegularExpression element, and extract the version. + QDomElement top = doc.documentElement(); + if (! (top.tagName() == QString::fromLocal8Bit("RegularExpression")) ) { + KMessageBox::sorry( 0, i18n("

    XML file did not contain a %1 tag.

    ").arg(QString::fromLatin1("RegularExpression")), + i18n("Error While Loading From XML File") ) ; + } + QString version = top.attribute( QString::fromLocal8Bit("version"), KRegExpEditorGUI::version ); + QDomNode child = top.firstChild(); + if ( ! child.isElement() ) { + KMessageBox::sorry( 0, i18n("

    Error while reading XML file. The element just below the tag " + "%1 was not an element.

    ").arg(QString::fromLatin1("RegularExpression")), + i18n("Error While Loading From XML File") ) ; + } + + RegExp* regexp = WidgetFactory::createRegExp( child.toElement(), version ); + + return regexp; +} + diff --git a/kregexpeditor/widgetfactory.h b/kregexpeditor/widgetfactory.h new file mode 100644 index 0000000..b1d1f26 --- /dev/null +++ b/kregexpeditor/widgetfactory.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef widgetfactory +#define widgetfactory + +#include + +class RegExpWidget; +class RegExpEditorWindow; +class QWidget; +class ConcWidget; +class RegExp; + +/** + All the different regular expression types. +*/ +enum RegExpType { + TEXT = 0, CHARSET = 1, DOT = 2, REPEAT = 3, ALTN = 4, COMPOUND = 5, BEGLINE = 6, + ENDLINE = 7, WORDBOUNDARY = 8, NONWORDBOUNDARY = 9, CONC = 10, DRAGACCEPTER = 11, + POSLOOKAHEAD = 12, NEGLOOKAHEAD = 13 +}; + +/** + Class used to encapsulate information about widgets. + + When reading widgets from a stream, it is necessary to know about all + sub-widgets to the @ref RegExpWidget class. This class exists to make + sure that such general information is only kept once. + + @internal +*/ +class WidgetFactory +{ +public: + static RegExpWidget* createWidget( RegExpEditorWindow* editorWindow, QWidget* parent, + RegExpType type ); + static RegExpWidget* createWidget( RegExp* regexp, RegExpEditorWindow* editorWindow, + QWidget* parent ); + static RegExp* createRegExp( QDomElement node, const QString& version ); + static RegExp* createRegExp( QString str ); + static bool isContainer( RegExpType ); +}; + +#endif // widgetfactory + diff --git a/kregexpeditor/zerowidgets.cpp b/kregexpeditor/zerowidgets.cpp new file mode 100644 index 0000000..94a15d5 --- /dev/null +++ b/kregexpeditor/zerowidgets.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifdef QT_ONLY + #include "compat.h" +#else + #include +#endif + +#include "zerowidgets.h" +#include "dotregexp.h" +#include "positionregexp.h" +#include +#include "myfontmetrics.h" +//-------------------------------------------------------------------------------- +// ZeroWidget +//-------------------------------------------------------------------------------- +ZeroWidget::ZeroWidget(QString txt, RegExpEditorWindow* editorWindow, + QWidget *parent, const char *name) + : RegExpWidget(editorWindow, parent, name ? name : "ZeroWidget" ) +{ + _text = txt; +} + +void ZeroWidget::addNewChild(DragAccepter *, RegExpWidget *) +{ + qFatal("No children should be added to this widget!"); +} + +QSize ZeroWidget::sizeHint() const +{ + QFontMetrics metrics = fontMetrics(); + _textSize = HackCalculateFontSize( metrics, _text ); + // _textSize = metrics.size(0,_text); + _boxSize = QSize(_textSize.width() + 2*space, _textSize.height() + 2 *space); + return _boxSize; +} + +void ZeroWidget::paintEvent( QPaintEvent *e) +{ + // So what is my Size? + QSize mySize = sizeHint(); + + QPainter painter(this); + drawPossibleSelection( painter, mySize); + + // Write the text and the rectangle + painter.drawText(space, space, _textSize.width(), _textSize.height(), 0, _text); + painter.drawRoundRect(0, 0, _boxSize.width(), _boxSize.height()); + + RegExpWidget::paintEvent(e); +} + + +//-------------------------------------------------------------------------------- +// AnyCharWidget +//-------------------------------------------------------------------------------- +AnyCharWidget::AnyCharWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : ZeroWidget(i18n("Any\nCharacter"), editorWindow, parent, + name ? name : "AnyCharWidget") +{ +} + +RegExp* AnyCharWidget::regExp() const +{ + return new DotRegExp( isSelected() ); +} + + +//-------------------------------------------------------------------------------- +// BegLineWidget +//-------------------------------------------------------------------------------- +BegLineWidget::BegLineWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : ZeroWidget(i18n("Line\nStart"), editorWindow, parent, + name ? name : "BegLineWidget") +{ +} + +RegExp* BegLineWidget::regExp() const +{ + return new PositionRegExp( isSelected(), PositionRegExp::BEGLINE ); + +} + +//-------------------------------------------------------------------------------- +// EndLineWidget +//-------------------------------------------------------------------------------- +EndLineWidget::EndLineWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : ZeroWidget(i18n("Line\nEnd"), editorWindow, parent, name) +{ +} + +RegExp* EndLineWidget::regExp() const +{ + return new PositionRegExp( isSelected(), PositionRegExp::ENDLINE ); +} + +//-------------------------------------------------------------------------------- +// WordBoundaryWidget +//-------------------------------------------------------------------------------- +WordBoundaryWidget::WordBoundaryWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : ZeroWidget(i18n("Word\nBoundary"), editorWindow, parent, + name ? name : "WordBoundaryWidget" ) +{ +} + +RegExp* WordBoundaryWidget::regExp() const +{ + return new PositionRegExp( isSelected(), PositionRegExp::WORDBOUNDARY ); +} + +//-------------------------------------------------------------------------------- +// NonWordBoundaryWidget +//-------------------------------------------------------------------------------- +NonWordBoundaryWidget::NonWordBoundaryWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name) + : ZeroWidget(i18n("Non-word\nBoundary"), editorWindow, parent, + name ? name : "NonWordBoundaryWidget" ) +{ +} + +RegExp* NonWordBoundaryWidget::regExp() const +{ + return new PositionRegExp( isSelected(), PositionRegExp::NONWORDBOUNDARY ); +} + diff --git a/kregexpeditor/zerowidgets.h b/kregexpeditor/zerowidgets.h new file mode 100644 index 0000000..cd5e9be --- /dev/null +++ b/kregexpeditor/zerowidgets.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002-2003 Jesper K. Pedersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ +#ifndef zerowidget +#define zerowidget + +#include "regexpwidget.h" + +/** + Represents any widget in the regular expression dialog, which do not have sub widget. + @internal +*/ +class ZeroWidget :public RegExpWidget +{ +public: + ZeroWidget(QString text, RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + virtual void addNewChild(DragAccepter *accepter, RegExpWidget *child); + virtual QSize sizeHint() const; + +protected: + virtual void paintEvent( QPaintEvent *e ); + +private: + QString _text; + + mutable QSize _textSize; + mutable QSize _boxSize; +}; + + + +/** + RegExp widget for `any single character' + @internal +*/ +class AnyCharWidget :public ZeroWidget +{ +public: + AnyCharWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *label = 0); + + virtual RegExp* regExp() const; + virtual RegExpType type() const { return DOT; } +}; + + + + +/** + RegExp widget for `beginning of line' + @internal +*/ +class BegLineWidget : public ZeroWidget +{ +public: + BegLineWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + virtual RegExp* regExp() const; + virtual RegExpType type() const { return BEGLINE; } +}; + + + + +/** + RegExp widget for `end of line' + @internal +*/ +class EndLineWidget : public ZeroWidget +{ +public: + EndLineWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + virtual RegExp* regExp() const; + virtual RegExpType type() const { return ENDLINE; } +}; + + + +/** + RegExp widget for `word boundary' + @internal +*/ +class WordBoundaryWidget : public ZeroWidget +{ +public: + WordBoundaryWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + virtual RegExp* regExp() const; + virtual RegExpType type() const { return WORDBOUNDARY; } +}; + + + + +/** + RegExp widget for `end of word' + @internal +*/ +class NonWordBoundaryWidget : public ZeroWidget +{ +public: + NonWordBoundaryWidget(RegExpEditorWindow* editorWindow, QWidget *parent, + const char *name = 0); + virtual RegExp* regExp() const; + virtual RegExpType type() const { return NONWORDBOUNDARY; } +}; + +#endif // zerowidget + diff --git a/ksim/AUTHORS b/ksim/AUTHORS new file mode 100644 index 0000000..ceef583 --- /dev/null +++ b/ksim/AUTHORS @@ -0,0 +1,2 @@ +Robbie Ward +Jason Katz-Brown diff --git a/ksim/BUGS b/ksim/BUGS new file mode 100644 index 0000000..8a3e620 --- /dev/null +++ b/ksim/BUGS @@ -0,0 +1,3 @@ +Current known bugs (as of 1.1.0): + + * see bugs.kde.org diff --git a/ksim/COPYING b/ksim/COPYING new file mode 100644 index 0000000..37ba36f --- /dev/null +++ b/ksim/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ksim/ChangeLog b/ksim/ChangeLog new file mode 100644 index 0000000..837a287 --- /dev/null +++ b/ksim/ChangeLog @@ -0,0 +1,363 @@ +KSim 1.1.0: + +Bug/Feature Changes: + * KSim no longer needs to generate gkrellmrc_ksim files, KSim will keep + the parsed file in memory + * Save the "on all desktop settings" when ksim is minimised + * Fixed the crash in the sensors plugin when using lm_sensors 2.7.0 + * Rewrote the CPU plugin, this should fix the problems with smp systems + * Made KSim a Kicker extension + * Made the configuration pages more user friendly + * Dont display filesystems if the block size is zero + * Fixed unsaved checked / unchecked items in the filesystem plugin being + removed when the configuration page is redisplayed + +API Changes: + * None + + -- Robbie Ward + +KSim 1.0.0: + +Bug/Feature Changes: + * Fixed a crash in ksim_disk when using FreeBSD + * Fixed the odd crash when ok or close is clicked in the config + dialog + * Added checks to fix compile issues on older kernel versions + * Some compile fixes for certain platforms + * Fixed a crash in KSim::ThemeLoader which occurred when + the theme alternative was set to a higher value than it should + * Fixed rare crashes in KSim::Led + +API Changes: + * No need to reimplement sizePolicy() in KSim::Label + and KSim::Chart + * Fixed spelling mistakes in the API + + -- Robbie Ward Saturday 02 November 2002 + +KSim 0.9.0: + +Bug/Feature Changes: + * Added checkbox to turn on / off the FQDN option + * Display the data in the net, cpu and disk plugins when + they get loaded + * Small cpu usage fix in the net plugin + * Added the option to recolour themes to the current + KDE color scheme + * Less expensive masking routines for the leds, and a less + expensive background drawing routine for labels + * The disk plugin is now able to monitor multiple disks + * Fixed the problem with the mininum width not being set + correctly in the filesystem when some entries were long + * Only remove a net device from the net plugin configuration + page when the apply button is clicked + * Remove partitions from the filesystem configuration page if + any partitions have been unmounted + +API Changes: + * Made the function names in KSim::Theme more consistant + * Moved setMinValue(), setMaxValue(), setValue() and setTitle() + from public to public slots in KSim::Chart + * Made KSim::ThemeLoader::currentTheme() a reference rather + than a pointer and renamed it to current() + * Renamed *Module() to *Plugin() in KSim::PluginLoader + * Renamed KSim::ThemeLoader::currentTheme*() to current*() + * Moved KSim::Label::setType() from protected to public + * Renamed KSim::ThemeLoader::parseThemeDir to parseDir + * Renamed KSim::ThemeLoader::themeAltString() to alternativeAsString() + * Made KSim::ThemeLoader::pargeConfig() and parseDir() static + * Renamed the KSim::ThemeLoader::ImageType enum to PixmapType + * Added some functions to KSim::Chart, KSim::Progress + and KSim::LedLabel + + -- Robbie Ward Wednesday 05 June 2002 + +KSim 0.8.1: + +Bug/Feature Changes: + * Fixed the bug in KSim::Label which sometimes prevented setText() + from updatig the display, the clock and uptime was affected by this + +API Changes: + * None + + -- Robbie Ward Monday 20 May 2002 + +KSim 0.8.0: + +Bug/Feature Changes: + * Make the filesystem plugin compile on Solaris + * Fixed the exec command option + * Fixed the SMP bug in the cpu plugin + * Build fixes in the cpu plugin for OpenBSD + * Added the option to display a short version of a mount point in + the filesystem plugin + * Fixed the problem with the progress meters not working sometimes + * Added the option to not display a FQDN, no GUI config option + at this time. To enable add 'DisplayFqdn=false' to ksimrc under + the '[Misc]' section + +API Changes: + * Added some new functions to KSim::Led + * Be consistant with the way the word 'Colour' is used in function names + * Added a KSim::Theme::currentFont() function which returns the + font KSim should use according to fontItem(); + * Renamed KSim::Led::setImage to setPixmap + * Remember to update the geometry so the layout can get a new sizeHint() + * Renamed setThemeImage to setThemePixmap and + setMeterImage to setThemePixmap + * Let KSim handle the config()->sync() call rather than the plugins + * Added a non-const version of KSim::PluginLoader::pluginList() + * Added a KSim::PluginLoader::plugin() function which returns + the last plugin loaded (or a null plugin if one couldnt be loaded) + * Also added a non-const version of KSim::PluginLoader::plugin() + * Renamed splitImage to splitPixmap in KSim::Theme + * Added a KSim::Theme::pixmapToList function + * Changed KSim::Chart::text() to accept a KSim::Chart::DataType + enum rather than an int + * Make the second parameter in KSim::Chart::setValue() have a + default value + * Added a new constructor to KSim::Progress + * Added a new constructor to KSim::LedLabel + * Document the KSim::PluginInfo class + * Append "ksim_" to the config filename for the plugins + * Added an extra SearchType to KSim::PluginLoader::findPlugin() + called LibName + + -- Robbie Ward Saturday 11 May 2002 + +KSim 0.7.0: + +Bug/Feature Changes: + * Display an error message if a network interface is added + which is already in the listview + * Disable the speed spin box if the stack items checkbox is not + ticked in the filesystem plugin config page + * Cleaned up the filesystem plugin config page GUI a little + * Cleaned up the sensors plugin config page GUI a little + * Some text / word corrections and spelling corrections + * Update the disk plugin display asap if anything has changed + * Dont set the hours, minutes and seconds time in the net plugin + if they are an invalid time format + * Update the memory and swap text labels when KSim reloads its + configuration rather than doing it 5 seconds later + * Dont increase the size of the filesystem view every time a + filesystem display is added or removed + * Pevent the net plugin from showing wacko in and out values + when a net interface is added or removed + * Prevent KSim from increasing size by 1 or 2 pixels when KSim + reloads its configuration + * Fixed the filesystem plugin view resizing to the wrong width when + an item is added + * Fixed the very weird problem where the led label and the normal + label would appear above the graphs for some people + * Fixed the bug where KSim would be resized to a very large width + when the net plugin was loaded after KSim had started + * Dont wait a second before we display the uptime and clock text + at KSim startup + * Fixed the problem with the filesystem plugin not being set to the + correct width sometimes when the plugin was loaded + * Fixed the bug where KSim would sometimes not be resize itself + to the correct height due to a bug in the filesystem plugin + * Added check for getloadavg() for some systems that dont have + this function + * Set the minimum width to the smallest possible rather than + hardcoding it to 80 pixels + * Dont store the enabled/disabled plugin as the translated plugin + name but the library name instead + * Relayout the leds correctly in KSim::LedLabel on theme change + +API Changes: + * Added a 'KSim::Theme::splitImage(ImageType type, bool useDefault)' + function + * Added two new functions to KSim::PluginObject which are + 'void setConfigFileName(const QString &)' and + 'const QString &configFileName()' + * Make the singleton instances return a reference rather than a + pointer to prevent accidental deletion + * Made the cleanup() functions in KSim::PluginLoader and + KSim::ThemeLoader private, so only the core of KSim can + cleanup these classes and nothing else + * Added a KSim::PluginLoader::findPlugin() method, which finds + out various plugin information from the string you give it + + -- Robbie Ward Saturday 27 April 2002 + +KSim 0.6.1: + +Bug/Feature Changes: + * Correctly set the default krell depth value so some themes dont show + the whole image as the meter/panel + * Only show the first part of the image rather than the whole image when + the progress bars are told to display krell_meter.png + * Dont forget to create the LED masks if needed + * Some FreeBSD build fixes in the net and disk plugins + * Fixed a recursive looping crash when there was no KSim config file + +API Changes: + * None + + -- Robbie Ward Tuesday 16 April 2002 + +KSim 0.6.0: + +Bug/Feature Changes: + * Added a modify button on the net configuration page + * Dont store absolute paths in the theme configuration, so if one + moves their kdedir to somewhere else then they wont have to + change any configuration settings + * Display a more correct value of the free ram on linux + * Fixed the bug where some themes would prevent any + data being drawn onto the graphs + * Reload the config page settings when the close button + is clicked in the config dialog + * Keep any changes in the sensor config listview unless + the apply/ok/close buttons are clicked in the config dialog + * Fixed the crash when enabling the clock, date, uptime, + memory or swap displays + * Fixed the charts not being resized when KSim reloads its + configuration + * Correcly show/hide the systray on configuration reload + * Correcly check/uncheck the always on top menu item if + the config option has changed + * Keep any changes in the filesystem config listview unless + the apply/ok/close buttons are clicked in the config dialog + +API Changes: + * Added a bool isThemeOnly() function in KSim::Base + which tells KSim if this KSim::Base instance should + have configureObject() called even if the theme hasn't + changed + + -- Robbie Ward Sunday 14 April 2002 + +KSim 0.5.1: + +Bug/Feature Changes: + * Added uptime and clock icons for the config dialog + * Fixed the problem when KSim would resize to 0 when the + apply button is clicked + * Removed the nice checkbox from the cpu config page and + added a new cpu key (%T which is user + sys + nice) + * Correcly set the filesystem height on plugin reloading if the + stack items checkbox is ticked + * Fixed the problem of the list view not being cleared in the + sensors plugin when the config dialog closes + +API Changes: + * None + + -- Robbie Ward Thursday 28 March 2002 + +KSim 0.5: + +Bug/Feature Changes: + * Added Disk monitor plugin + * Added Mail monitor plugin (written by Malte Starostik) + * Worked around the leak in the sensors plugin + * Set the backgrounds of widgets correctly if UseThemes is set to false + * Changed the combo boxes in the add net dialog to url requesters + * Fixed the ASSERT warnings when the sensors plugin is initially configured + * Fixed the problems in the net plugin where there was a slight chance + the net device name (for the add net dialog) could contain the receive + bytes or the receive bytes data (for the main plugin) could contain the + net device also + * Speed improvement: dont recreate a plugins view if it is about to be + removed or if it was just loaded + * Remember to set the current text in the net dialog when you + double click on a net interface in the listview + * Display a "Are you sure you want to remove this net interface?" + message box when you ask KSim to remove the currently selected + net interface in the list view + +API Changes: + * Added a krellMail(bool = false) function in themeloader.h + * moved all the theme functions from common.h to themeloader.h + * Try and return an optional default value for the themeloader if the value + isnt found and then return the value for the default theme if that + also is invalid + + -- Robbie Ward Tuesday 26 March 2002 + +KSim 0.4: + +Bug/Feature Changes: + * Fixed the resize delay in the filesystem plugin + * Fixed segfault when KSim was started with an invalid 'themeUrl' entry + * Fixed compile problems on FreeBSD in the net plugin + * Ported the cpu plugin to OpenBSD and NetBSD + * Reduced flicker in the led labels + * More theme enhancements + * Faster theme loading times + * Dont move KSim to the location stored in the config file if the systray + icon hides and then later shows KSim's main view + * Stop the cpu plugin from updating when it reloads its configuration, + and then resume the updating once finished to avoid crashes + * Improved the speed/memory usage of the sensors plugin when + you are displaying many sensor labels + * Dont attempt to unload all plugins and then crash if there was a problem + loading a plugin when KSim starts up + * Update the listviews in the sensors and filesystem config pages when + the config page gets displayed and hidden + +API Changes: + * Return a null string if we cant open the theme's gkrellmrc + file in ThemeLoader::parseConfig() + * Completely removed the first arg in KSIM_INIT_PLUGIN() + * Removed the 'ksim' prefix from the installed headers (eg: ksimblah is + now blah.h), this only affects people who write plugins as + eg '#include ' will become '#include + + -- Robbie Ward Tuesday 05 March 2002 + +KSim 0.3: + + * Added CPU plugin + * Implemented more theme support + * Improved the performance and cleaned up the code in the net plugin + * Decode the filenames to Unicode when using the command line options + * Fixed the adding/removing interfaces problem in the net plugin + * Made the first arg in KSIM_INIT_PLUGIN() redundant + * Some speed/memory fixes + * Moved the misc config page to seperate pages in the config dialog + * Fixed the plugin reloading issues in the net, sensors and filesystem plugins + * Workaround fix for the expensiveness of colecting the meminfo on FreeBSD + * Added time/date display (patch from Heitham Omar) + * Fixed some leaks in the net/sensors/filesystem plugins + * Moved the two enums from KSim::Theme to KSim::Types + * Fixed various themeing issues + * Fixed various spelling mistakes + * Reset the net-plugin information to zero when a net interface goes off line + * Insert the available net interfaces into the add net interface dialog + * Fixed the bug where some themes (one without masked image borders) + would influence if KSim had a kwin deco or not + * Re-worked the KSim::Base class, a derived class of KSim::Base no + longer has to inherit a QObject derived class and doesn't have to + reimplement 'void setName(const char *name)' + + -- Robbie Ward Wednesday 13 February 2002 + +KSim 0.2: + + * Re-Wrote the Plugin/PluginLoader code + * Re-Wrote the ThemeLoader code + * Fixed various memleaks + * Implemented the graph widget + * Correctly collect the in/out net data + * Fixed various problems on FreeBSD + * Some speed improvements + * Other tweaks/fixes to the code + * Moved the remainder of the API to a KSim namespace + * Fixed errors with building plugins outside of KSim + * Made X-KSIM-PREFS (in the .desktop files) redundant + * Moved the set on all desktops/always on top popupmenu from + the frames of the app to the main popup menu + + -- Robbie Ward Saturday 05 January 2002 + +KSim 0.1: + + * Initial release + + -- Robbie Ward Thursday 28 June 2001 diff --git a/ksim/Makefile.am b/ksim/Makefile.am new file mode 100644 index 0000000..c8102cb --- /dev/null +++ b/ksim/Makefile.am @@ -0,0 +1,34 @@ +noinst_LTLIBRARIES = libsysteminfo.la + +libsysteminfo_la_SOURCES = systeminfo.cpp +libsysteminfo_la_LDFLAGS = -module -avoid-version + +kde_module_LTLIBRARIES = ksim_panelextension.la +ksim_panelextension_la_SOURCES = ksim.cpp ksimview.cpp ksimview.skel \ + ksimsysinfo.cpp ksimsysinfo.skel ksimframe.cpp \ + ksimpref.cpp monitorprefs.cpp generalprefs.cpp \ + themeprefs.cpp + +ksim_panelextension_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +ksim_panelextension_la_LIBADD = ./library/libksimcore.la libsysteminfo.la $(LIB_KIO) $(LIB_KDEUI) + +SUBDIRS = themes library monitors pics +EXTRA_DIST = ksim.desktop +METASOURCES = AUTO +CLEANFILES = dummy.cpp + +extension_DATA = ksim.desktop +extensiondir = $(kde_datadir)/kicker/extensions + +dummy.cpp: + echo > dummy.cpp + +INCLUDES= -I$(top_srcdir)/ksim/library \ + $(all_includes) + +conf_DATA = ksim_panelextensionrc +confdir = $(kde_confdir) + +messages: rc.cpp + $(EXTRACTRC) */*.rc */*.ui *.ui *.rc >> rc.cpp + $(XGETTEXT) `find . -name "*.cpp"` -o $(podir)/ksim.pot diff --git a/ksim/README b/ksim/README new file mode 100644 index 0000000..d5ee23a --- /dev/null +++ b/ksim/README @@ -0,0 +1,42 @@ +KSim - K System Information Monitor +----------------------------------- + +KSim is a plugin based system monitor that has +support for GKrellm (www.gkrellm.net) themes. + +KSim can currently monitor these types: + * Cpu usage (plugin) + * Net (eth0, ppp0 etc) usage (plugin) + * Filesystem usage (plugin) + * Sensors information (plugin) + * Disk information (plugin) + * Mail monitor (plugin) + * Clock & Date display + * Hostname display + * Uptime display + * Memory/Free Memory display + * Swap/Free Swap display + +The current planned features are: + * Proc monitor (plugin) + +NOTE: the plugin naming conventions changed +in v0.5 and above, i recommend you to +rm -rf $KDEDIR/lib/libksim* before you install +v0.5 or above, if you are using v0.4 or below. + +As of v0.9.0 and above, KSim has the option to +recolour themes to the current KDE color scheme, +if you have any problems of it recolouring to the wrong +color or some other recolouring related problem then +send me the name of the color scheme you are using +and the color values for your background and text color. + +Please read BUGS for a list of current known bugs +and ChangeLog for the changes in the last release. +Also the theme support isn't 100% implemented +(which it may never be), if you have any theme +related issues then please email me describing what +problem you had and with which theme. + +Any other problems? email me (linuxphreak@gmx.co.uk) diff --git a/ksim/TODO b/ksim/TODO new file mode 100644 index 0000000..f749d5b --- /dev/null +++ b/ksim/TODO @@ -0,0 +1,5 @@ +Current things todo (in any order): + + * Fix the bug in BUGS + * Insert the plugin views at the correct location and don't just append + them to the bottom of the view diff --git a/ksim/baselist.h b/ksim/baselist.h new file mode 100644 index 0000000..b55ab3b --- /dev/null +++ b/ksim/baselist.h @@ -0,0 +1,97 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef BASELIST_H +#define BASELIST_H + +#include +#include +#include + +namespace KSim +{ + class BaseList + { + public: + static void add(KSim::Base *object) + { + if (!m_baseList) { + m_baseList = new QPtrList; + m_baseList->setAutoDelete(false); + + // Make sure our m_baseList instance gets + // deleted when KSim exits + qAddPostRoutine(cleanup); + } + + if (!object) + return; + + m_baseList->append(object); + } + + static bool remove(KSim::Base *object) + { + if (!m_baseList) + return false; + + // Find our object and remove it from the list + if (m_baseList->findRef(object) >= 0) + return m_baseList->remove(); + + return false; + } + + static void configureObjects(bool themeChanged) + { + if (!m_baseList) + return; + + QPtrListIterator object(*m_baseList); + for (; object.current(); ++object) { + // Call processEvents() so our ui doesn't block + if (!object.current()->isThemeConfigOnly() || themeChanged) { + qApp->processEvents(); + object.current()->configureObject(true); + } + } + } + + private: + // Protect the class from being able to be created/deleted + BaseList(); + BaseList(const BaseList &); + BaseList &operator=(const BaseList &); + ~BaseList(); + + static void cleanup() + { + if (!m_baseList) + return; + + delete m_baseList; + m_baseList = 0L; + } + + static QPtrList *m_baseList; + }; + + QPtrList *BaseList::m_baseList = 0L; +} +#endif // BASELIST_H diff --git a/ksim/configure.in.in b/ksim/configure.in.in new file mode 100644 index 0000000..4ddee70 --- /dev/null +++ b/ksim/configure.in.in @@ -0,0 +1,36 @@ +AC_CHECK_FUNCS(getloadavg) + +sysinfo_check=no +case "$target" in + *-*-linux*) + sysinfo_check=yes + ;; +esac + +if test x$sysinfo_check = xyes; then + sysinfo_ok=no + AC_MSG_CHECKING(for totalhigh and totalfree in sysinfo) + AC_TRY_COMPILE( + [ + #include + + static void check() + { + struct sysinfo system; /* dummy sysinfo */ + int totalhigh = system.totalhigh; + int freehigh = system.freehigh; + } + ], [], + [ + sysinfo_ok=yes + AC_DEFINE_UNQUOTED(HAVE_SYSINFO_HIGH, 1, [whether we have totalhigh and freehigh]) + ]) + + AC_MSG_RESULT($sysinfo_ok) +fi + +dnl Check for dell laptop support +AM_CONDITIONAL(supports_i8k, test -f /proc/i8k) + +KDE_CHECK_HEADER(X11/extensions/extutil.h, AC_DEFINE(HAVE_EXTUTIL_H, 1, [If we have extutil.h]) have_extutil_h=yes, , ) +AM_CONDITIONAL(include_nv, test "x$have_extutil_h" = "xyes") diff --git a/ksim/generalprefs.cpp b/ksim/generalprefs.cpp new file mode 100644 index 0000000..1f3baf7 --- /dev/null +++ b/ksim/generalprefs.cpp @@ -0,0 +1,574 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "generalprefs.h" +#include "generalprefs.moc" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +KSim::GeneralPrefs::GeneralPrefs(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + m_mainLayout = new QGridLayout(this); + m_mainLayout->setSpacing(6); + + m_sizeBox = new QGroupBox(this); + m_sizeBox->setTitle(i18n("Graph Size")); + m_sizeBox->setColumnLayout(0, Qt::Horizontal); + + QGridLayout *sizeBoxLayout = new QGridLayout(m_sizeBox->layout()); + sizeBoxLayout->setSpacing(6); + + m_sizeHLabel = new QLabel(m_sizeBox); + m_sizeHLabel->setText(i18n("Graph height:")); + sizeBoxLayout->addWidget(m_sizeHLabel, 0, 0); + + m_sizeHSpin = new KIntSpinBox(m_sizeBox); + m_sizeHSpin->setValue(40); + m_sizeHSpin->setMinValue(40); + m_sizeHSpin->setMaxValue(200); + m_sizeHSpin->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, + QSizePolicy::Fixed)); + sizeBoxLayout->addWidget(m_sizeHSpin, 0, 1); + + QSpacerItem *sizeHSpacer = new QSpacerItem(20, 20, + QSizePolicy::Expanding, QSizePolicy::Minimum); + sizeBoxLayout->addItem(sizeHSpacer, 0, 2); + + m_sizeWLabel = new QLabel(m_sizeBox); + m_sizeWLabel->setText(i18n("Graph width:")); + sizeBoxLayout->addWidget(m_sizeWLabel, 1, 0); + + m_sizeWSpin = new KIntSpinBox(m_sizeBox); + m_sizeWSpin->setValue(58); + m_sizeWSpin->setMinValue(58); + m_sizeWSpin->setMaxValue(200); + m_sizeWSpin->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, + QSizePolicy::Fixed)); + sizeBoxLayout->addWidget(m_sizeWSpin, 1, 1); + + QSpacerItem *sizeWSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + sizeBoxLayout->addItem(sizeWSpacer, 1, 2); + + m_mainLayout->addWidget(m_sizeBox, 0, 0); + QSpacerItem *boxSpacer = new QSpacerItem(20, 20, + QSizePolicy::Expanding, QSizePolicy::Minimum); + m_mainLayout->addItem(boxSpacer, 0, 1); + + m_displayFqdn = new QCheckBox(this); + m_displayFqdn->setText(i18n("Display fully qualified domain name")); + m_mainLayout->addMultiCellWidget(m_displayFqdn, 1, 1, 0, 1); + + m_recolourThemes = new QCheckBox(this); + m_recolourThemes->setText(i18n("Recolor themes to the current color scheme")); + m_mainLayout->addMultiCellWidget(m_recolourThemes, 2, 2, 0, 1); + + QSpacerItem *spacer = new QSpacerItem(20, 20, + QSizePolicy::Minimum, QSizePolicy::Expanding); + m_mainLayout->addItem(spacer, 3, 0); +} + +KSim::GeneralPrefs::~GeneralPrefs() +{ +} + +void KSim::GeneralPrefs::saveConfig(KSim::Config *config) +{ + config->setGraphSize(QSize(m_sizeWSpin->value(), m_sizeHSpin->value())); + config->setDisplayFqdn(m_displayFqdn->isChecked()); + config->setReColourThemes(m_recolourThemes->isChecked()); +} + +void KSim::GeneralPrefs::readConfig(KSim::Config *config) +{ + QSize size = config->graphSize(); + m_sizeHSpin->setValue(size.height()); + m_sizeWSpin->setValue(size.width()); + m_displayFqdn->setChecked(config->displayFqdn()); + m_recolourThemes->setChecked(config->reColourThemes()); +} + +KSim::ClockPrefs::ClockPrefs(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + m_mainLayout = new QVBoxLayout(this); + m_mainLayout->setSpacing(6); + + m_timeCheck = new QCheckBox(i18n("Show time"),this); + m_mainLayout->addWidget(m_timeCheck); + m_timeCheck->setChecked(true); + + m_dateCheck = new QCheckBox(i18n("Show date"),this); + m_mainLayout->addWidget(m_dateCheck); + m_dateCheck->setChecked(true); + + QSpacerItem *spacer = new QSpacerItem(20, 20, + QSizePolicy::Minimum, QSizePolicy::Expanding); + m_mainLayout->addItem(spacer); +} + +KSim::ClockPrefs::~ClockPrefs() +{ +} + +void KSim::ClockPrefs::saveConfig(KSim::Config *config) +{ + config->setShowTime(m_timeCheck->isChecked()); + config->setShowDate(m_dateCheck->isChecked()); +} + +void KSim::ClockPrefs::readConfig(KSim::Config *config) +{ + m_timeCheck->setChecked(config->showTime()); + m_dateCheck->setChecked(config->showDate()); +} + +KSim::UptimePrefs::UptimePrefs(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + m_addIcon = SmallIconSet("filenew"); + m_removeIcon = SmallIconSet("editdelete"); + + m_mainLayout = new QVBoxLayout(this); + m_mainLayout->setSpacing(6); + + m_uptimeCombo = new KComboBox(true, this); + m_uptimeCombo->setDuplicatesEnabled(false); + m_uptimeCombo->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Fixed)); + m_uptimeCombo->insertItem(i18n("%hh:%mm:%ss")); + m_uptimeCombo->insertItem(i18n("%dd %h:%m")); + m_uptimeCombo->insertItem(i18n("Uptime: %h:%m:%s")); + connect(m_uptimeCombo, + SIGNAL(aboutToShowContextMenu(QPopupMenu *)), + SLOT(uptimeContextMenu(QPopupMenu *))); + + m_uptimeAdd = new QPushButton(this); + m_uptimeAdd->setPixmap(SmallIcon("down")); + connect(m_uptimeAdd, SIGNAL(clicked()), SLOT(insertUptimeItem())); + QToolTip::add(m_uptimeAdd, i18n("Insert item")); + + m_uptimeCheck = new QCheckBox(this); + m_uptimeCheck->setText(i18n("Show uptime")); + m_uptimeCheck->setChecked(true); + connect(m_uptimeCheck, SIGNAL(toggled(bool)), + m_uptimeCombo, SLOT(setEnabled(bool))); + connect(m_uptimeCheck, SIGNAL(toggled(bool)), + m_uptimeAdd, SLOT(setEnabled(bool))); + m_mainLayout->addWidget(m_uptimeCheck); + + m_subLayout = new QHBoxLayout; + m_subLayout->setSpacing(6); + + m_formatLabel = new QLabel(this); + m_formatLabel->setText(i18n("Uptime format:")); + m_subLayout->addWidget(m_formatLabel); + + m_subLayout->addWidget(m_uptimeCombo); + m_subLayout->addWidget(m_uptimeAdd); + m_mainLayout->addLayout(m_subLayout); + + m_uptimeInfo = new QLabel(this); + m_uptimeInfo->setText(i18n("The text in the edit box will be " + "what is displayed as \nthe uptime except the % items " + "will be replaced with \nthe legend")); + m_mainLayout->addWidget(m_uptimeInfo); + + m_uptimeBox = new QGroupBox(this); + m_uptimeBox->setTitle(i18n("Uptime Legend")); + m_uptimeBox->setColumnLayout(0, Qt::Vertical); + m_uptimeBox->layout()->setSpacing(0); + m_uptimeBox->layout()->setMargin(0); + m_boxLayout = new QVBoxLayout(m_uptimeBox->layout()); + m_boxLayout->setAlignment(Qt::AlignTop); + m_boxLayout->setSpacing(6); + m_boxLayout->setMargin(11); + + m_udLabel = new QLabel(m_uptimeBox); + m_udLabel->setText(i18n("%d - Total days uptime")); + m_boxLayout->addWidget(m_udLabel); + + m_uhLabel = new QLabel(m_uptimeBox); + m_uhLabel->setText(i18n("%h - Total hours uptime")); + m_boxLayout->addWidget(m_uhLabel); + + m_umLabel = new QLabel(m_uptimeBox); + m_umLabel->setText(i18n("%m - Total minutes uptime")); + m_boxLayout->addWidget(m_umLabel); + + m_usLabel = new QLabel(m_uptimeBox); + m_usLabel->setText(i18n("%s - Total seconds uptime")); + m_boxLayout->addWidget(m_usLabel); + m_mainLayout->addWidget(m_uptimeBox); + + QSpacerItem *spacer = new QSpacerItem(20, 20, + QSizePolicy::Minimum, QSizePolicy::Expanding); + m_mainLayout->addItem(spacer); +} + +KSim::UptimePrefs::~UptimePrefs() +{ +} + +void KSim::UptimePrefs::saveConfig(KSim::Config *config) +{ + config->setUptimeItem(m_uptimeCombo->currentItem()); + config->setShowUptime(m_uptimeCheck->isChecked()); + + QStringList comboItems; + for (int i = 0; i < m_uptimeCombo->count(); i++) + comboItems.append(m_uptimeCombo->text(i)); + + config->setUptimeFormat(comboItems); +} + +void KSim::UptimePrefs::readConfig(KSim::Config *config) +{ + m_uptimeCheck->setChecked(config->showUptime()); + + QStringList::ConstIterator it; + QStringList items = config->uptimeFormatList(); + for (it = items.begin(); it != items.end(); ++it) + if (!m_uptimeCombo->contains(*it)) + m_uptimeCombo->insertItem(*it); + + m_uptimeCombo->setCurrentItem(config->uptimeItem()); +} + +void KSim::UptimePrefs::uptimeContextMenu(QPopupMenu *menu) +{ + menu->insertSeparator(); + menu->insertItem(m_addIcon, i18n("Insert Item"), + this, SLOT(insertUptimeItem())); + menu->insertItem(m_removeIcon, i18n("Remove Item"), + this, SLOT(removeUptimeItem())); +} + +void KSim::UptimePrefs::insertUptimeItem() +{ + QString text = m_uptimeCombo->lineEdit()->text(); + if (!m_uptimeCombo->contains(text)) { + m_uptimeCombo->insertItem(text); + m_uptimeCombo->setCurrentItem(m_uptimeCombo->count() - 1); + } +} + +void KSim::UptimePrefs::removeUptimeItem() +{ + int currentItem = m_uptimeCombo->currentItem(); + m_uptimeCombo->removeItem(currentItem); + m_uptimeCombo->setCurrentItem(currentItem - 1); +} + +KSim::MemoryPrefs::MemoryPrefs(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + m_addIcon = SmallIconSet("filenew"); + m_removeIcon = SmallIconSet("editdelete"); + + m_mainLayout = new QVBoxLayout(this); + m_mainLayout->setSpacing(6); + + m_memCombo = new KComboBox(true, this); + m_memCombo->setDuplicatesEnabled(false); + m_memCombo->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Fixed)); + //m_memCombo->insertItem(i18n("%tM - %fM free")); + //m_memCombo->insertItem(i18n("%tM - %uM used")); + connect(m_memCombo, + SIGNAL(aboutToShowContextMenu(QPopupMenu *)), + SLOT(memoryContextMenu(QPopupMenu *))); + + m_memoryAdd = new QPushButton(this); + m_memoryAdd->setPixmap(SmallIcon("down")); + connect(m_memoryAdd, SIGNAL(clicked()), SLOT(insertMemoryItem())); + QToolTip::add(m_memoryAdd, i18n("Insert item")); + + m_memCheck = new QCheckBox(this); + m_memCheck->setText(i18n("Show memory and free memory")); + m_memCheck->setChecked(false); + connect(m_memCheck, SIGNAL(toggled(bool)), + m_memCombo, SLOT(setEnabled(bool))); + connect(m_memCheck, SIGNAL(toggled(bool)), + m_memoryAdd, SLOT(setEnabled(bool))); + m_mainLayout->addWidget(m_memCheck); + + m_subLayout = new QHBoxLayout; + m_subLayout->setSpacing(6); + + m_memFormat = new QLabel(this); + m_memFormat->setText(i18n("Mem format:")); + m_subLayout->addWidget(m_memFormat); + + m_subLayout->addWidget(m_memCombo); + m_subLayout->addWidget(m_memoryAdd); + m_mainLayout->addLayout(m_subLayout); + + m_memInfo = new QLabel(this); + m_memInfo->setText(i18n("The text in the edit box will be what " + "is displayed as \nthe memory & free memory except the " + "% items will be \nreplaced with the legend")); + m_mainLayout->addWidget(m_memInfo); + + m_memBox = new QGroupBox(this); + m_memBox->setTitle(i18n("Memory Legend")); + m_memBox->setColumnLayout(0, Qt::Vertical); + m_memBox->layout()->setSpacing(0); + m_memBox->layout()->setMargin(0); + m_boxLayout = new QVBoxLayout(m_memBox->layout()); + m_boxLayout->setAlignment(Qt::AlignTop); + m_boxLayout->setSpacing(6); + m_boxLayout->setMargin(11); + + m_mtLabel = new QLabel(m_memBox); + m_mtLabel->setText(i18n("%t - Total memory")); + m_boxLayout->addWidget(m_mtLabel); + + m_mfLabel = new QLabel(m_memBox); + m_mfLabel->setText(i18n("%F - Total free memory including cached and buffered")); + m_boxLayout->addWidget(m_mfLabel); + + m_mfLabel = new QLabel(m_memBox); + m_mfLabel->setText(i18n("%f - Total free memory")); + m_boxLayout->addWidget(m_mfLabel); + + m_muLabel = new QLabel(m_memBox); + m_muLabel->setText(i18n("%u - Total used memory")); + m_boxLayout->addWidget(m_muLabel); + + m_mcLabel = new QLabel(m_memBox); + m_mcLabel->setText(i18n("%c - Total cached memory")); + m_boxLayout->addWidget(m_mcLabel); + + m_mbLabel = new QLabel(m_memBox); + m_mbLabel->setText(i18n("%b - Total buffered memory")); + m_boxLayout->addWidget(m_mbLabel); + + m_msLabel = new QLabel(m_memBox); + m_msLabel->setText(i18n("%s - Total shared memory")); + m_boxLayout->addWidget(m_msLabel); + m_mainLayout->addWidget(m_memBox); + + QSpacerItem *spacer = new QSpacerItem(20, 20, + QSizePolicy::Minimum, QSizePolicy::Expanding); + m_mainLayout->addItem(spacer); +} + +KSim::MemoryPrefs::~MemoryPrefs() +{ +} + +void KSim::MemoryPrefs::saveConfig(KSim::Config *config) +{ + config->setMemoryItem(m_memCombo->currentItem()); + config->setShowMemory(m_memCheck->isChecked()); + + QStringList comboItems; + for (int i = 0; i < m_memCombo->count(); i++) + comboItems.append(m_memCombo->text(i)); + + config->setMemoryFormat(comboItems); +} + +void KSim::MemoryPrefs::readConfig(KSim::Config *config) +{ + m_memCheck->setChecked(config->showMemory()); + + QStringList::ConstIterator it; + QStringList items = config->memoryFormatList(); + for (it = items.begin(); it != items.end(); ++it) + if (!m_memCombo->contains(*it)) + m_memCombo->insertItem(*it); + + m_memCombo->setCurrentItem(config->memoryItem()); +} + +void KSim::MemoryPrefs::memoryContextMenu(QPopupMenu *menu) +{ + menu->insertSeparator(); + menu->insertItem(m_addIcon, i18n("Insert Item"), + this, SLOT(insertMemoryItem())); + menu->insertItem(m_removeIcon, i18n("Remove Item"), + this, SLOT(removeMemoryItem())); +} + +void KSim::MemoryPrefs::insertMemoryItem() +{ + QString text = m_memCombo->lineEdit()->text(); + if (!m_memCombo->contains(text)) { + m_memCombo->insertItem(text); + m_memCombo->setCurrentItem(m_memCombo->count() - 1); + } +} + +void KSim::MemoryPrefs::removeMemoryItem() +{ + int currentItem = m_memCombo->currentItem(); + m_memCombo->removeItem(currentItem); + m_memCombo->setCurrentItem(currentItem - 1); +} + +KSim::SwapPrefs::SwapPrefs(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + m_addIcon = SmallIconSet("filenew"); + m_removeIcon = SmallIconSet("editdelete"); + + m_mainLayout = new QVBoxLayout(this); + m_mainLayout->setSpacing(6); + + m_swapCheck = new QCheckBox(this); + m_swapCheck->setText(i18n("Show swap and free swap")); + m_swapCheck->setChecked(true); + m_mainLayout->addWidget(m_swapCheck); + + m_swapCombo = new KComboBox(true, this); + m_swapCombo->setDuplicatesEnabled(false); + m_swapCombo->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Fixed)); + //m_swapCombo->insertItem(i18n("%tM - %fM free")); + //m_swapCombo->insertItem(i18n("%tM - %uM used")); + + connect(m_swapCombo, + SIGNAL(aboutToShowContextMenu(QPopupMenu *)), + SLOT(swapContextMenu(QPopupMenu *))); + + m_swapAdd = new QPushButton(this); + m_swapAdd->setPixmap(SmallIcon("down")); + connect(m_swapAdd, SIGNAL(clicked()), SLOT(insertSwapItem())); + QToolTip::add(m_swapAdd, i18n("Insert item")); + + m_subLayout = new QHBoxLayout; + m_subLayout->setSpacing(6); + connect(m_swapCheck, SIGNAL(toggled(bool)), + m_swapCombo, SLOT(setEnabled(bool))); + connect(m_swapCheck, SIGNAL(toggled(bool)), + m_swapAdd, SLOT(setEnabled(bool))); + + m_swapFormat = new QLabel(this); + m_swapFormat->setText(i18n("Swap format:")); + m_subLayout->addWidget(m_swapFormat); + + m_subLayout->addWidget(m_swapCombo); + m_subLayout->addWidget(m_swapAdd); + m_mainLayout->addLayout(m_subLayout); + + m_swapInfo = new QLabel(this); + m_swapInfo->setText(i18n("The text in the edit box will be what is " + "displayed as \nthe swap & free swap except the % items " + "will be \nreplaced with the legend")); + m_mainLayout->addWidget(m_swapInfo); + + m_swapBox = new QGroupBox(this); + m_swapBox->setTitle(i18n("Swap Legend")); + m_swapBox->setColumnLayout(0, Qt::Vertical); + m_swapBox->layout()->setSpacing(0); + m_swapBox->layout()->setMargin(0); + m_boxLayout = new QVBoxLayout(m_swapBox->layout()); + m_boxLayout->setAlignment(Qt::AlignTop); + m_boxLayout->setSpacing(6); + m_boxLayout->setMargin(11); + + m_stLabel = new QLabel(m_swapBox); + m_stLabel->setText(i18n("%t - Total swap")); + m_boxLayout->addWidget(m_stLabel); + + m_sfLabel = new QLabel(m_swapBox); + m_sfLabel->setText(i18n("%f - Total free swap")); + m_boxLayout->addWidget(m_sfLabel); + + m_suLabel = new QLabel(m_swapBox); + m_suLabel->setText(i18n("%u - Total used swap")); + m_boxLayout->addWidget(m_suLabel); + m_mainLayout->addWidget(m_swapBox); + + QSpacerItem *spacer = new QSpacerItem(20, 20, + QSizePolicy::Minimum, QSizePolicy::Expanding); + m_mainLayout->addItem(spacer); +} + +KSim::SwapPrefs::~SwapPrefs() +{ +} + +void KSim::SwapPrefs::saveConfig(KSim::Config *config) +{ + config->setSwapItem(m_swapCombo->currentItem()); + + QStringList comboItems; + for (int i = 0; i < m_swapCombo->count(); i++) + comboItems.append(m_swapCombo->text(i)); + + config->setSwapFormat(comboItems); + config->setShowSwap(m_swapCheck->isChecked()); +} + +void KSim::SwapPrefs::readConfig(KSim::Config *config) +{ + m_swapCheck->setChecked(config->showSwap()); + + QStringList::ConstIterator it; + QStringList items = config->swapFormatList(); + for (it = items.begin(); it != items.end(); ++it) + if (!m_swapCombo->contains(*it)) + m_swapCombo->insertItem(*it); + + m_swapCombo->setCurrentItem(config->swapItem()); +} + +void KSim::SwapPrefs::swapContextMenu(QPopupMenu *menu) +{ + menu->insertSeparator(); + menu->insertItem(m_addIcon, i18n("Insert Item"), this, SLOT(insertSwapItem())); + menu->insertItem(m_removeIcon, i18n("Remove Item"), this, SLOT(removeSwapItem())); +} + +void KSim::SwapPrefs::insertSwapItem() +{ + QString text = m_swapCombo->lineEdit()->text(); + if (!m_swapCombo->contains(text)) { + m_swapCombo->insertItem(text); + m_swapCombo->setCurrentItem(m_swapCombo->count() - 1); + } +} + +void KSim::SwapPrefs::removeSwapItem() +{ + int currentItem = m_swapCombo->currentItem(); + m_swapCombo->removeItem(currentItem); + m_swapCombo->setCurrentItem(currentItem - 1); +} diff --git a/ksim/generalprefs.h b/ksim/generalprefs.h new file mode 100644 index 0000000..b163dac --- /dev/null +++ b/ksim/generalprefs.h @@ -0,0 +1,185 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef GENERAL_H +#define GENERAL_H + +#include +#include + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QCheckBox; +class QGroupBox; +class QLabel; +class QLineEdit; +class QTabWidget; +class KComboBox; +class QPopupMenu; +class QPushButton; +class KIntSpinBox; + +namespace KSim +{ + class Config; + + class GeneralPrefs : public QWidget + { + Q_OBJECT + public: + GeneralPrefs(QWidget *parent, const char *name=0); + ~GeneralPrefs(); + + public slots: + void saveConfig(KSim::Config *); + void readConfig(KSim::Config *); + + private: + QGridLayout *m_mainLayout; + QGroupBox *m_sizeBox; + QLabel *m_sizeHLabel; + KIntSpinBox *m_sizeHSpin; + QLabel *m_sizeWLabel; + KIntSpinBox *m_sizeWSpin; + QCheckBox *m_displayFqdn; + QCheckBox *m_recolourThemes; + }; + + class ClockPrefs : public QWidget + { + Q_OBJECT + public: + ClockPrefs(QWidget *parent, const char *name=0); + ~ClockPrefs(); + + public slots: + void saveConfig(KSim::Config *); + void readConfig(KSim::Config *); + + private: + QVBoxLayout *m_mainLayout; + QCheckBox *m_timeCheck; + QCheckBox *m_dateCheck; + }; + + class UptimePrefs : public QWidget + { + Q_OBJECT + public: + UptimePrefs(QWidget *parent, const char *name=0); + ~UptimePrefs(); + + public slots: + void saveConfig(KSim::Config *); + void readConfig(KSim::Config *); + + private slots: + void uptimeContextMenu(QPopupMenu *); + void insertUptimeItem(); + void removeUptimeItem(); + + private: + QVBoxLayout *m_mainLayout; + QHBoxLayout *m_subLayout; + QVBoxLayout *m_boxLayout; + KComboBox *m_uptimeCombo; + QPushButton *m_uptimeAdd; + QCheckBox *m_uptimeCheck; + QLabel *m_formatLabel; + QLabel *m_uptimeInfo; + QGroupBox *m_uptimeBox; + QLabel *m_udLabel; + QLabel *m_uhLabel; + QLabel *m_umLabel; + QLabel *m_usLabel; + QIconSet m_addIcon; + QIconSet m_removeIcon; + }; + + class MemoryPrefs : public QWidget + { + Q_OBJECT + public: + MemoryPrefs(QWidget *parent, const char *name=0); + ~MemoryPrefs(); + + public slots: + void saveConfig(KSim::Config *); + void readConfig(KSim::Config *); + + private slots: + void memoryContextMenu(QPopupMenu *); + void insertMemoryItem(); + void removeMemoryItem(); + + private: + QVBoxLayout *m_mainLayout; + QHBoxLayout *m_subLayout; + QVBoxLayout *m_boxLayout; + QCheckBox *m_memCheck; + QLabel *m_memFormat; + KComboBox *m_memCombo; + QLabel *m_memInfo; + QGroupBox *m_memBox; + QLabel *m_mtLabel; + QLabel *m_mfLabel; + QLabel *m_muLabel; + QLabel *m_mcLabel; + QLabel *m_mbLabel; + QLabel *m_msLabel; + QPushButton *m_memoryAdd; + QIconSet m_addIcon; + QIconSet m_removeIcon; + }; + + class SwapPrefs : public QWidget + { + Q_OBJECT + public: + SwapPrefs(QWidget *parent, const char *name=0); + ~SwapPrefs(); + + public slots: + void saveConfig(KSim::Config *); + void readConfig(KSim::Config *); + + private slots: + void swapContextMenu(QPopupMenu *); + void insertSwapItem(); + void removeSwapItem(); + + private: + QVBoxLayout *m_mainLayout; + QHBoxLayout *m_subLayout; + QVBoxLayout *m_boxLayout; + QCheckBox *m_swapCheck; + QLabel *m_swapFormat; + KComboBox *m_swapCombo; + QLabel *m_swapInfo; + QGroupBox *m_swapBox; + QLabel *m_stLabel; + QLabel *m_sfLabel; + QLabel *m_suLabel; + QPushButton *m_swapAdd; + QIconSet m_addIcon; + QIconSet m_removeIcon; + }; +} +#endif diff --git a/ksim/ksim.cpp b/ksim/ksim.cpp new file mode 100644 index 0000000..86ea980 --- /dev/null +++ b/ksim/ksim.cpp @@ -0,0 +1,129 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "ksim.h" +#include "ksimview.h" +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +extern "C" +{ + KDE_EXPORT KPanelExtension *init(QWidget *parent, const QString &configFile) + { + KGlobal::locale()->insertCatalogue("ksim"); + return new KSim::PanelExtension(configFile, KPanelExtension::Normal, + KPanelExtension::About | KPanelExtension::Help | + KPanelExtension::Preferences | KPanelExtension::ReportBug, + parent, "ksim"); + } +} + +KSim::PanelExtension::PanelExtension(const QString &configFile, + Type type, int actions, QWidget *parent, const char *name) + : KPanelExtension(configFile, type, actions, parent, name) +{ + m_dcopClient = new DCOPClient; + m_view = new KSim::MainView(config(), true, this, "m_view"); + m_view->positionChange(orientation()); + + m_dcopClient->registerAs(name, false); + + m_aboutData = new KAboutData(name, I18N_NOOP("KSim"), KSIM_VERSION_STRING, + I18N_NOOP("A plugin based system monitor for KDE"), + KAboutData::License_GPL, I18N_NOOP("(C) 2001-2003 Robbie Ward\n(C) 2005 Reuben Sutton")); + m_aboutData->addAuthor("Reuben Sutton", I18N_NOOP("Maintainer"),"reuben.sutton@gmail.com"); + m_aboutData->addAuthor("Robbie Ward", I18N_NOOP("Original Author"), + "linuxphreak@gmx.co.uk"); + m_aboutData->addAuthor("Jason Katz-Brown", I18N_NOOP("Developer"), + "jason@katzbrown.com"); + m_aboutData->addAuthor("Heitham Omar", I18N_NOOP("Some FreeBSD ports"), + "super_ice@ntlworld.com"); + m_aboutData->addAuthor("Otto Bruggeman", I18N_NOOP("Testing, Bug fixing and some help"), + "bruggie@home.nl"); +} + +KSim::PanelExtension::~PanelExtension() +{ + delete m_aboutData; + delete m_dcopClient; +} + +QSize KSim::PanelExtension::sizeHint(Position p, QSize maxSize) const +{ + return m_view->sizeHint(p, maxSize); +} + +void KSim::PanelExtension::resizeEvent(QResizeEvent *) +{ + m_view->resize(size()); +} + +KPanelExtension::Position KSim::PanelExtension::preferedPosition() const +{ + return KPanelExtension::Right; +} + +void KSim::PanelExtension::reparse() +{ + emit updateLayout(); +} + +void KSim::PanelExtension::show() +{ + KPanelExtension::show(); + + reparse(); +} + +void KSim::PanelExtension::about() +{ + KAboutApplication(m_aboutData).exec(); +} + +void KSim::PanelExtension::help() +{ +} + +void KSim::PanelExtension::preferences() +{ + m_view->preferences(); +} + +void KSim::PanelExtension::reportBug() +{ + KBugReport(this, true, m_aboutData).exec(); +} + +void KSim::PanelExtension::positionChange(Position) +{ + m_view->positionChange(orientation()); +} + +#include "ksim.moc" diff --git a/ksim/ksim.desktop b/ksim/ksim.desktop new file mode 100644 index 0000000..8f4934a --- /dev/null +++ b/ksim/ksim.desktop @@ -0,0 +1,134 @@ +[Desktop Entry] +GenericName=System Monitor +GenericName[af]=Stelsel Monitor +GenericName[ar]=مراقب النظام +GenericName[az]=Sistem İzləyici +GenericName[bg]=Мониторинг на системата +GenericName[br]=Diskwel saviad ar reizhiad +GenericName[bs]=Monitor sistema +GenericName[ca]=Monitor del sistema +GenericName[cs]=Monitor systému +GenericName[cy]=Monitr Cysawd +GenericName[da]=Systemovervågningsprogram +GenericName[de]=Systemüberwachung +GenericName[el]=Επόπτης συστήματος +GenericName[eo]=Sistemstato-programo +GenericName[es]=Monitor del sistema +GenericName[et]=Süsteemi monitor +GenericName[eu]=Sistemaren Begiralea +GenericName[fa]=نمایشگر سیستم +GenericName[fi]=Järjestelmänvalvontaohjelma +GenericName[fr]=Indicateurs du système +GenericName[ga]=Monatóir Córais +GenericName[gl]=Monitor do Sistema +GenericName[he]=צג מערכת +GenericName[hi]=तंत्र मॉनीटर +GenericName[hr]=Monitor sustava +GenericName[hu]=Rendszermonitor +GenericName[id]=Monitor Sistem +GenericName[is]=Kerfiseftirlit +GenericName[it]=Controllo di sistema +GenericName[ja]=システムモニタ +GenericName[ka]=სისტემური მონიტორი +GenericName[kk]=Жүйені қадағалау +GenericName[km]=កម្មវិធី​ត្រួតពិនិត្យ​ប្រព័ន្ធ +GenericName[ko]=X용 시스템 지켜보기 (Xosview) +GenericName[lt]=Sistemos stebėtojas +GenericName[lv]=Sistēmas Monitors +GenericName[mk]=Монитор на системот +GenericName[ms]=Pemerhati Sistem +GenericName[mt]=Monitur tas-sistema +GenericName[nb]=Systemovervåker +GenericName[nds]=Systeemkieker +GenericName[ne]=प्रणाली मोनिटर +GenericName[nl]=Systeemmonitor +GenericName[nn]=Systemovervakar +GenericName[nso]=Molebeledi wa System +GenericName[pa]=ਸਿਸਟਮ ਨਿਗਰਾਨ +GenericName[pl]=Monitor systemu +GenericName[pt]=Monitor do Sistema +GenericName[pt_BR]=Monitor de sistema +GenericName[ro]=Program de monitorizare a sistemului +GenericName[ru]=Системный монитор +GenericName[rw]=Mugaragaza Sisitemu +GenericName[sk]=Monitor systému +GenericName[sl]=Sistemski nadzornik +GenericName[sr]=Надгледање система +GenericName[sr@Latn]=Nadgledanje sistema +GenericName[sv]=Systemövervakare +GenericName[ta]=அமைப்பு கண்காணி +GenericName[tg]=Дидабони Системавӣ +GenericName[th]=สอดส่องการทำงานของระบบ +GenericName[tr]=Sistem İzleyici +GenericName[uk]=Монітор системи +GenericName[uz]=Tizimni nazorat qilish +GenericName[uz@cyrillic]=Тизимни назорат қилиш +GenericName[ven]=Mugadi wa Maitele +GenericName[vi]=Trình theo dõi hềEthống +GenericName[wa]=Corwaitoe do sistinme +GenericName[xh]=Umphendli Wendlela Esetyenziswayo +GenericName[zh_CN]=系统监视器 +GenericName[zh_TW]=系統監視器 +GenericName[zu]=Umlawuli Wesistimu +Comment=System Information Monitor (GKrellM style) +Comment[ar]=مراقب معلومات نظام K (أسلوب GKrellM) +Comment[bg]=Информация за състоянието на системата (стил GKrellM) +Comment[bs]=Nadzor sistemskih informacija (nalik na GKrellM) +Comment[ca]=Monitor d'informació del sistema (similar a GKrellM) +Comment[cs]=Monitor systémových informací (ve stulu programu GKrellM) +Comment[da]=Systeminformationsovervågning (GKrellM-lignende) +Comment[de]=System-Informationsüberwachung (GKrellM-Stil) +Comment[el]=Επόπτης πληροφοριών συστήματος (στο στυλ του GKrellM) +Comment[eo]=Monitoro por Sisteminformoj (GKrellM-stilo) +Comment[es]=Monitor de información del sistema (estilo GKrellM) +Comment[et]=Süsteemi monitooring (GKrellM stiil) +Comment[eu]=Sistemaren Informazioaren Begiralea (GKrellM estiloa) +Comment[fa]=نمایشگر اطلاعات سیستم (GKrellM سبک) +Comment[fi]=Järjestelmätietomonitori (GKrellM-tyylinen) +Comment[fr]=Indicateur d'informations système (dans le style de GKrellM) +Comment[ga]=Monatóir Eolais an Chórais (stíl GKrellM) +Comment[he]=צג מידע מערכת (נוסח GKrellM) +Comment[hu]=Rendszermonitor (GKrellM-stílusú) +Comment[is]=Kerfisupplýsingavaki (líkur GKrellM) +Comment[it]=Controllo delle informazioni di sistema (simile a GKrellM) +Comment[ja]=システム情報モニタ (GKrellM スタイル) +Comment[ka]= სისტემური ინფორმაციის მონიტორი (GKrellM style) +Comment[kk]=Жүені қадағалау ақпараты (GKrellM стилінде) +Comment[km]=កម្មវិធី​ត្រួតពិនិត្យ​ព័ត៌មាន​របស់​ប្រព័ន្ធ (GKrellM style) +Comment[lt]=Sistemos informacijos stebėtojas (GKrellM stilius) +Comment[nb]=Overvåkning av K systeminformasjon (GKrellM stil) +Comment[nds]=Kieker för Systeeminformatschonen (GKrellM-Stil) +Comment[ne]=प्रणाली सूचना मोनिटर (GKrellM शैली) +Comment[nl]=Systeeminformatiemonitor (gKrellM-stijl) +Comment[nn]=Systeminfovisar (GKrellM-stil) +Comment[pa]=ਸਿਸਟਮ ਜਾਣਕਾਰੀ ਨਿਗਰਾਨ (GKrellM ਸ਼ੈਲੀ) +Comment[pl]=Informacja o stanie systemu (w stylu GKrellM) +Comment[pt]=Monitor de Informações do Sistema (estilo GKrellM) +Comment[pt_BR]=Monitor de Informações do Sistema (estilo GKrellM) +Comment[ru]=Информационный монитор (в стиле GKrellM) +Comment[sk]=Monitor systémových informácií (v štýle GKrellM) +Comment[sl]=Nadzornik sistemskih informacij (v slogu GKrellM) +Comment[sr]=Надгледање системских информација (у стилу GKrellM-а) +Comment[sr@Latn]=Nadgledanje sistemskih informacija (u stilu GKrellM-a) +Comment[sv]=Systeminformationsövervakare (Gkrellm-stil) +Comment[tr]=Sistem Bildirimileri İzleyici (GKrellM stili) +Comment[uk]=Монітор системної інформації (в стилі GKrellM) +Comment[zh_CN]=系统信息监视器(GKrellM 风格) +Comment[zh_TW]=系統資訊監視器 (GKrellM 風格) +DocPath=ksim/index.html +Icon=ksim +MimeType= +Name=KSim +Name[af]=Ksim +Name[cy]=kSim +Name[eo]=Simulilo +Name[hi]=के-सिम +Name[ne]=केडीई सिम +Name[sv]=Ksim +Name[ta]=கேசிம் +Name[th]=สอดส่องระบบ +Name[zh_TW]=KSim 系統監視器 +X-KDE-Library=ksim_panelextension +X-KDE-UniqueApplet=true +Categories=Qt;KDE;System; +Hidden=false diff --git a/ksim/ksim.h b/ksim/ksim.h new file mode 100644 index 0000000..8a43a06 --- /dev/null +++ b/ksim/ksim.h @@ -0,0 +1,67 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef KSIMEXTENSION_H +#define KSIMEXTENSION_H + +#include + +class QBoxLayout; +class KAboutData; +class KInstance; +class DCOPClient; + +namespace KSim +{ + class MainView; + + class PanelExtension : public KPanelExtension + { + Q_OBJECT + public: + PanelExtension( const QString & configFile, Type type, + int actions, QWidget * parent, const char * name); + + ~PanelExtension(); + + QSize sizeHint( Position, QSize maxSize ) const; + void resizeEvent(QResizeEvent *); + Position preferedPosition() const; + + void reparse(); + + public slots: + void show(); + + protected: + void about(); + void help(); + void preferences(); + void reportBug(); + void positionChange( Position ); + + private: + KSim::MainView * m_view; + QBoxLayout * m_layout; + KAboutData * m_aboutData; + DCOPClient * m_dcopClient; + }; +} +#endif diff --git a/ksim/ksim_panelextensionrc b/ksim/ksim_panelextensionrc new file mode 100644 index 0000000..8986d4d --- /dev/null +++ b/ksim/ksim_panelextensionrc @@ -0,0 +1,81 @@ +[CpuPlugin] +Cpus=cpu 0 +DisplayNice=true +Cpu0_options=%T + +[DiskPlugin] +UseSeperatly=true +Disks=complete + +[Fsystem] +ShowPercentage=true +mountEntries=/ +scrollerUpdate=65 +stackItems=true +updateValue=60 + +[General] +Alignment=0 +AutoHideDelay=3 +AutoHidePanel=false +AutoHideSwitch=true +BackgroundHide=false +CustomSize=58 +ExpandSize=true +HideAnimation=true +HideAnimationSpeed=40 +HideButtonSize=14 +Position=1 +ResizeableHandle=false +ShowLeftHideButton=true +ShowRightHideButton=false +Size=2 +SizePercentage=1 +UnhideLocation=6 +XineramaScreen=0 + +[General Options] +Width=-1 + +[Misc] +MemoryFormat=Memory: %fM/%tM +MemoryItem=0 +ShowMemory=true +ShowSwap=true +ShowUptime=true +SwapFormat=Swap: %fM/%tM +SwapItem=0 +UptimeFormat=%hh:%mm:%ss,%dd %h:%m,Uptime: %h:%m:%s +UptimeItem=0 +GraphSize=58,40 +savePos=false +showDock=true +showDate=false +showTime=false + +[Monitors] +cpu=true +filesystem=true +disk=true +net=true + +[Net] +deviceAmount=1 + +[Sensors] +sensorLocations=/usr/lib/,/usr/local/lib/ + +[Theme] +Alternative=0 +FontItem=4 +Name=ksim + +[device-0] +cCommand= +commands=false +dCommand= +deviceFormat=%h:%m:%s +deviceName=eth0 +showGraph=true +showLabel=true +showTimer=false diff --git a/ksim/ksimframe.cpp b/ksim/ksimframe.cpp new file mode 100644 index 0000000..e69a6c6 --- /dev/null +++ b/ksim/ksimframe.cpp @@ -0,0 +1,94 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "ksimframe.h" +#include "ksimframe.moc" +#include +#include "ksim.h" +#include "themetypes.h" + +KSim::Frame::Frame(int type, QWidget *parent, const char *name) + : QWidget (parent, name) +{ + setType(type); + + setBackgroundMode(NoBackground); + configureObject(); +} + +KSim::Frame::~Frame() +{ +} + +void KSim::Frame::configureObject(bool repaintWidget) +{ + m_image.load(themeLoader().current().framePixmap(type())); + + switch (type()) { + case KSim::Types::TopFrame: + setFrameHeight(themeLoader().current().frameTopHeight()); + break; + case KSim::Types::BottomFrame: + setFrameHeight(themeLoader().current().frameBottomHeight()); + break; + case KSim::Types::LeftFrame: + setFrameWidth(themeLoader().current().frameLeftWidth()); + break; + case KSim::Types::RightFrame: + setFrameWidth(themeLoader().current().frameRightWidth()); + break; + } + + themeLoader().reColourImage(m_image); + m_background.convertFromImage(m_image.smoothScale(size())); + + if (repaintWidget) + update(); +} + +void KSim::Frame::paintEvent(QPaintEvent *) +{ + bitBlt(this, 0, 0, &m_background); +} + +void KSim::Frame::resizeEvent(QResizeEvent *ev) +{ + m_background.convertFromImage(m_image.smoothScale(ev->size())); + QWidget::resizeEvent(ev); +} + +void KSim::Frame::setFrameHeight(int height) +{ + if (!height) { + setFixedHeight(m_image.height()); + return; + } + + setFixedHeight(height); +} + +void KSim::Frame::setFrameWidth(int width) +{ + if (!width) { + setFixedWidth(m_image.width()); + return; + } + + setFixedWidth(width); +} diff --git a/ksim/ksimframe.h b/ksim/ksimframe.h new file mode 100644 index 0000000..b7b397f --- /dev/null +++ b/ksim/ksimframe.h @@ -0,0 +1,63 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIMFRAME_H +#define KSIMFRAME_H + +#include +#include +#include + +namespace KSim +{ + class PanelExtension; + + /** + * @internal + */ + class Frame : public QWidget, public KSim::Base + { + Q_OBJECT + public: + Frame(int type, QWidget *parent, const char *name = 0); + ~Frame(); + + const QPixmap *const background() const { return &m_background; } + virtual void configureObject(bool repaintWidget=true); + + protected: + virtual void paintEvent(QPaintEvent *); + virtual void resizeEvent(QResizeEvent *); + + private: + // helper functions to make + // the source more readable + void setFrameHeight(int height); + void setFrameWidth(int width); + + int m_origWidth; + int m_origHeight; + QPoint m_globalBottomRight; + QPoint m_globalTopLeft; + QPoint m_origPos; + QImage m_image; + QPixmap m_background; + }; +} +#endif diff --git a/ksim/ksimpref.cpp b/ksim/ksimpref.cpp new file mode 100644 index 0000000..d8aa12d --- /dev/null +++ b/ksim/ksimpref.cpp @@ -0,0 +1,260 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "ksimpref.h" +#include "ksimpref.moc" + +#include "generalprefs.h" +#include "monitorprefs.h" +#include "themeprefs.h" +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +KSim::ConfigDialog::ConfigDialog(KSim::Config *config, + QWidget *parent, const char *name) + : KDialogBase(TreeList, i18n("Configure"), + Help | Ok | Apply | Close, Ok, parent, name, true, true) +{ + resize(466, 363); + setShowIconsInTreeList(true); + setRootIsDecorated(false); + + m_config = config; + + setFolderIcon(QStringList(' ' + i18n("Plugins")), + BarIcon("folder", KIcon::SizeSmall)); + setFolderIcon(QStringList(' ' + i18n("Miscellaneous")), + BarIcon("misc", KIcon::SizeSmall)); + + QFrame *monitors = addHBoxPage(' ' + i18n("Monitors"), + i18n("Monitors Installed"), BarIcon("ksim", KIcon::SizeSmall)); + m_monPage = new KSim::MonitorPrefs(monitors); + + QStringList list; + list << ' ' + i18n("Miscellaneous") << ' ' + i18n("General"); + QFrame *general = addHBoxPage(list, i18n("General Options"), + SmallIcon("misc")); + m_generalPage = new KSim::GeneralPrefs(general); + list.clear(); + + list << ' ' + i18n("Miscellaneous") << ' ' + i18n("Clock"); + QFrame *clock = addHBoxPage(list, i18n("Clock Options"), + QPixmap(locate("data", "ksim/pics/clock.png"))); + m_clockPage = new KSim::ClockPrefs(clock); + list.clear(); + + list << ' ' + i18n("Miscellaneous") << ' ' + i18n("Uptime"); + QFrame *uptime = addHBoxPage(list, i18n("Uptime Options"), + QPixmap(locate("data", "ksim/pics/uptime.png"))); + m_uptimePage = new KSim::UptimePrefs(uptime); + list.clear(); + + list << ' ' + i18n("Miscellaneous") << ' ' + i18n("Memory"); + QFrame *memory = addHBoxPage(list, i18n("Memory Options"), + SmallIcon("memory")); + m_memoryPage = new KSim::MemoryPrefs(memory); + list.clear(); + + list << ' ' + i18n("Miscellaneous") << ' ' + i18n("Swap"); + QFrame *swap = addHBoxPage(list, i18n("Swap Options"), + SmallIcon("hdd_unmount")); + m_swapPage = new KSim::SwapPrefs(swap); + + QFrame *theme = addHBoxPage(' ' + i18n("Themes"), + i18n("Theme Selector"), BarIcon("folder_image", KIcon::SizeSmall)); + m_themePage = new KSim::ThemePrefs(theme); + + connect(this, SIGNAL(applyClicked()), SLOT(savePrefs())); + connect(this, SIGNAL(okClicked()), SLOT(closePrefs())); + connect(this, SIGNAL(closeClicked()), SLOT(loadPluginConfig())); + connect(parent, SIGNAL(reload()), SLOT(reload())); + + KSim::PluginList::ConstIterator it; + const KSim::PluginList &pluginList = KSim::PluginLoader::self().pluginList(); + for (it = pluginList.begin(); it != pluginList.end(); ++it) + createPage((*it)); + + readConfig(); +} + +KSim::ConfigDialog::~ConfigDialog() +{ + ChangedPluginList::ConstIterator it; + for (it = m_currentPlugins.begin(); it != m_currentPlugins.end(); ++it) { + if ((*it).isEnabled()) + removePage((*it).libName()); + } +} + +void KSim::ConfigDialog::reload() +{ + enableButtons(); +} + +void KSim::ConfigDialog::removePage(const QCString &name) +{ + const KSim::Plugin &plugin = KSim::PluginLoader::self().find(name); + if (plugin.isNull() || !plugin.configPage()) { + KMessageBox::sorry(0, i18n("Failed to remove %1's config page due to the " + "plugin not being loaded or the config page has not been created").arg(name)); + return; + } + + QWidget *frame = plugin.configPage()->parentWidget(); + // reparent the widget if the parent is not null + if (frame) { + plugin.configPage()->hide(); + plugin.configPage()->reparent(0, QPoint(0, 0), false); + // delete the frame so it removes the page from the config dialog + delete frame; + kdDebug(2003) << "removing " << name << " from KSimPref" << endl; + } +} + +void KSim::ConfigDialog::createPage(const QCString &name) +{ + const KSim::Plugin &plugin = KSim::PluginLoader::self().find(name); + createPage(plugin); +} + +void KSim::ConfigDialog::createPage(const KSim::Plugin &plugin) +{ + if (plugin.isNull() || !plugin.configPage()) { + KMessageBox::sorry(0, i18n("Failed to add %1's config page due to the plugin" + " not being loaded or the config page has not been created") + .arg(plugin.libName())); + return; + } + + kdDebug(2003) << "adding " << plugin.libName() << " to KSimPref" << endl; + + QStringList list; + list << ' ' + i18n("Plugins") << ' ' + plugin.name(); + QFrame *pluginFrame = addHBoxPage(list, i18n("%1 Options").arg(plugin.name()), + plugin.icon()); + + plugin.configPage()->reparent(pluginFrame, QPoint(0, 0), true); + plugin.configPage()->readConfig(); + +// TODO: implement this correctly one day +// connect (info.configPage(), SIGNAL(pageChanged()), +// this, SLOT(enableButtons())); +} + +void KSim::ConfigDialog::savePrefs() +{ + saveConfig(true); +} + +void KSim::ConfigDialog::saveConfig(bool reload) +{ + disableButtons(); + + m_monPage->saveConfig(m_config); + m_generalPage->saveConfig(m_config); + m_clockPage->saveConfig(m_config); + m_uptimePage->saveConfig(m_config); + m_memoryPage->saveConfig(m_config); + m_swapPage->saveConfig(m_config); + m_themePage->saveConfig(m_config); + + ChangedPluginList changedPlugins; + for (QListViewItemIterator it(m_monPage); it.current(); ++it) { + QCheckListItem *item = static_cast(it.current()); + KSim::PluginInfo info = KSim::PluginLoader::self().findPluginInfo(item->text(0), + KSim::PluginLoader::Name); + changedPlugins.append(ChangedPlugin(item->isOn(), + info.libName(true), item->text(0), info.location(), + findPlugin(item->text(0)).isEnabled())); + + KSim::PluginLoader::self().find(info).setEnabled(item->isOn()); + } + + m_currentPlugins = changedPlugins; + emit reparse(reload, changedPlugins); +} + +void KSim::ConfigDialog::readConfig() +{ + m_monPage->readConfig(m_config); + m_generalPage->readConfig(m_config); + m_clockPage->readConfig(m_config); + m_uptimePage->readConfig(m_config); + m_memoryPage->readConfig(m_config); + m_swapPage->readConfig(m_config); + m_themePage->readConfig(m_config); + + m_currentPlugins.clear(); + for (QListViewItemIterator it(m_monPage); it.current(); ++it) { + QCheckListItem *item = static_cast(it.current()); + KSim::PluginInfo info = KSim::PluginLoader::self().findPluginInfo(item->text(0), + KSim::PluginLoader::Name); + m_currentPlugins.append(ChangedPlugin(item->isOn(), + info.libName(true), item->text(0), info.location())); + } +} + +void KSim::ConfigDialog::closePrefs() +{ + saveConfig(false); + close(); +} + +void KSim::ConfigDialog::loadPluginConfig() +{ + const KSim::PluginList &list = KSim::PluginLoader::self().pluginList(); + KSim::PluginList::ConstIterator it; + for (it = list.begin(); it != list.end(); ++it) { + if ((*it).configPage()) + (*it).configPage()->readConfig(); + } +} + +void KSim::ConfigDialog::enableButtons() +{ + enableButtonApply(true); + enableButtonOK(true); +} + +void KSim::ConfigDialog::disableButtons() +{ + enableButtonApply(false); + enableButtonOK(false); +} + +const KSim::ChangedPlugin &KSim::ConfigDialog::findPlugin(const QString &name) const +{ + ChangedPluginList::ConstIterator it; + for (it = m_currentPlugins.begin(); it != m_currentPlugins.end(); ++it) { + if ((*it).name() == name) + return (*it); + } + + return *m_currentPlugins.end(); +} diff --git a/ksim/ksimpref.h b/ksim/ksimpref.h new file mode 100644 index 0000000..8e560a8 --- /dev/null +++ b/ksim/ksimpref.h @@ -0,0 +1,112 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIMPREF_H +#define KSIMPREF_H + +#include +#include + +class QFrame; +class KDesktopFile; +namespace KSim +{ + class Config; + class Plugin; + class MonitorPrefs; + class GeneralPrefs; + class ClockPrefs; + class UptimePrefs; + class MemoryPrefs; + class SwapPrefs; + class ThemePrefs; + + class ChangedPlugin + { + public: + ChangedPlugin() : m_name(0) {} + ChangedPlugin(bool enabled, const QCString &libname, + const QString &name, const QString &file) : m_enabled(enabled), + m_libname(libname), m_name(name), m_file(file) {} + ChangedPlugin(bool enabled, const QCString &libname, + const QString &name, const QString &file, bool oldState) + : m_enabled(enabled), m_libname(libname), m_name(name), + m_file(file), m_oldState(oldState) {} + + bool isEnabled() const { return m_enabled; } + bool isDifferent() const { return m_enabled != m_oldState; } + const QCString &libName() const { return m_libname; } + const QString &name() const { return m_name; } + const QString &filename() const { return m_file; } + + private: + bool m_enabled; + QCString m_libname; + QString m_name; + QString m_file; + bool m_oldState; + }; + + class ChangedPluginList : public QValueList + { + public: + ChangedPluginList() {} + ~ChangedPluginList() {} + }; + + class KDE_EXPORT ConfigDialog : public KDialogBase + { + Q_OBJECT + public: + ConfigDialog(KSim::Config *config, QWidget *parent, const char *name = 0); + ~ConfigDialog(); + + public slots: + void removePage(const QCString &name); + void createPage(const QCString &name); // overload + void createPage(const KSim::Plugin &plugin); + + signals: + void reparse(bool, const KSim::ChangedPluginList &); + + private slots: + void reload(); + void savePrefs(); + void saveConfig(bool); + void readConfig(); + void closePrefs(); + void loadPluginConfig(); + void enableButtons(); + void disableButtons(); + + private: + const KSim::ChangedPlugin &findPlugin(const QString &name) const; + + ChangedPluginList m_currentPlugins; + KSim::MonitorPrefs *m_monPage; + KSim::GeneralPrefs *m_generalPage; + KSim::ClockPrefs *m_clockPage; + KSim::UptimePrefs *m_uptimePage; + KSim::MemoryPrefs *m_memoryPage; + KSim::SwapPrefs *m_swapPage; + KSim::ThemePrefs *m_themePage; + KSim::Config *m_config; + }; +} +#endif diff --git a/ksim/ksimsysinfo.cpp b/ksim/ksimsysinfo.cpp new file mode 100644 index 0000000..724adb6 --- /dev/null +++ b/ksim/ksimsysinfo.cpp @@ -0,0 +1,325 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ksimsysinfo.h" +#include "ksimsysinfo.moc" +#include "systeminfo.h" +#include +#include +#include +#include + +#include +#include + +KSim::Sysinfo::Sysinfo(KSim::Config *config, + QWidget *parent, const char *name, WFlags fl) + : DCOPObject("sysinfo"), QWidget(parent, name, fl) +{ + m_config = config; + m_layout = new QVBoxLayout(this); + + m_timeLabel = 0L; + m_dateLabel = 0L; + m_uptimeLabel = 0L; + m_memLabel = 0L; + m_swapLabel = 0L; + //m_procsLabel = 0L; + + m_timer = new QTimer(this); + connect(m_timer, SIGNAL(timeout()), SLOT(clockUptimeUpdate())); + + m_sysTimer = new QTimer(this); + connect(m_sysTimer, SIGNAL(timeout()), SLOT(sysUpdate())); + + createView(); +} + +KSim::Sysinfo::~Sysinfo() +{ + // remember to cleanup + System::cleanup(); +} + +void KSim::Sysinfo::clockUptimeUpdate() +{ + QString time; + static bool updateDate = true; + + if (m_timeLabel) { + QTime now = QTime::currentTime(); + time = KGlobal::locale()->formatTime(now, true); + if ( now == QTime(0, 0) ) + updateDate = true; + + m_timeLabel->setText(time); + } + + // only update the date when necessary + if (m_dateLabel) { + if (updateDate) { + m_dateLabel->setText(KGlobal::locale()->formatDate(QDate::currentDate())); + updateDate = false; + } + } + else { + updateDate = true; + } + + if (m_uptimeLabel) { + QString uptime = m_config->uptimeFormat(); + ++m_totalUptime; + long uptimeDays, uptimeHours, uptimeMins, uptimeSecs; + + uptimeHours = m_totalUptime / 3600; + uptimeDays = uptimeHours / 24; + uptimeMins = (m_totalUptime - uptimeHours * 3600) / 60; + uptimeSecs = m_totalUptime % 60; + + QString days; + QString hours; + QString minutes; + QString seconds; + + // found days so we have to modify hours + if (uptime.find(QRegExp("%d" ), 0) >= 0) + uptimeHours -= (uptimeDays * 24); + + days.sprintf("%02li", uptimeDays); + hours.sprintf("%02li", uptimeHours); + minutes.sprintf("%02li", uptimeMins); + seconds.sprintf("%02li", uptimeSecs); + + uptime.replace(QRegExp("%d"), days); + uptime.replace(QRegExp("%h"), hours); + uptime.replace(QRegExp("%m"), minutes); + uptime.replace(QRegExp("%s"), seconds); + m_uptimeLabel->setText(uptime); + } +} + +void KSim::Sysinfo::sysUpdate() +{ + const System &system = System::self(); + m_totalUptime = system.uptime(); + + if (m_memLabel) { + QString memory = m_config->memoryFormat(); + unsigned long total = system.totalRam(); + unsigned long free = system.freeRam(); + unsigned long shared = system.sharedRam(); + unsigned long buffer = system.bufferRam(); + unsigned long cache = system.cacheRam(); + unsigned long used = system.usedRam(); + unsigned long allFree = free + buffer + cache; + bool all = memory.find( "%F" ) != -1; + + memory.replace(QRegExp("%s"), QString::number(System::bytesToMegs(shared))); + memory.replace(QRegExp("%b"), QString::number(System::bytesToMegs(buffer))); + memory.replace(QRegExp("%c"), QString::number(System::bytesToMegs(cache))); + memory.replace(QRegExp("%u"), QString::number(System::bytesToMegs(used))); + memory.replace(QRegExp("%t"), QString::number(System::bytesToMegs(total))); + memory.replace(QRegExp("%f"), QString::number(System::bytesToMegs(free))); + memory.replace(QRegExp("%F"), QString::number(System::bytesToMegs(allFree))); + kdDebug(2003) << memory << endl; + m_memLabel->setText("Memory"); + QToolTip::add(m_memLabel, memory ); + + if ( !all ) + m_memLabel->setValue( System::bytesToMegs( total ) - System::bytesToMegs( free ) ); + else + m_memLabel->setValue( System::bytesToMegs( total ) - System::bytesToMegs( allFree ) ); + } + + if (m_swapLabel) { + QString swap = m_config->swapFormat(); + unsigned long total = system.totalSwap(); + unsigned long free = system.freeSwap(); + unsigned long swapUsed = system.usedSwap(); + swap.replace(QRegExp("%u"), QString::number(System::bytesToMegs(swapUsed))); + swap.replace(QRegExp("%t"), QString::number(System::bytesToMegs(total))); + swap.replace(QRegExp("%f"), QString::number(System::bytesToMegs(free))); + m_swapLabel->setText("Swap"); + QToolTip::add(m_swapLabel, swap); + m_swapLabel->setValue(System::bytesToMegs(total) - System::bytesToMegs(free)); + } + +// if (m_config->showProcs()) { +// m_procsLabel->setText(i18n("Procs: %1").arg(sysInfo.procs)); +// } +} + +void KSim::Sysinfo::createView() +{ + stopTimers(); + const System &system = System::self(); + int timeLocation = 0; + int dateLocation = 1; + int uptimeLocation = 2; + int memLocation = 3; + int swapLocation = 4; + // int procsLocation = 5; + int offset = 0; + + if (m_config->showTime()) { + if (!m_timeLabel) { + m_timeLabel = new KSim::Label(this); + m_layout->insertWidget(timeLocation - offset, m_timeLabel); + } + QToolTip::add(m_timeLabel, i18n("Current system time")); + m_timeLabel->show(); + } + else { + offset++; + delete m_timeLabel; + m_timeLabel = 0L; + } + + if (m_config->showDate()) { + if (!m_dateLabel) { + m_dateLabel = new KSim::Label(this); + m_layout->insertWidget(dateLocation - offset, m_dateLabel); + } + QToolTip::add(m_dateLabel, i18n("Current system date")); + m_dateLabel->show(); + } + else { + offset++; + delete m_dateLabel; + m_dateLabel = 0L; + } + + kdDebug(2003) << m_dateLabel << endl; + + if (m_config->showUptime()) { + if (!m_uptimeLabel) { + m_uptimeLabel = new KSim::Label(KSim::Types::Uptime, this); + m_layout->insertWidget(uptimeLocation - offset, m_uptimeLabel); + } + QToolTip::add(m_uptimeLabel, i18n("System uptime")); + m_uptimeLabel->show(); + } + else { + offset++; + delete m_uptimeLabel; + m_uptimeLabel = 0L; + } + + if (m_config->showMemory()) { + if (!m_memLabel) { + m_memLabel = new KSim::Progress(System::bytesToMegs(system.totalRam()), + KSim::Types::Mem, this); + m_layout->insertWidget(memLocation - offset, m_memLabel); + } + + m_memLabel->show(); + } + else { + offset++; + delete m_memLabel; + m_memLabel = 0L; + } + + if (m_config->showSwap()) { + if (!m_swapLabel) { + m_swapLabel = new KSim::Progress(System::bytesToMegs(system.totalSwap()), + KSim::Types::Swap, this); + m_layout->insertWidget(swapLocation - offset, m_swapLabel); + } + m_swapLabel->show(); + } + else { + offset++; + delete m_swapLabel; + m_swapLabel = 0L; + } + + /*if (m_config->showProcs()) { + if (!m_procsLabel) { + m_procsLabel = new KSimLabel(this); + m_layout->insertWidget(procsLocation, m_procsLabel); + } + m_procsLabel->show(); + } + else { + delete m_procsLabel; + m_procsLabel = 0L; + }*/ + +// m_layout->invalidate(); + updateGeometry(); + adjustSize(); + + startTimers(); + sysUpdate(); + clockUptimeUpdate(); +} + +void KSim::Sysinfo::stopTimers() +{ + m_timer->stop(); + m_sysTimer->stop(); +} + +void KSim::Sysinfo::startTimers() +{ + // Cellecting meminfo on fbsd seems to be expensive :( + // so better update the memory display every 5 seconds rather than 1 + // until i can find a better solution (if there is one) + if (!m_sysTimer->isActive() && !m_timer->isActive()) { + m_sysTimer->start(5000); + m_timer->start(1000); + } +} + +QString KSim::Sysinfo::uptime() const +{ + if (m_uptimeLabel) + return m_uptimeLabel->text(); + + return i18n("Uptime display disabled"); +} + +QString KSim::Sysinfo::memInfo() const +{ + if (m_memLabel) + return m_memLabel->text(); + + return i18n("Memory display disabled"); +} + +QString KSim::Sysinfo::swapInfo() const +{ + if (m_swapLabel) + return m_swapLabel->text(); + + return i18n("Swap display disabled"); +} diff --git a/ksim/ksimsysinfo.h b/ksim/ksimsysinfo.h new file mode 100644 index 0000000..5c80d37 --- /dev/null +++ b/ksim/ksimsysinfo.h @@ -0,0 +1,70 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SYSINFO_H +#define SYSINFO_H + +#include +#include + +class QTimer; +class QVBoxLayout; +namespace KSim +{ + class Config; + class Label; + class Progress; + + class Sysinfo : public QWidget, virtual public DCOPObject + { + Q_OBJECT + K_DCOP + public: + Sysinfo(KSim::Config *config, QWidget *parent=0, + const char *name=0, WFlags fl=0); + ~Sysinfo(); + + k_dcop: + QString uptime() const; + QString memInfo() const; + QString swapInfo() const; + + public slots: + void clockUptimeUpdate(); + void sysUpdate(); + void createView(); + void stopTimers(); + void startTimers(); + + + private: + KSim::Label *m_timeLabel; + KSim::Label *m_dateLabel; + KSim::Label *m_uptimeLabel; + KSim::Progress *m_memLabel; + KSim::Progress *m_swapLabel; + //KSimLabel *m_procsLabel; + QVBoxLayout *m_layout; + QTimer *m_timer; + QTimer *m_sysTimer; + KSim::Config *m_config; + long m_totalUptime; + }; +} +#endif diff --git a/ksim/ksimview.cpp b/ksim/ksimview.cpp new file mode 100644 index 0000000..6f71b66 --- /dev/null +++ b/ksim/ksimview.cpp @@ -0,0 +1,467 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "ksimview.h" +#include "ksimview.moc" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "ksimsysinfo.h" +#include "ksim.h" +#include "ksimframe.h" +#include +#include +#include +#include +#include +#include +#include "ksimpref.h" +#include "baselist.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +KSim::MainView::MainView(KConfig *config, + bool loadPlugins, KSim::PanelExtension *topLevel, + const char *name) : DCOPObject("KSim"), + QWidget(topLevel, name) +{ + // create the local "themes" and "monitors" dirs + makeDirs(); + + setBackgroundMode(PaletteBackground); + + m_topLevel = topLevel; + m_oldLocation = 1; + m_prefDialog = 0L; + + m_config = new KSim::Config(config); + + // Make sure the current theme is valid + // if not then revert to the default theme + KSim::ThemeLoader::self().validate(); + + // parse the current theme in case it doesn't have the correct dir structure + if (KSim::ThemeLoader::currentName() != "ksim") + KSim::ThemeLoader::self().parseDir(KSim::ThemeLoader::currentUrl(), + KSim::ThemeLoader::currentAlternative()); + + kdDebug(2003) << "loadPlugins: " << loadPlugins << endl; + + m_subLayout = new QVBoxLayout(this); + + m_topFrame = new KSim::Frame(KSim::Types::TopFrame, this); + m_subLayout->addWidget(m_topFrame); + + m_sizeLayout = new QHBoxLayout; + m_subLayout->addLayout(m_sizeLayout); + + m_leftFrame = new KSim::Frame(KSim::Types::LeftFrame, this); + m_sizeLayout->addWidget(m_leftFrame); + + m_pluginLayout = new QBoxLayout(QBoxLayout::TopToBottom); + m_sizeLayout->addLayout(m_pluginLayout); + + QVBoxLayout *vb = new QVBoxLayout; + QSpacerItem *item = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding); + vb->addItem(item); + + m_hostLabel = new KSim::Label(KSim::Types::Host, this); + m_hostLabel->installEventFilter(this); + vb->addWidget(m_hostLabel); + + m_pluginLayout->addLayout(vb); + + char hostName[MAXHOSTNAMELEN]; + if (gethostname(hostName, sizeof(hostName))) + m_hostLabel->setText(i18n("Unknown")); + else { + QCString host(hostName); + int dotLocation = host.find("."); + if (!m_config->displayFqdn() && dotLocation != -1) + host.truncate(dotLocation); + + m_hostLabel->setText(host); + } + + vb = new QVBoxLayout; + item = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding); + vb->addItem(item); + m_sysinfo = new KSim::Sysinfo(m_config, this); + vb->addWidget(m_sysinfo); + m_pluginLayout->addLayout(vb); + + m_bottomFrame = new KSim::Frame(KSim::Types::BottomFrame, this); + m_subLayout->addWidget(m_bottomFrame); + + m_rightFrame = new KSim::Frame(KSim::Types::RightFrame, this); + m_sizeLayout->addWidget(m_rightFrame); + + connect(&KSim::PluginLoader::self(), + SIGNAL(pluginLoaded(const KSim::Plugin &)), + this, SLOT(addMonitor(const KSim::Plugin &))); + + KSim::ThemeLoader::self().themeColours(this); + + // load the plugins and create the plugin menu + if (loadPlugins) { + addPlugins(); + } + + connect(&m_maskTimer, SIGNAL(timeout()), SLOT(slotMaskMainView())); +} + +KSim::MainView::~MainView() +{ + delete m_config; +} + +void KSim::MainView::show() +{ + maskMainView(); + QWidget::show(); +} + +void KSim::MainView::cleanup() +{ + // delete our configuration dialog and remove + // the plugin config pages from the configuration + // dialog before we unload our plugins + delete m_prefDialog; + + // Clean up the singleton instances + KSim::PluginLoader::cleanup(); +} + +KSim::Config *KSim::MainView::config() const +{ + return m_config; +} + +void KSim::MainView::makeDirs() +{ + QString homeDir = locateLocal("data", "ksim"); + QString themeDir = homeDir + QString::fromLatin1("/themes"); + QString monitorDir = homeDir + QString::fromLatin1("/monitors"); + + // return true if the dirs already exist + if (QFile::exists(themeDir) && QFile::exists(monitorDir)) + return; + + bool themeCreated = KStandardDirs::makeDir(themeDir); + bool monitorCreated = KStandardDirs::makeDir(monitorDir); + + if (!themeCreated || !monitorCreated) + { + KMessageBox::sorry(0, i18n("There was an error while trying to create " + "the local folders. This could be caused by permission problems.")); + } +} + +const QString &KSim::MainView::hostname() const +{ + return m_hostLabel->text(); +} + +void KSim::MainView::slotMaskMainView() +{ + maskMainView(); +} + +void KSim::MainView::maskMainView() +{ + if (!m_topFrame->background()->mask() || + !m_leftFrame->background()->mask() || + !m_rightFrame->background()->mask() || + !m_bottomFrame->background()->mask()) + { + topLevelWidget()->clearMask(); + return; + } + + QBitmap topPixmap(*m_topFrame->background()->mask()); + QBitmap leftPixmap(*m_leftFrame->background()->mask()); + QBitmap rightPixmap(*m_rightFrame->background()->mask()); + QBitmap bottomPixmap(*m_bottomFrame->background()->mask()); + + QSize insideSize(m_pluginLayout->geometry().size()); + + // make a cleared bigrect where we can put our pixmap masks on + QBitmap bigBitmap(topLevelWidget()->size(), true); + + // better return if our bitmap is null so we can avoid crashes + if (bigBitmap.isNull()) + return; + + QPoint ofs = mapTo(topLevelWidget(), QPoint(0,0)); + int ofsX = ofs.x(); + int ofsY = ofs.y(); + + QPainter painter; + painter.begin(&bigBitmap); + painter.setBrush(color1); + painter.setPen(color1); + QRect rect = m_pluginLayout->geometry(); + rect.moveBy(ofsX, ofsY); + painter.drawRect(rect); + painter.drawPixmap(ofsX, ofsY, topPixmap); + painter.drawPixmap(ofsX, topPixmap.height()+ofsY, leftPixmap); + painter.drawPixmap(ofsX+insideSize.width() + leftPixmap.width(), + ofsY+ topPixmap.height(), rightPixmap); + painter.drawPixmap(ofsX, ofsY + height() - bottomPixmap.height(), + bottomPixmap); + + painter.end(); + topLevelWidget()->setMask(bigBitmap); +} + +void KSim::MainView::reparseConfig(bool emitReload, + const KSim::ChangedPluginList &list) +{ + kdDebug(2003) << "creating a new view" << endl; + + // Update the theme information for the theme classes + bool themeChanged = KSim::ThemeLoader::self().isDifferent(); + if (themeChanged) + KSim::ThemeLoader::self().reload(); + + const KSim::PluginList &pluginList = KSim::PluginLoader::self().pluginList(); + KSim::PluginList::ConstIterator plugin; + for (plugin = pluginList.begin(); plugin != pluginList.end(); ++plugin) { + if ((*plugin).configPage()) { + (*plugin).configPage()->saveConfig(); + KConfig *conf = (*plugin).configPage()->config(); + if (conf) conf->sync(); + } + + if (!(*plugin).isDifferent() && (*plugin).isEnabled()) { + kdDebug(2003) << "Recreating " << (*plugin).name() << "'s view" << endl; + kapp->processEvents(); + // Make sure the plugins background color is + // set to the correct theme color + if (themeChanged && (*plugin).view()) + KSim::ThemeLoader::self().themeColours((*plugin).view()); + + // Reload the config file and and recreate the plugins view + if ((*plugin).configPage() && (*plugin).configPage()->config()) + (*plugin).configPage()->config()->reparseConfiguration(); + + if ((*plugin).view()) { + (*plugin).view()->config()->reparseConfiguration(); + (*plugin).view()->reparseConfig(); + } + } + } + + ChangedPluginList::ConstIterator it; + for (it = list.begin(); it != list.end(); ++it) { + if ((*it).isDifferent()) { + if ((*it).isEnabled()) { // Go through the added/removed plugins and load/unload them + const KDesktopFile kdf((*it).filename()); + addPlugin(kdf); + m_prefDialog->createPage((*it).libName()); + } + else { + m_prefDialog->removePage((*it).libName()); + const KDesktopFile kdf((*it).filename()); + removePlugin(kdf); + } + } + } + + // reparse various non-plugin specific code + // recreate the plugin menu and the dock icon + KSim::BaseList::configureObjects(themeChanged); + if (themeChanged) + KSim::ThemeLoader::self().themeColours(this); + + m_sysinfo->createView(); + maskMainView(); + + m_topLevel->reparse(); + + if (emitReload) + emit reload(); + + kdDebug(2003) << "new view created" << endl; +} + +void KSim::MainView::addPlugins() +{ + QStringList locatedFiles = KGlobal::dirs()->findAllResources("data", "ksim/monitors/*.desktop"); + QStringList::ConstIterator it; + for (it = locatedFiles.begin(); it != locatedFiles.end(); ++it) + { + const KDesktopFile kdf(*it, true); + addPlugin(kdf); + } +} + +void KSim::MainView::addPlugin(const KDesktopFile &file, bool force) +{ + if (force || m_config->enabledMonitor(file.readEntry("X-KSIM-LIBRARY"))) + KSim::PluginLoader::self().loadPlugin(file); +} + +// provided for convenience +void KSim::MainView::removePlugin(const KDesktopFile &file) +{ + KSim::PluginLoader::self().unloadPlugin(file.readEntry("X-KSIM-LIBRARY").local8Bit()); +} + +void KSim::MainView::addMonitor(const KSim::Plugin &plugin) +{ + if (!plugin.view()) + return; + + plugin.view()->reparent(this, 0, QPoint(0, 0), true); + KSim::ThemeLoader::self().themeColours(plugin.view()); + +// int location = m_config->monitorLocation(plugin.libName()); +// if (location == -1) +// location = m_oldLocation + 1; +// else { +// location += 1; +// if (location > m_oldLocation) +// location = m_oldLocation + 1; +// } + +// kdDebug(2003) << "m_oldLocation: " << m_oldLocation << endl; +// kdDebug(2003) << "location: " << location << endl; + m_pluginLayout->addWidget(plugin.view()); + connect(plugin.view(), SIGNAL(runCommand(const QCString &)), + SLOT(runCommand(const QCString &))); + +// if (location > m_oldLocation) +// m_oldLocation = location; +} + +void KSim::MainView::runCommand(const QCString &name) +{ + if (name.isNull()) + return; + + kdDebug(2003) << "runCommand(" << name.mid(5) << ")" << endl; + QString exec = m_config->monitorCommand(name.mid(5)); + kdDebug(2003) << "exec is " << exec << endl; + KRun::runCommand(exec); +} + +void KSim::MainView::preferences() +{ + if (m_prefDialog == 0L) { + m_prefDialog = new KSim::ConfigDialog(m_config, this, "m_prefDialog"); + connect(m_prefDialog, SIGNAL(reparse(bool, const KSim::ChangedPluginList &)), + this, SLOT(reparseConfig(bool, const KSim::ChangedPluginList &))); + } + + m_prefDialog->exec(); + destroyPref(); +} + +void KSim::MainView::resizeEvent(QResizeEvent *re) +{ + QWidget::resizeEvent(re); + m_maskTimer.start(0, true); +} + +void KSim::MainView::paletteChange(const QPalette &) +{ + // Call true here to fool the KSim::Base pointers to + // think our theme changed, we can afford todo this + // since the palette doesn't change often. + KSim::BaseList::configureObjects(true); + + // Probably find a better way to do this + KSim::PluginList::ConstIterator it; + const KSim::PluginList &pluginList = KSim::PluginLoader::self().pluginList(); + for (it = pluginList.begin(); it != pluginList.end(); ++it) + KSim::ThemeLoader::self().themeColours((*it).view()); +} + +void KSim::MainView::destroyPref() +{ + if (m_prefDialog != 0L) { + kdDebug(2003) << "deleting KSimPref" << endl; + delete m_prefDialog; + m_prefDialog = 0L; + } +} + +QSize KSim::MainView::sizeHint(KPanelExtension::Position p, QSize) const +{ + int width = 0; + int height = 0; + + QLayoutItem *child; + for( QLayoutIterator it = m_pluginLayout->iterator(); + (child = it.current()) != 0; ++it) + { + QSize sz = child->minimumSize(); + if ((p == KPanelExtension::Right) || (p == KPanelExtension::Left)) + { + width = QMAX(width, sz.width()); + height += sz.height(); + } + else + { + width += sz.width(); + height = QMAX(height, sz.height()); + } + } + + width += m_leftFrame->minimumWidth() + m_rightFrame->minimumWidth(); + height += m_topFrame->minimumHeight() + m_bottomFrame->minimumHeight(); + + return QSize(width, height); +} + +void KSim::MainView::positionChange(KPanelExtension::Orientation o) +{ + if (o == KPanelExtension::Vertical) + m_pluginLayout->setDirection(QBoxLayout::TopToBottom); + else + m_pluginLayout->setDirection(QBoxLayout::LeftToRight); +} diff --git a/ksim/ksimview.h b/ksim/ksimview.h new file mode 100644 index 0000000..4bf7f1f --- /dev/null +++ b/ksim/ksimview.h @@ -0,0 +1,112 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIMVIEW_H +#define KSIMVIEW_H + +#include +#include + +#include + +#include +#include + +class QBoxLayout; +class QHBoxLayout; +class QVBoxLayout; +class QPopupMenu; +class KDesktopFile; +class KConfig; + +namespace KSim +{ + class Sysinfo; + class Config; + class Plugin; + class Label; + class Frame; + class PanelExtension; + class ConfigDialog; + class ChangedPluginList; + + class KDE_EXPORT MainView : public QWidget, virtual public DCOPObject + { + Q_OBJECT + K_DCOP + public: + MainView(KConfig *config, bool loadPlugins, + KSim::PanelExtension *topLevel, + const char *name); + + ~MainView(); + + virtual void show(); + + KSim::Config *config() const; + void makeDirs(); + + QSize sizeHint(KPanelExtension::Position, QSize maxSize) const; + void positionChange(KPanelExtension::Orientation); + + k_dcop: + const QString &hostname() const; + virtual void maskMainView(); + + signals: + void reload(); + + public slots: + void reparseConfig(bool, const KSim::ChangedPluginList &); + void addPlugins(); + void addPlugin(const KDesktopFile &, bool force = false); + void removePlugin(const KDesktopFile &); + void addMonitor(const KSim::Plugin &); + void runCommand(const QCString &); + void preferences(); + void slotMaskMainView(); + + protected: + virtual void resizeEvent(QResizeEvent *); + virtual void paletteChange(const QPalette &); + + private slots: + void destroyPref(); + + private: + void cleanup(); + + KSim::Sysinfo *m_sysinfo; + KSim::Label *m_hostLabel; + KSim::Frame *m_leftFrame; + KSim::Frame *m_rightFrame; + KSim::Frame *m_topFrame; + KSim::Frame *m_bottomFrame; + KSim::PanelExtension *m_topLevel; + KSim::Config *m_config; + KSim::ConfigDialog *m_prefDialog; + QHBoxLayout *m_sizeLayout; + QVBoxLayout *m_subLayout; + QBoxLayout *m_pluginLayout; + QPoint m_mousePoint; + int m_oldLocation; + QTimer m_maskTimer; + }; +} +#endif // KSIMVIEW_H diff --git a/ksim/library/Makefile.am b/ksim/library/Makefile.am new file mode 100644 index 0000000..f3b834f --- /dev/null +++ b/ksim/library/Makefile.am @@ -0,0 +1,25 @@ +lib_LTLIBRARIES = libksimcore.la + +libksimcore_la_SOURCES = common.cpp themeloader.cpp \ + chart.cpp label.cpp \ + led.cpp progress.cpp \ + pluginglobal.cpp pluginloader.cpp \ + pluginmodule.cpp ksimconfig.cpp + +libksimcore_la_LDFLAGS = $(all_libraries) -version-info 1:0 -no-undefined +libksimcore_la_LIBADD = $(LIB_KDEUI) + +ksiminclude_HEADERS = common.h themeloader.h \ + chart.h label.h \ + led.h progress.h \ + pluginglobal.h pluginloader.h \ + pluginmodule.h themetypes.h \ + ksimconfig.h + + +ksimincludedir = $(includedir)/ksim + +INCLUDES= $(all_includes) + +METASOURCES = AUTO + diff --git a/ksim/library/chart.cpp b/ksim/library/chart.cpp new file mode 100644 index 0000000..38f0f17 --- /dev/null +++ b/ksim/library/chart.cpp @@ -0,0 +1,627 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "chart.h" +#include "chart.moc" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include "themetypes.h" + +class KSim::Chart::Timer +{ + public: + static void syncChart(KSim::Chart *chart) + { + if (!m_timer) { + m_timer = new QTimer; + m_timer->start(1000); + qAddPostRoutine(cleanup); + } + + QObject::connect(m_timer, SIGNAL(timeout()), + chart, SLOT(updateDisplay())); + } + + static void disconnect(KSim::Chart *chart) + { + if (!m_timer) + return; + + QObject::disconnect(m_timer, SIGNAL(timeout()), + chart, SLOT(updateDisplay())); + } + + private: + static void cleanup() + { + if (!m_timer) + return; + + delete m_timer; + m_timer = 0; + } + + static QTimer *m_timer; +}; + +QTimer *KSim::Chart::Timer::m_timer = 0; + +class KSim::Chart::Private +{ + public: + typedef QPair ValuePair; + + QSize size; + int type; + bool showShadow; + bool showKrell; + QString inText; + QString outText; + QString title; + QPixmap chartPixmap; + QPixmap gridPixmap; + QPixmap graphData; + QColor mColour; + QColor sColour; + QColor dataInColour; + QColor dataOutColour; + Chart::LabelType labelType; + KSim::Label *krell; + // first will be data In and second will be data out + QValueList values; + QValueList maxValues; + int minValue; + int maxValue; + bool variableGraphs; +}; + +KSim::Chart::Chart(bool showKrell, int maxValue, + const QString &title, QWidget *parent, const char *name, + WFlags fl) : QWidget(parent, name, fl) +{ + init(showKrell, maxValue, title); +} + +KSim::Chart::Chart(bool showKrell, int maxValue, + QWidget *parent, const char *name, WFlags fl) + : QWidget(parent, name, fl) +{ + init(showKrell, maxValue, i18n("None")); +} + +KSim::Chart::~Chart() +{ + delete d->krell; + delete d; +} + +const QString &KSim::Chart::text(DataType type) const +{ + if (type == DataIn) + return d->inText; + + return d->outText; +} + +const QString &KSim::Chart::title() const +{ + return d->title; +} + +bool KSim::Chart::displayMeter() const +{ + return d->showKrell; +} + +int KSim::Chart::minValue() const +{ + return d->minValue; +} + +int KSim::Chart::maxValue() const +{ + return d->maxValue; +} + +int KSim::Chart::value(DataType dataType) const +{ + switch (dataType) { + case DataIn: + return d->values.first().first; + break; + case DataOut: + return d->values.first().second; + break; + } + + return 0; +} + +void KSim::Chart::setLabelType(LabelType labelType) +{ + d->labelType = labelType; + + // return if d->krell is not NULL and if the label type is the + // same or if showKrell is set to false + if ((d->krell && d->labelType == labelType) || !d->showKrell) + return; + + delete d->krell; + + switch (labelType) { + case Label: + d->krell = new KSim::Label(this); + break; + case Progress: + d->krell = new KSim::Progress(maxValue(), KSim::Types::None, + KSim::Progress::Panel, this); + break; + case Led: + d->krell = new KSim::LedLabel(maxValue(), KSim::Types::None, this); + break; + } + + int height = d->krell->height() - 2; + d->krell->setText(title()); + d->krell->setFixedSize(width(), height); + d->krell->move(0, d->size.height() - height); + d->krell->show(); +} + +KSim::Chart::LabelType KSim::Chart::labelType() const +{ + return d->labelType; +} + +void KSim::Chart::buildPixmaps() +{ + QImage image(themeLoader().current().chartPixmap()); + KSim::ThemeLoader::self().reColourImage(image); + d->chartPixmap.convertFromImage(image.smoothScale(chartSize())); + + // We need to reset the image data just + // incase the krellDataIn image doesn't exist + image.reset(); + image.load(themeLoader().current().gridPixmap()); + KSim::ThemeLoader::self().reColourImage(image); + d->gridPixmap.convertFromImage(image.smoothScale(chartSize().width(), 1)); + + // load these values here so we dont need to keep accessing them while + // painting to keep the cpu usage down + d->dataInColour = themeLoader().current().chartInColour(); + d->dataOutColour = themeLoader().current().chartOutColour(); + + image.reset(); + image.load(themeLoader().current().dataInPixmap()); + KSim::ThemeLoader::self().reColourImage(image); + if (!image.isNull()) { + d->dataInColour = image.smoothScale(chartSize()).pixel(2, 2); + kdDebug(2003) << className() << ": Using krellDataIn() = " + << themeLoader().current().dataInPixmap() << endl; + } + else { + kdDebug(2003) << className() << ": Using chartInColor() = " + << d->dataInColour.name() << endl; + } + + image.reset(); + image.load(themeLoader().current().dataOutPixmap()); + KSim::ThemeLoader::self().reColourImage(image); + if (!image.isNull()) { + d->dataOutColour = image.smoothScale(chartSize()).pixel(2, 2); + kdDebug(2003) << className() << ": Using krellDataOut() = " + << themeLoader().current().dataOutPixmap() << endl; + } + else { + kdDebug(2003) << className() << ": Using chartOutColor() = " + << d->dataOutColour.name() << endl; + } +} + +void KSim::Chart::configureObject(bool repaintWidget) +{ + QSize oldSize = sizeHint(); + KSim::Config::config()->setGroup("Misc"); + d->size = KSim::Config::config()->readSizeEntry("GraphSize"); + + if (d->krell && d->showKrell) { + int krellHeight = d->krell->fontMetrics().height() - 2; + d->size.setHeight(d->size.height() + krellHeight); + d->krell->setFixedHeight(krellHeight); + d->krell->move(0, d->size.height() - krellHeight); + d->krell->show(); + } + + // Update our geometry if we need to let any + // layout know about our sizeHint() change + if (oldSize != sizeHint()) { + // Using resize() here seems to be needed + resize(sizeHint()); + updateGeometry(); + } + + buildPixmaps(); + + setConfigValues(); + + if (repaintWidget) + update(); +} + +QSize KSim::Chart::sizeHint() const +{ + return d->size; +} + +QSize KSim::Chart::minimumSizeHint() const +{ + return sizeHint(); +} + +void KSim::Chart::resizeEvent(QResizeEvent *re) +{ + if (d->chartPixmap.size() != chartSize()) + buildPixmaps(); + QWidget::resizeEvent(re); +} + +void KSim::Chart::disableAutomaticUpdates() +{ + KSim::Chart::Timer::disconnect(this); +} + +void KSim::Chart::clear() +{ + d->values.clear(); + d->maxValues.clear(); + updateDisplay(); +} + +void KSim::Chart::setTitle(const QString &name) +{ + if (d->krell) { + d->title = name; + d->krell->setText(name); + } +} + +void KSim::Chart::setDisplayMeter(bool value) +{ + if (d->showKrell == value) + return; + + d->showKrell = value; + setLabelType(d->labelType); + + // delete the meter if value is false + if (!value) { + delete d->krell; + d->krell = 0; + } +} + +void KSim::Chart::setText(const QString &in, const QString &out) +{ + bool repaint = false; + + if (d->inText != in) { + repaint = true; + d->inText = in; + } + + if (d->outText != out) { + repaint = true; + d->outText = out; + } + + if (repaint) + update(); +} + +void KSim::Chart::setMinValue(int minValue) +{ + if (d->minValue == minValue) + return; + + d->minValue = minValue; + + if (d->krell && labelType() != Label) + static_cast(d->krell)->setMinValue(minValue); +} + +void KSim::Chart::setMaxValue(int maxValue) +{ + if (d->maxValue == maxValue) + return; + + d->maxValue = maxValue; + + if (d->krell && labelType() != Label) + static_cast(d->krell)->setMaxValue(maxValue); +} + +void KSim::Chart::setValue(int valueIn, int valueOut) +{ + d->values.prepend(qMakePair(range(valueIn), range(valueOut))); + + if (d->variableGraphs) { + d->maxValues.prepend(valueIn > valueOut ? valueIn : valueOut); + } + else { + if (valueIn > maxValue()) + setMaxValue(valueIn); + + if (valueOut > maxValue()) + setMaxValue(valueOut); + } + + if (d->krell && labelType() != Label) + static_cast(d->krell)->setValue(valueIn ? valueIn + : valueOut); + + // Remove the first entry from our lists to + // make sure we only have a list the size of + // our widgets width + if (d->values.count() == (uint)(width() + 1)) { + d->values.remove(--(d->values.end())); + d->maxValues.remove(--(d->maxValues.end())); + } + + if (d->krell && labelType() == Led) { + static_cast(d->krell)->toggle(KSim::Led::First); + static_cast(d->krell)->toggle(KSim::Led::Second); + } +} + +void KSim::Chart::setConfigValues() +{ + QFont newFont = font(); + bool repaint = themeLoader().current().fontColours(this, + newFont, d->mColour, d->sColour, d->showShadow); + + if (font() != newFont) + setFont(newFont); + + if (repaint) + update(); +} + +void KSim::Chart::extraTypeCall() +{ + setConfigValues(); +} + +QColor KSim::Chart::chartColour(const DataType &dataType, int, int) const +{ + switch (dataType) { + case DataIn: + return d->dataInColour; + break; + case DataOut: + return d->dataOutColour; + break; + } + + return QColor(); // avoid a g++ warning +} + +void KSim::Chart::paintEvent(QPaintEvent *) +{ + if (d->krell && labelType() == Led) { + static_cast(d->krell)->setOff(KSim::Led::First); + static_cast(d->krell)->setOff(KSim::Led::Second); + } + + const QSize &size = chartSize(); + QPixmap pixmap(size); + QPainter painter; + painter.begin(&pixmap, this); + + int location = size.height() / 5; + painter.drawPixmap(0, 0, d->chartPixmap); + // draw the plotted data onto the graph + painter.drawPixmap(0, 0, d->graphData); + painter.drawPixmap(0, location, d->gridPixmap); + painter.drawPixmap(0, location * 2, d->gridPixmap); + painter.drawPixmap(0, location * 3, d->gridPixmap); + painter.drawPixmap(0, location * 4, d->gridPixmap); + painter.drawPixmap(0, location * 5, d->gridPixmap); + + if (d->showShadow) { + painter.setPen(d->sColour); + location = (fontMetrics().height() / 2) + 5; + painter.drawText(3, location, d->inText); + if (!d->outText.isNull()) + painter.drawText(3, location * 2, d->outText); + } + + painter.setPen(d->mColour); + location = (fontMetrics().height() / 2) + 3; + painter.drawText(1, location, d->inText); + if (!d->outText.isNull()) + painter.drawText(1, location * 2, d->outText); + + painter.end(); + bitBlt(this, 0, 0, &pixmap); +} + +void KSim::Chart::fontChange(const QFont &) +{ + if (d->krell) + d->krell->setFont(font()); +} + +void KSim::Chart::updateDisplay() +{ + drawChart(); + update(); +} + +int KSim::Chart::yLocation(int value) const +{ + int krellHeight = (d->krell ? d->krell->height() : 0); + + int rangePos = maxValue() - minValue(); + int valuePos = value - minValue(); + + int returnValue = 0; + if (rangePos) + returnValue = (height() - krellHeight) * valuePos / rangePos; + + // Make sure we dont return a negative value + return returnValue >= 0 ? returnValue : 0; +} + +void KSim::Chart::drawChart() +{ + if (chartSize() != d->graphData.size()) + d->graphData.resize(chartSize()); + + if (d->variableGraphs) { + int maxValue = 0; + QValueList::ConstIterator max; + for (max = d->maxValues.begin(); max != d->maxValues.end(); ++max) { + if ((*max) > maxValue) + maxValue = (*max); + } + + setMaxValue(maxValue); + } + + QPainter painter; + d->graphData.setMask(drawMask(&painter)); + painter.begin(&d->graphData, this); + + int position = width() - 1; + QValueList::ConstIterator it; + for (it = d->values.begin(); it != d->values.end(); ++it) { + // Draw the data In lines first if its higher than the data out lines + if ((*it).first >= (*it).second) { + drawIn(&painter, (*it).first, position); + drawOut(&painter, (*it).second, position); + } + else { + drawOut(&painter, (*it).second, position); + drawIn(&painter, (*it).first, position); + } + --position; + } + + painter.end(); +} + +QSize KSim::Chart::chartSize() const +{ + QSize sz(size()); + if (d->krell && d->showKrell) + sz.setHeight(sz.height() - d->krell->height()); + + return sz; +} + +QBitmap KSim::Chart::drawMask(QPainter *painter) +{ + QBitmap bitmap(chartSize(), true); + painter->begin(&bitmap, this); + painter->setPen(color1); + + int position = width() - 1; + QValueList::ConstIterator it; + for (it = d->values.begin(); it != d->values.end(); ++it) { + drawIn(painter, (*it).first, position, true); + drawOut(painter, (*it).second, position, true); + --position; + } + + painter->end(); + + return bitmap; +} + +void KSim::Chart::drawIn(QPainter *painter, int value, int pos, bool dontSet) +{ + if (!dontSet) { + painter->setPen(chartColour(DataIn)); + } + + int location = yLocation(value); + painter->moveTo(0, 0); + painter->drawLine(pos, d->graphData.size().height(), + pos, d->graphData.size().height() - location); +} + +void KSim::Chart::drawOut(QPainter *painter, int value, int pos, bool dontSet) +{ + if (!dontSet) { + painter->setPen(chartColour(DataOut)); + } + + int location = yLocation(value); + painter->moveTo(0, 0); + painter->drawLine(pos, d->graphData.size().height(), + pos, d->graphData.size().height() - location); +} + +int KSim::Chart::range(int value) const +{ + if (value > maxValue()) + return maxValue(); + + if (value < minValue()) + return minValue(); + + return value; +} + +void KSim::Chart::init(bool krell, int maxValue, const QString &title) +{ + setConfigString("StyleChart"); + setThemeConfigOnly(false); + setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed)); + + d = new Private; + KSim::Config::config()->setGroup("Misc"); + d->variableGraphs = KSim::Config::config()->readBoolEntry("UseVariableGraphs", true); + d->showKrell = krell; + d->krell = 0L; + d->title = title; + d->minValue = 0; + d->maxValue = 0; + + KSim::Chart::Timer::syncChart(this); + setBackgroundMode(NoBackground); + setLabelType(Label); + setMaxValue(maxValue); + configureObject(false); +} diff --git a/ksim/library/chart.h b/ksim/library/chart.h new file mode 100644 index 0000000..55f4426 --- /dev/null +++ b/ksim/library/chart.h @@ -0,0 +1,184 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIM__CHART_H +#define KSIM__CHART_H + +#include +#include "common.h" + +#include + +class QColor; + +namespace KSim +{ + /** + * provides a graph displaying data onscreen using gkrellm themes + * @author Robbie Ward + */ + class KDE_EXPORT Chart : public QWidget, public KSim::Base + { + Q_OBJECT + public: + enum DataType { DataIn = 0, DataOut }; + enum LabelType { Label = 0, Progress, Led }; + /** + * Constructs a KSim::Chart. + * + * @param displayMeter is if the krellbar should be shown + * @param minValue is the minimum value to show + * @param maxValue is the maximum value to show + * @param title is the title off the krell bar (if enabled) + * @param parent is the parent widget + */ + Chart(bool displayMeter, int maxValue, + const QString &title, QWidget *parent, + const char *name = 0, WFlags fl = 0); + /** + * Constructs a KSim::Chart. + * + * @param showKrell is if the krellbar should be shown + * @param minValue is the minimum value to show + * @param maxValue is the maximum value to show + * @param parent is the parent widget + */ + Chart(bool displayMeter, int maxValue, + QWidget *parent, const char *name = 0, + WFlags fl = 0); + /** + * destructs KSim::Chart + */ + virtual ~Chart(); + + /** + * returns the current text of the chart + */ + const QString &text(DataType type) const; + /** + * @return the title of the chart + */ + const QString &title() const; + /** + * @return true if the meter is enabled + */ + bool displayMeter() const; + /** + * @return the minimum value + */ + int minValue() const; + /** + * @return the minimum value + */ + int maxValue() const; + /** + * @return the current value + */ + int value(DataType dataType) const; + /** + * sets the type of the label that will appear under the graph + */ + void setLabelType(LabelType labelType); + /** + * @return the current label type, one of: Label, Progress, Led + */ + LabelType labelType() const; + + /** + * reimplemented for internal reasons + */ + virtual void configureObject(bool repaintWidget = true); + + /** + * reimplemented for internal reasons + */ + QSize sizeHint() const; + /** + * reimplemented for internal reasons + */ + QSize minimumSizeHint() const; + + void disableAutomaticUpdates(); + + public slots: + /** + * Cleats the graphs contents + */ + void clear(); + /** + * sets the title of the chart, this function returns if + * the optional krell widget is disabled + */ + void setTitle(const QString &); + /** + * turns the meter on and off + */ + void setDisplayMeter(bool); + /** + * sets the current text that apears in the top left hand corner + */ + void setText(const QString &in, const QString &out = QString::null); + /** + * Sets the minimum value the graph will display + */ + void setMinValue(int); + /** + * Sets the maximum value the graph will display + */ + void setMaxValue(int); + /** + * sets the value of the graph + */ + void setValue(int valueIn, int valueOut = 0); + + protected: + /** + * Set the config values depending on the chart type + */ + void setConfigValues(); + /** + * reimplemented for internal reasons + */ + virtual void extraTypeCall(); + + QColor chartColour(const DataType &dataType, int x = 1, int y = 1) const; + virtual void paintEvent(QPaintEvent *); + virtual void fontChange(const QFont &); + virtual void resizeEvent(QResizeEvent *re); + + protected slots: + void updateDisplay(); + + private: + void buildPixmaps(); + int yLocation(int) const; + void drawChart(); + QSize chartSize() const; + QBitmap drawMask(QPainter *); + void drawIn(QPainter *, int, int, bool = false); + void drawOut(QPainter *, int, int, bool = false); + int range(int) const; + void init(bool, int, const QString &); + + class Timer; + class Private; + Private *d; + }; +} +#endif diff --git a/ksim/library/common.cpp b/ksim/library/common.cpp new file mode 100644 index 0000000..3e714c6 --- /dev/null +++ b/ksim/library/common.cpp @@ -0,0 +1,102 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "common.h" +#include + +#include +#include "themetypes.h" +#include "../baselist.h" + +class KSim::Base::Private +{ + public: + int type; + bool theme; + QString string; +}; + +KSim::Base::Base() +{ + KSim::BaseList::add(this); + + d = new Base::Private; + d->type = KSim::Types::None; + d->theme = true; +} + +KSim::Base::Base(int type) +{ + KSim::BaseList::add(this); + + d = new Base::Private; + d->type = type; + d->theme = true; +} + +KSim::Base::~Base() +{ + if (!KSim::BaseList::remove(this)) + kdError() << "While trying to remove " << this << " from the list" << endl; + delete d; +} + +bool KSim::Base::isThemeConfigOnly() const +{ + return d->theme; +} + +void KSim::Base::setType(int type) +{ + if (d->type == type) + return; + + d->type = type; + extraTypeCall(); +} + +int KSim::Base::type() const +{ + return d->type; +} + +void KSim::Base::setConfigString(const QString &string) +{ + d->string = string; +} + +const QString &KSim::Base::configString() const +{ + return d->string; +} + +void KSim::Base::extraTypeCall() +{ +} + +KSim::ThemeLoader &KSim::Base::themeLoader() const +{ + // Provided for convenience + return KSim::ThemeLoader::self(); +} + +void KSim::Base::setThemeConfigOnly(bool value) +{ + d->theme = value; +} diff --git a/ksim/library/common.h b/ksim/library/common.h new file mode 100644 index 0000000..3f53f7a --- /dev/null +++ b/ksim/library/common.h @@ -0,0 +1,134 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIM__COMMON_H +#define KSIM__COMMON_H + +#define KSIM_VERSION 110 +#define KSIM_VERSION_STRING "1.1.0" + +#include +#include + +/** + * namespace for common ksim entries + * + * @author Robbie Ward + */ +namespace KSim +{ + // a few forward declares + class ThemeLoader; + class Theme; + class PluginLoader; + class PluginList; + class Plugin; + class PluginObject; + class PluginView; + class PluginPage; + + /** + * class that all widgets (library dir only) HAVE to inherit + * if they want to change items on ksim configuration reload + * + * any class that inherits this must re-implement + * the configureObject() function. + * + * example: + *
    +   *  #include <qwidget.h>
    +   *  #include <ksim/common.h>
    +   *
    +   *  class Test : public QWidget, virtual public KSim::Base
    +   *  {
    +   *    public:
    +   *      Test(QWidget *parent, const char *name) : QWidget(parent, name)
    +   *      {
    +   *      }
    +   *      ~Test() {}
    +   *
    +   *      void configureObject(bool repaintWidget)
    +   *      {
    +   *        // Re-Create view code here
    +   *      }
    +   *  };
    +   * 
    + * @short base class for widgets + * @author Robbie Ward + */ + class KDE_EXPORT Base + { + public: + Base(); + Base(int type); + virtual ~Base(); + + /** + * Reimplement this to change theme images/locations etc + */ + virtual void configureObject(bool = true) = 0; + /** + * returns true if configureObject has been setup + * to contain only theme configuration + * @see #setThemeConfigOnly + */ + bool isThemeConfigOnly() const; + /** + * sets the theme type + */ + void setType(int type); + /** + * @return the theme type, eg host, mem, swap etc + */ + int type() const; + /** + * Set the config entry key to look for when reading gkrellmrc + */ + void setConfigString(const QString &string); + /** + * @return the config entry to look for when reading theme files + */ + const QString &configString() const; + + protected: + /** + * reimplement this function if you want setType() + * to call extra information + */ + virtual void extraTypeCall(); + /** + * @return the current KSim::ThemeLoader instance + */ + KSim::ThemeLoader &themeLoader() const; + /** + * set this to false if you want KSim to call your KSim::Base + * configureObject() when KSim's configuration has changed + * even if the theme settings are the same. The default is true + */ + void setThemeConfigOnly(bool); + + private: + Base(const Base &rhs); + Base &operator=(const Base &rhs); + + class Private; + Private *d; + }; +} +#endif diff --git a/ksim/library/ksimconfig.cpp b/ksim/library/ksimconfig.cpp new file mode 100644 index 0000000..9f70890 --- /dev/null +++ b/ksim/library/ksimconfig.cpp @@ -0,0 +1,427 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#include "ksimconfig.h" +#include "themeloader.h" + +KConfig *KSim::Config::mainConfig = 0; + +KSim::Config::Config(KConfig *config) +{ + mainConfig = config; +} + +KSim::Config::~Config() +{ +} + +KConfig *KSim::Config::config() +{ + return mainConfig; +} + +int KSim::Config::width(int defaultWidth) const +{ + mainConfig->setGroup("General Options"); + int savedWidth = mainConfig->readNumEntry("Width"); + if (savedWidth == -1) + return defaultWidth; + + return savedWidth; +} + +void KSim::Config::setWidth(int width) +{ + mainConfig->setGroup("General Options"); + mainConfig->writeEntry("Width", width); + mainConfig->sync(); +} + +bool KSim::Config::enabledMonitor(const QString &entry) const +{ + mainConfig->setGroup("Monitors"); + return mainConfig->readBoolEntry(entry, false); +} + +void KSim::Config::setEnabledMonitor(const QString &entry, bool enabled) +{ + mainConfig->setGroup("Monitors"); + mainConfig->writeEntry(entry, enabled); + mainConfig->sync(); +} + +QString KSim::Config::monitorCommand(const QString &entry) const +{ + mainConfig->setGroup("Monitors"); + return mainConfig->readPathEntry(entry + "_command"); +} + +void KSim::Config::setMonitorCommand(const QString &entry, + const QString &command) +{ + mainConfig->setGroup("Monitors"); + mainConfig->writePathEntry(entry + "_command", command); + mainConfig->sync(); +} + +int KSim::Config::monitorLocation(const QString &entry) +{ + mainConfig->setGroup("Monitors"); + return mainConfig->readNumEntry(entry + "_location", -1); +} + +void KSim::Config::setMonitorLocation(const QString &entry, int location) +{ + mainConfig->setGroup("Monitors"); + mainConfig->writeEntry(entry + "_location", location); + mainConfig->sync(); +} + +bool KSim::Config::displayFqdn() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("DisplayFqdn", true); +} + +void KSim::Config::setDisplayFqdn(bool value) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("DisplayFqdn", value); + mainConfig->sync(); +} + +bool KSim::Config::showDock() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("showDock", true); +} + +void KSim::Config::setShowDock(bool showDock) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("showDock", showDock); + mainConfig->sync(); +} + +bool KSim::Config::savePos() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("savePos", false); +} + +void KSim::Config::setSavePos(bool savePos) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("savePos", savePos); + mainConfig->sync(); +} + +bool KSim::Config::stayOnTop() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("stayOnTop", false); +} + +void KSim::Config::setStayOnTop(bool stayOnTop) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("stayOnTop", stayOnTop); + mainConfig->sync(); +} + +QPoint KSim::Config::position(const QPoint &defaultPos) const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readPointEntry("ksimPosition", &defaultPos); +} + +void KSim::Config::setPosition(const QPoint &pos) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("ksimPosition", pos); + mainConfig->sync(); +} + +QSize KSim::Config::graphSize() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readSizeEntry("GraphSize"); +} + +void KSim::Config::setGraphSize(const QSize &size) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("GraphSize", size); + mainConfig->sync(); +} + +QString KSim::Config::uptimeFormat() const +{ + return uptimeFormatList()[uptimeItem()]; +} + +int KSim::Config::uptimeItem() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readNumEntry("UptimeItem", 0); +} + +QStringList KSim::Config::uptimeFormatList() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readListEntry("UptimeFormat"); +} + +void KSim::Config::setUptimeFormat(const QStringList &uptimeFormat) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("UptimeFormat", uptimeFormat); + mainConfig->sync(); +} + +void KSim::Config::setUptimeItem(int item) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("UptimeItem", item); + mainConfig->sync(); +} + +QString KSim::Config::memoryFormat() const +{ + return memoryFormatList()[memoryItem()]; +} + +int KSim::Config::memoryItem() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readNumEntry("MemoryItem", 0); +} + +QStringList KSim::Config::memoryFormatList() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readListEntry("MemoryFormat"); +} + +void KSim::Config::setMemoryFormat(const QStringList &memoryFormat) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("MemoryFormat", memoryFormat); + mainConfig->sync(); +} + +void KSim::Config::setMemoryItem(int item) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("MemoryItem", item); + mainConfig->sync(); +} + +QString KSim::Config::swapFormat() const +{ + mainConfig->setGroup("Misc"); + return swapFormatList()[swapItem()]; +} + +int KSim::Config::swapItem() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readNumEntry("SwapItem", 0); +} + +QStringList KSim::Config::swapFormatList() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readListEntry("SwapFormat"); +} + +void KSim::Config::setSwapFormat(const QStringList &swapFormat) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("SwapFormat", swapFormat); + mainConfig->sync(); +} + +void KSim::Config::setSwapItem(int item) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("SwapItem", item); + mainConfig->sync(); +} + +bool KSim::Config::showTime() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("ShowTime", false); +} + +void KSim::Config::setShowTime(bool time) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("ShowTime", time); + mainConfig->sync(); +} + +bool KSim::Config::show24hour() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("Show24hour", true); +} + +void KSim::Config::setShow24hour(bool _24hour) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("Show24hour", _24hour); + mainConfig->sync(); +} + +bool KSim::Config::showDate() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("ShowDate", false); +} + +void KSim::Config::setShowDate(bool date) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("ShowDate", date); + mainConfig->sync(); +} + +bool KSim::Config::showUptime() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("ShowUptime", true); +} + +void KSim::Config::setShowUptime(bool uptime) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("ShowUptime", uptime); + mainConfig->sync(); +} + +bool KSim::Config::showMemory() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("ShowMemory", true); +} + +void KSim::Config::setShowMemory(bool memory) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("ShowMemory", memory); + mainConfig->sync(); +} + +bool KSim::Config::showSwap() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("ShowSwap", true); +} + +void KSim::Config::setShowSwap(bool swap) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("ShowSwap", swap); + mainConfig->sync(); +} + +bool KSim::Config::showProcs() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("ShowProcs", false); +} + +void KSim::Config::setShowProcs(bool procs) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("ShowProcs", procs); + mainConfig->sync(); +} + +QString KSim::Config::themeUrl() const +{ + return KSim::ThemeLoader::currentUrl(); +} + +QString KSim::Config::themeName() const +{ + return KSim::ThemeLoader::currentName(); +} + +void KSim::Config::setThemeName(const QString &name) +{ + mainConfig->setGroup("Theme"); + mainConfig->writeEntry("Name", name); + mainConfig->sync(); +} + +int KSim::Config::themeAlt() const +{ + return KSim::ThemeLoader::currentAlternative(); +} + +void KSim::Config::setThemeAlt(int alt) +{ + mainConfig->setGroup("Theme"); + mainConfig->writeEntry("Alternative", alt); + mainConfig->sync(); +} + +QFont KSim::Config::themeFont() const +{ + return KSim::ThemeLoader::currentFont(); +} + +void KSim::Config::setThemeFont(const QFont &font) +{ + mainConfig->setGroup("Theme"); + mainConfig->writeEntry("Font", font); + mainConfig->sync(); +} + +int KSim::Config::themeFontItem() const +{ + return KSim::ThemeLoader::currentFontItem(); +} + +void KSim::Config::setThemeFontItem(int item) +{ + mainConfig->setGroup("Theme"); + mainConfig->writeEntry("FontItem", item); + mainConfig->sync(); +} + +bool KSim::Config::reColourThemes() const +{ + mainConfig->setGroup("Misc"); + return mainConfig->readBoolEntry("ReColourTheme", false); +} + +void KSim::Config::setReColourThemes(bool value) +{ + mainConfig->setGroup("Misc"); + mainConfig->writeEntry("ReColourTheme", value); + mainConfig->sync(); +} diff --git a/ksim/library/ksimconfig.h b/ksim/library/ksimconfig.h new file mode 100644 index 0000000..0208b18 --- /dev/null +++ b/ksim/library/ksimconfig.h @@ -0,0 +1,109 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIMCONFIG_H +#define KSIMCONFIG_H + +#include +#include +#include + +#include + +class KConfig; + +namespace KSim +{ + /** + * @internal + */ + class KDE_EXPORT Config + { + public: + Config(KConfig *config); + ~Config(); + + static KConfig *config(); + + int width(int defaultWidth) const; + void setWidth(int width); + bool enabledMonitor(const QString &) const; + void setEnabledMonitor(const QString &, bool); + QString monitorCommand(const QString &) const; + void setMonitorCommand(const QString &, const QString &); + int monitorLocation(const QString &); + void setMonitorLocation(const QString &, int); + bool displayFqdn() const; + void setDisplayFqdn(bool); + bool showDock() const; + void setShowDock(bool); + bool savePos() const; + void setSavePos(bool); + bool stayOnTop() const; + void setStayOnTop(bool); + QPoint position(const QPoint &) const; + void setPosition(const QPoint &); + QSize graphSize() const; + void setGraphSize(const QSize &); + QString uptimeFormat() const; + void setUptimeFormat(const QStringList &); + int uptimeItem() const; + void setUptimeItem(int); + QStringList uptimeFormatList() const; + QString memoryFormat() const; + void setMemoryFormat(const QStringList &); + int memoryItem() const; + void setMemoryItem(int); + QStringList memoryFormatList() const; + QString swapFormat() const; + void setSwapFormat(const QStringList &); + int swapItem() const; + void setSwapItem(int); + QStringList swapFormatList() const; + bool showTime() const; + void setShowTime(bool); + bool show24hour() const; + void setShow24hour(bool); + bool showDate() const; + void setShowDate(bool); + bool showUptime() const; + void setShowUptime(bool); + bool showMemory() const; + void setShowMemory(bool); + bool showSwap() const; + void setShowSwap(bool); + bool showProcs() const; + void setShowProcs(bool); + QString themeUrl() const; + QString themeName() const; + void setThemeName(const QString &); + int themeAlt() const; + void setThemeAlt(int); + QFont themeFont() const; + void setThemeFont(const QFont &); + int themeFontItem() const; + void setThemeFontItem(int); + bool reColourThemes() const; + void setReColourThemes(bool); + + private: + static KConfig *mainConfig; + }; +} +#endif diff --git a/ksim/library/label.cpp b/ksim/library/label.cpp new file mode 100644 index 0000000..91e7621 --- /dev/null +++ b/ksim/library/label.cpp @@ -0,0 +1,301 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "label.h" +#include "label.moc" +#include +#include "themetypes.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class KSim::Label::Private +{ + public: + QColor mColour; + QColor sColour; + QRect loc; + QRect shad; + QString text; + QImage meterImage; + QPixmap background; + QPixmap sidePixmap; + bool showShadow; +}; + +KSim::Label::Label(QWidget *parent, const char *name, WFlags fl) + : QWidget(parent, name, fl) +{ + initWidget(KSim::Types::None); +} + +KSim::Label::Label(int type, QWidget *parent, const char *name, + WFlags fl) : QWidget(parent, name, fl) +{ + initWidget(type); +} + +KSim::Label::Label(int type, const QString &text, QWidget *parent, + const char *name, WFlags fl) : QWidget(parent, name, fl) +{ + initWidget(type); + setText(text); +} + +KSim::Label::~Label() +{ + delete d; +} + +const QString &KSim::Label::text() const +{ + return d->text; +} + +void KSim::Label::configureObject(bool repaintWidget) +{ + QString image = themeLoader().current().meterPixmap(type(), false); + if (image.isEmpty()) + image = themeLoader().current().panelPixmap(type()); + + d->meterImage.load(image); + KSim::ThemeLoader::self().reColourImage(d->meterImage); + d->background = d->meterImage.smoothScale(size()); + QSize oldSize = sizeHint(); + + setConfigValues(); + relayoutLabel(oldSize, repaintWidget); +} + +void KSim::Label::setPixmap(const QPixmap &pixmap) +{ + if (pixmap.serialNumber() == d->sidePixmap.serialNumber()) + return; + + QSize oldSize = sizeHint(); + d->sidePixmap = pixmap; + + relayoutLabel(oldSize); +} + +const QPixmap &KSim::Label::pixmap() const +{ + return d->sidePixmap; +} + +QSize KSim::Label::sizeHint() const +{ + int width = fontMetrics().size(SingleLine, text()).width(); + if (!pixmap().isNull()) + width += pixmap().width() + 5; + + int height = fontMetrics().height() + 4; + if (!pixmap().isNull() && pixmap().height() > height) + height = pixmap().height(); + + return QSize(width, height); +} + +QSize KSim::Label::minimumSizeHint() const +{ + return sizeHint(); +} + +void KSim::Label::clear() +{ + setText(QString::null); +} + +void KSim::Label::setText(const QString &text) +{ + if (text == d->text) + return; // If the text is the same, no need to repaint etc + + QSize oldSize = sizeHint(); + // set the text of our widget and repaint + d->text = text; + relayoutLabel(oldSize); +} + +void KSim::Label::extraTypeCall() +{ + d->meterImage.load(themeLoader().current().meterPixmap(type())); + setConfigValues(); +} + +void KSim::Label::setShowShadow(bool show) +{ + d->showShadow = show; +} + +bool KSim::Label::showShadow() const +{ + return d->showShadow; +} + +void KSim::Label::setTextColour(const QColor &color) +{ + d->mColour = color; +} + +const QColor &KSim::Label::textColour() const +{ + return d->mColour; +} + +void KSim::Label::setShadowColour(const QColor &color) +{ + d->sColour = color; +} + +const QColor &KSim::Label::shadowColour() const +{ + return d->sColour; +} + +void KSim::Label::setConfigValues() +{ + QFont newFont = font(); + bool repaint = themeLoader().current().fontColours(this, + newFont, d->mColour, d->sColour, d->showShadow); + + if (font() != newFont) + setFont(newFont); + + if (repaint) + update(); +} + +void KSim::Label::paintEvent(QPaintEvent *) +{ + QPainter painter; + painter.begin(this); + + // paint our background pixmap onto the widget + painter.drawPixmap(0, 0, d->background); + + drawPixmap(&painter, d->loc, pixmap()); + if (d->showShadow) { // draw the shadow text on the image + drawText(&painter, d->shad, d->sColour, d->text); + } + + // draw the label text onto the widget + painter.setPen(d->mColour); + drawText(&painter, d->loc, d->mColour, d->text); + painter.end(); +} + +void KSim::Label::resizeEvent(QResizeEvent *ev) +{ + // set the location of where the shadow'ed text will be drawn + d->shad.setWidth(ev->size().width() + 3); + d->shad.setHeight(ev->size().height() + 3); + + // set the location of where the text will be drawn + d->loc.setWidth(ev->size().width()); + d->loc.setHeight(ev->size().height()); + + d->background = d->meterImage.smoothScale(ev->size()); +} + +void KSim::Label::drawText(QPainter *painter, const QRect &rect, + const QColor &color, const QString &text) +{ + QRect location(rect); + if (!pixmap().isNull()) + location.setX(pixmap().width() + 5); + + style().drawItem(painter, location, AlignCenter, colorGroup(), true, + 0, text, -1, &color); +} + +void KSim::Label::drawPixmap(QPainter *painter, const QRect &rect, + const QPixmap &pixmap) +{ + QRect location(rect); + location.setWidth(pixmap.width()); + + style().drawItem(painter, location, AlignCenter, colorGroup(), true, + pixmap.isNull() ? 0 : &pixmap, QString::null); +} + +void KSim::Label::setTextLocation(const QRect &rect) +{ + d->loc = rect; +} + +const QRect &KSim::Label::textLocation() const +{ + return d->loc; +} + +void KSim::Label::setShadowLocation(const QRect &rect) +{ + d->shad = rect; +} + +const QRect &KSim::Label::shadowLocation() const +{ + return d->shad; +} + +void KSim::Label::setThemePixmap(const QString &image) +{ + QSize oldSize = sizeHint(); + d->meterImage.reset(); + d->meterImage.load(image); + KSim::ThemeLoader::self().reColourImage(d->meterImage); + d->background = d->meterImage.smoothScale(size()); + relayoutLabel(oldSize); +} + +void KSim::Label::relayoutLabel(const QSize &old, bool repaint) +{ + if (sizeHint() != old) { + updateGeometry(); + } + + if (repaint) + update(); +} + +void KSim::Label::initWidget(int type) +{ + d = new Private; + setType(type); + setConfigString("StyleMeter"); + + // try to reduce flicker as much as possible + setBackgroundMode(NoBackground); + setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, + QSizePolicy::Fixed)); + + configureObject(); +} diff --git a/ksim/library/label.h b/ksim/library/label.h new file mode 100644 index 0000000..1c750f2 --- /dev/null +++ b/ksim/library/label.h @@ -0,0 +1,210 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIM__LABEL_H +#define KSIM__LABEL_H + +#include +#include "common.h" + +#include + +namespace KSim +{ + /** + * A widget that provides a text or image display + * which supports themes from gkrellm + * + * @short Label widget + * @author Robbie Ward + */ + class KDE_EXPORT Label : public QWidget, public KSim::Base + { + Q_OBJECT + public: + /** + * Constructs a KSim::Label. + * + * @param parent is the parent widget + * + * Example usage: + *
    +       *  KSim::Label *label = new KSim::Label(this);
    +       * 
    + * To create a KSim::Label with the normal theme look + * @see KSim::ThemeLoader + */ + Label(QWidget *parent, const char *name = 0, WFlags fl = 0); + /** + * Constructs a KSimLabel. + * + * @param type is the theme type + * @param parent is the parent widget + * + * Example usage: + *
    +       *  KSim::Label *label = new KSim::Label(KSim::Types::None, this);
    +       * 
    + * To create a KSim::Label with the normal theme look, + * NOTE: this is the same as the KSim::Label(QWidget *, const char *, WFlags) ctor + * @see KSim::ThemeLoader + */ + Label(int type, QWidget *parent, const char *name = 0, WFlags fl = 0); + /** + * Constructs a KSim::Label. + * + * @param type is the theme type + * @param text is the default text to display + * @param parent is the parent widget + * + * Example usage: + *
    +       *  KSim::Label *label = new KSim:Label(KSim::Types::Host, "test label", this);
    +       * 
    + * To create a KSim::Label with the theme look of host + * @see KSim::ThemeLoader + */ + Label(int type, const QString &text, + QWidget *parent, const char *name = 0, WFlags fl = 0); + /** + * destructs KSim::Label. + */ + virtual ~Label(); + + /** + * returns the current text of the label + * @see #setText + */ + const QString &text() const; + /** + * recreates the labels look & feel + */ + virtual void configureObject(bool repaintWidget = true); + /** + * sets a pixmap for the label + */ + void setPixmap(const QPixmap &pixmap); + /** + * @return the side pixmap + */ + const QPixmap &pixmap() const; + /** + * reimplemented for internal reasons + */ + virtual QSize sizeHint() const; + /** + * reimplemented for internal reasons + */ + virtual QSize minimumSizeHint() const; + + public slots: + /** + * clears the current text in the label + */ + void clear(); + /** + * sets the current label of the widget to @ref text + * @see text() + */ + void setText(const QString &text); + + protected: + /** + * reimplemented for internal reasons + */ + virtual void extraTypeCall(); + /** + * set wether the shadow should be shown or not + */ + void setShowShadow(bool show); + /** + * @return true if the shadow is to be shown, else false + */ + bool showShadow() const; + /** + * Set the text color + */ + void setTextColour(const QColor &color); + /** + * @return the text color + */ + const QColor &textColour() const; + /** + * Set the shadow color + */ + void setShadowColour(const QColor &color); + /** + * @return the shadow color + */ + const QColor &shadowColour() const; + /** + * Set the config values depending on the chart type + */ + void setConfigValues(); + /** + * reimplemented for internal reasons + */ + virtual void paintEvent(QPaintEvent *); + /** + * reimplemented for internal reasons + */ + virtual void resizeEvent(QResizeEvent *); + /** + * draw the text onto the label + */ + void drawText(QPainter *painter, const QRect &rect, + const QColor &color, const QString &text); + /** + * draw the pixmap onto the label + */ + void drawPixmap(QPainter *painter, + const QRect &rect, const QPixmap &pixmap); + /** + * sets the location of the text + */ + void setTextLocation(const QRect &rect); + /** + * @return the location of the text + */ + const QRect &textLocation() const; + /** + * sets the location of the shadow text + */ + void setShadowLocation(const QRect &rect); + /** + * @return the location of the shadow text + */ + const QRect &shadowLocation() const; + /** + * sets the background image to be painted + */ + void setThemePixmap(const QString &image); + void relayoutLabel(const QSize &old, bool repaint = true); + + private: + /** + * initiates the widget + */ + void initWidget(int type); + + class Private; + Private *d; + }; +} +#endif diff --git a/ksim/library/led.cpp b/ksim/library/led.cpp new file mode 100644 index 0000000..8d0c88d --- /dev/null +++ b/ksim/library/led.cpp @@ -0,0 +1,349 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "led.h" +#include "led.moc" + +#include +#include +#include +#include + +#include +#include + +#include +#include "themetypes.h" + +class KSim::Led::Private +{ + public: + KPixmapSplitter splitter; + QPixmap pixmap; + QString imageName; + KSim::Led::Type type; + bool toggled; +}; + +KSim::Led::Led() : QPixmap() +{ + d = new Private; + + d->type = First; + d->toggled = false; + + setPixmap(KSim::ThemeLoader::self().current().ledPixmap(KSim::Types::Net)); + setOff(); +} + +KSim::Led::Led(Type type, const QString &imageName) : QPixmap() +{ + d = new Private; + + d->type = type; + d->toggled = false; + + setPixmap(imageName); + setOff(); +} + +KSim::Led::~Led() +{ + delete d; +} + +void KSim::Led::setOn(bool force) +{ + if (isOn() && !force) + return; + + // Return if our pixmap is null + QRect rect = d->splitter.coordinates(d->type == First ? 1 : 3); + if (d->pixmap.isNull() || rect.isEmpty()) { + resize(12, 8); + fill(Qt::white); + return; + } + + if (d->pixmap.mask() && !d->pixmap.mask()->isNull()) { + QBitmap mask(rect.size()); + bitBlt(&mask, QPoint(0, 0), d->pixmap.mask(), rect, CopyROP); + setMask(mask); + } + + bitBlt(this, QPoint(0, 0), &d->pixmap, rect, CopyROP); + d->toggled = true; +} + +void KSim::Led::setOff(bool force) +{ + if (!isOn() && !force) + return; + + // Return if our pixmap is null + QRect rect = d->splitter.coordinates(d->type == First ? 0 : 2); + if (d->pixmap.isNull() || rect.isEmpty()) { + resize(12, 8); + fill(Qt::white); + return; + } + + if (d->pixmap.mask() && !d->pixmap.mask()->isNull()) { + QBitmap mask(rect.size()); + bitBlt(&mask, QPoint(0, 0), d->pixmap.mask(), rect, CopyROP); + setMask(mask); + } + + bitBlt(this, QPoint(0, 0), &d->pixmap, rect, CopyROP); + d->toggled = false; +} + +void KSim::Led::toggle() +{ + if (d->toggled) + setOff(); + else + setOn(); +} + +void KSim::Led::setPixmap(const QString &imageName) +{ + if (imageName == d->imageName) + return; + + QImage image(imageName); + + if (image.width() >= 19) + image = image.smoothScale(19, image.height()); + + KSim::ThemeLoader::self().reColourImage(image); + d->pixmap.convertFromImage(image); + QSize size(image.width(), image.height() / 4); + + d->splitter.setPixmap(d->pixmap); + d->splitter.setItemSize(size); + + resize(size); + setMask(QBitmap()); +} + +const QString &KSim::Led::fileName() const +{ + return d->imageName; +} + +bool KSim::Led::isOn() const +{ + return d->toggled; +} + +void KSim::Led::setType(Type type) +{ + if (type == d->type) + return; + + d->type = type; +} + +KSim::Led::Type KSim::Led::type() const +{ + return d->type; +} + +void KSim::Led::update() +{ + if (isOn()) + setOn(true); + else + setOff(true); +} + +class KSim::LedLabel::Private +{ + public: + KSim::Led receiveLed; + KSim::Led sendLed; + QPoint sendPoint; + QPoint receivePoint; +}; + +KSim::LedLabel::LedLabel(int max, int type, const QString &label, + QWidget *parent, const char *name, WFlags fl) + : KSim::Progress(max, type, Panel, parent, name, fl) +{ + init(); + setText(label); +} + +KSim::LedLabel::LedLabel(int max, int type, + QWidget *parent, const char *name, WFlags fl) + : KSim::Progress(max, type, Panel, parent, name, fl) +{ + init(); +} + +KSim::LedLabel::LedLabel(int max, + QWidget *parent, const char *name, WFlags fl) + : KSim::Progress(max, KSim::Types::None, + Panel, parent, name, fl) +{ + init(); +} + +KSim::LedLabel::~LedLabel() +{ + delete d; +} + +void KSim::LedLabel::configureObject(bool reapaintWidget) +{ + KSim::Progress::configureObject(false); + + QPixmap pixmap = themeLoader().current().splitPixmap(KSim::Theme::KrellPanel, 0, false); + if (pixmap.isNull()) + pixmap = themeLoader().current().splitPixmap(KSim::Theme::KrellSlider); + + setMeterPixmap(pixmap); + d->receiveLed.setPixmap(themeLoader().current().ledPixmap(KSim::Types::Net)); + d->sendLed.setPixmap(themeLoader().current().ledPixmap(KSim::Types::Net)); + + // Update the leds to make sure they get painted correctly + d->receiveLed.update(); + d->sendLed.update(); + + setConfigValues(); + layoutLeds(); + + if (reapaintWidget) + update(); +} + +QSize KSim::LedLabel::sizeHint() const +{ + QSize hint(Progress::sizeHint()); + + if (d->sendLed.height() > hint.height()) + hint.setHeight(d->sendLed.height()); + + return hint; +} + +void KSim::LedLabel::reset() +{ + KSim::Progress::reset(); + setOff(Led::First); + setOff(Led::Second); +} + +void KSim::LedLabel::setOn(Led::Type type) +{ + if (type == Led::First) { + if (d->receiveLed.isOn()) + return; + + d->receiveLed.setOn(); + } + else { + if (d->sendLed.isOn()) + return; + + d->sendLed.setOn(); + } + + update(); +} + +void KSim::LedLabel::setOff(Led::Type type) +{ + if (type == Led::First) { + if (!d->receiveLed.isOn()) + return; + + d->receiveLed.setOff(); + } + else { + if (!d->sendLed.isOn()) + return; + + d->sendLed.setOff(); + } + + update(); +} + +void KSim::LedLabel::toggle(Led::Type type) +{ + if (type == Led::First) + d->receiveLed.toggle(); + else + d->sendLed.toggle(); + + update(); +} + +void KSim::LedLabel::drawLeds() +{ + bitBlt(this, d->sendPoint, &d->sendLed); + bitBlt(this, d->receivePoint, &d->receiveLed); +} + +void KSim::LedLabel::paintEvent(QPaintEvent *ev) +{ + KSim::Label::paintEvent(ev); + drawLeds(); + KSim::Progress::drawMeter(); +} + +void KSim::LedLabel::resizeEvent(QResizeEvent *ev) +{ + KSim::Progress::resizeEvent(ev); + layoutLeds(); +} + +void KSim::LedLabel::layoutLeds() +{ + int ledHeight = height() / 2; + + // get the location of the sendLed + d->sendPoint.setX((width() - d->sendLed.width()) - 2); + d->sendPoint.setY(ledHeight - (d->sendLed.height() / 2)); + + // get the location of the receiveLed + d->receivePoint.setX((d->sendPoint.x() - d->receiveLed.width()) - 3); + d->receivePoint.setY(ledHeight - (d->receiveLed.height() / 2)); + + QRect location = textLocation(); + location.setWidth(d->receivePoint.x()); + setTextLocation(location); + + QRect shadow = shadowLocation(); + shadow.setWidth(d->receivePoint.x() + 3); + setShadowLocation(shadow); + + setOrigin(rect()); +} + +void KSim::LedLabel::init() +{ + d = new Private; + d->receiveLed.setType(KSim::Led::First); + d->sendLed.setType(KSim::Led::Second); + setConfigString("StylePanel"); + configureObject(); +} diff --git a/ksim/library/led.h b/ksim/library/led.h new file mode 100644 index 0000000..2e5d084 --- /dev/null +++ b/ksim/library/led.h @@ -0,0 +1,193 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIM__LED_H +#define KSIM__LED_H + +#include "progress.h" +#include +#include + +namespace KSim +{ + /** + * A custom led for use with KSim::LedLabel, + * usually you shouldn't need to use this class, use KSim::LedLabel instead + * @see KSim::LedLabel + * + * @short led using gkrellm themes + * @author Robbie Ward + */ + class KDE_EXPORT Led : public QPixmap + { + public: + enum Type { First = 0, Second }; + Led(); + /** + * Constructs a KSim::Led. + * + * @param type is the led type + * @param ImageName is the image to display + * the image's height is divided by 4 and each item is used for send in, + * send out, receive in and receive out + * @param parent is the parent widget + * @param name is the object instance name + */ + Led(Type type, const QString &imageName); + /** + * destructor for KSim::Led. + */ + virtual ~Led(); + + /** + * sets the led on + */ + void setOn(bool force = false); + /** + * sets the led off + */ + void setOff(bool force = false); + /** + * toggles the current state of the led + */ + void toggle(); + /** + * sets the image of the led + */ + void setPixmap(const QString &); + /** + * @return the location of the filename + */ + const QString &fileName() const; + /** + * @return true if the led is on + */ + bool isOn() const; + /** + * sets the type of led, send or receive + */ + void setType(Type type); + /** + * @return the type of the led + */ + Type type() const; + /** + * Force the Led to repaint its state + */ + void update(); + + private: + class Private; + Private *d; + }; + + /** + * A custom widget that inheriits KSim::Progress. + * this wiget provides two KSim::Led's and a label + * + * @short Label widget with 2 leds + * @author Robbie Ward + */ + class KDE_EXPORT LedLabel : public KSim::Progress + { + Q_OBJECT + public: + /** + * Constructs a KSim::LedLabel. + * + * @param type is the theme type + * @param label is the default text to display + * @param parent is the parent widget + * @see KSim::ThemeLoader + */ + LedLabel(int max, int type, const QString &label, + QWidget *parent, const char *name = 0, WFlags fl = 0); + /** + * Constructs a KSim::LedLabel. + * + * @param type is the theme type + * @param label is the default text to display + * @param parent is the parent widget + * @see KSim::ThemeLoader + */ + LedLabel(int max, int type, QWidget *parent, + const char *name = 0, WFlags fl = 0); + /** + * Constructs a KSim::LedLabel. + * + * @param label is the default text to display + * @param parent is the parent widget + * @see KSim::ThemeLoader + */ + LedLabel(int max, QWidget *parent, + const char *name = 0, WFlags fl = 0); + /** + * destructor for KSim::LedLabel. + */ + virtual ~LedLabel(); + + /** + * reimplemented for internal reasons + */ + virtual void configureObject(bool reapaintWidget = true); + /** + * reimplemented for internal reasons + */ + virtual QSize sizeHint() const; + + public slots: + /** + * reimplemented for internal reasons + */ + virtual void reset(); + /** + * sets @ref ledType on + */ + void setOn(Led::Type type); + /** + * sets @ref ledType off + */ + void setOff(Led::Type type); + /** + * toggles the state of @ref ledType + * if the led is on then it will be set off, + * if the led is off it will be set on. + */ + void toggle(Led::Type type); + + protected: + void drawLeds(); + /** + * reimplemented for internal reasons + */ + virtual void paintEvent(QPaintEvent *); + /** + * reimplemented for internal reasons + */ + virtual void resizeEvent(QResizeEvent *); + + private: + void layoutLeds(); + void init(); + + class Private; + Private *d; + }; +} +#endif // KSIMLED_H diff --git a/ksim/library/pluginglobal.cpp b/ksim/library/pluginglobal.cpp new file mode 100644 index 0000000..02b32ad --- /dev/null +++ b/ksim/library/pluginglobal.cpp @@ -0,0 +1,207 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "pluginglobal.h" +#include "pluginmodule.h" + +#include +#include +#include +#include + +class KSim::Plugin::Private +{ + public: + Private() : plugin(0), + view(0), page(0) + { + oldState = true; + enabled = true; + // Set the ref-count to 1 + count = 1; + } + + ~Private() + { + kdDebug(2003) << "Deleting " << (plugin ? + plugin->name() : QString("Null")) + << " objects." << endl; + + // Remember to delete the objects we own + delete plugin; + delete view; + delete page; + + plugin = 0; + view = 0; + page = 0; + } + + void ref() { ++count; } + bool deref() { return !--count; } + + uint count; + QString name; + QPixmap icon; + QCString libName; + QString filename; + KSim::PluginObject *plugin; + KSim::PluginView *view; + KSim::PluginPage *page; + bool oldState; + bool enabled; +}; + +KSim::Plugin KSim::Plugin::null; + +// Null Plugin +KSim::Plugin::Plugin() : d(0) +{ +} + +KSim::Plugin::Plugin(KSim::PluginObject *plugin, const KDesktopFile &file) +{ + init(plugin, file); + + if (d) { + d->view = d->plugin ? d->plugin->createView(d->libName) : 0; + d->page = d->plugin ? d->plugin->createConfigPage(d->libName) : 0; + } +} + +KSim::Plugin::Plugin(const KSim::Plugin &rhs) +{ + d = rhs.d; + if (d) + d->ref(); +} + +KSim::Plugin::~Plugin() +{ + if (d && d->deref()) + delete d; +} + +KSim::Plugin &KSim::Plugin::operator=(const KSim::Plugin &rhs) +{ + if (*this == rhs) + return *this; + + if (rhs.d) { + rhs.d->ref(); + if (d && d->deref()) + delete d; + + d = rhs.d; + return *this; + } + + // rhs is a null plugin so we just go ahead + // and make this a null plugin too. + if (d && d->deref()) + delete d; + + d = 0; + return *this; +} + +bool KSim::Plugin::operator==(const KSim::Plugin &rhs) const +{ + return d == rhs.d; +} + +bool KSim::Plugin::operator!=(const KSim::Plugin &rhs) const +{ + return !(operator==(rhs)); +} + +void KSim::Plugin::setEnabled(bool enabled) +{ + if (!d) + return; + + d->oldState = d->enabled; + d->enabled = enabled; +} + +bool KSim::Plugin::isEnabled() const +{ + return (d ? d->enabled : false); +} + +bool KSim::Plugin::isDifferent() const +{ + return d ? d->enabled != d->oldState : false; +} + +bool KSim::Plugin::isNull() const +{ + return !d; +} + +const QString &KSim::Plugin::name() const +{ + return d ? d->name : QString::null; +} + +QPixmap KSim::Plugin::icon() const +{ + return d ? d->icon : QPixmap(); +} + +QCString KSim::Plugin::libName() const +{ + return d ? d->libName : QCString(); +} + +const QString &KSim::Plugin::fileName() const +{ + return d ? d->filename : QString::null; +} + +KSim::PluginObject *KSim::Plugin::plugin() const +{ + return d ? d->plugin : 0; +} + +KSim::PluginView *KSim::Plugin::view() const +{ + return d ? d->view : 0; +} + +KSim::PluginPage *KSim::Plugin::configPage() const +{ + return d ? d->page : 0; +} + +void KSim::Plugin::init(KSim::PluginObject *plugin, const KDesktopFile &file) +{ + if (!plugin || file.fileName().isEmpty()) { + d = 0; + return; + } + + d = new Private; + + d->libName = "ksim_" + file.readEntry("X-KSIM-LIBRARY").local8Bit(); + d->name = file.readName(); + d->icon = SmallIcon(file.readIcon()); + d->filename = file.fileName(); + d->plugin = plugin; +} diff --git a/ksim/library/pluginglobal.h b/ksim/library/pluginglobal.h new file mode 100644 index 0000000..85df9ce --- /dev/null +++ b/ksim/library/pluginglobal.h @@ -0,0 +1,161 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLUGINGLOBAL_H +#define PLUGINGLOBAL_H + +#include +#include +#include + +#include + +class KDesktopFile; + +namespace KSim +{ + class PluginObject; + class PluginView; + class PluginPage; + + /** + * A class that holds various information about a plugin + * @author Robbie Ward + */ + class KDE_EXPORT Plugin + { + public: + /** + * Constructs a null Plugin + */ + Plugin(); + /** + * Constructs a Plugin + */ + Plugin(KSim::PluginObject *plugin, const KDesktopFile &file); + /** + * Copy constructor + */ + Plugin(const Plugin &rhs); + /** + * Destructor for Plugin + */ + ~Plugin(); + + /** + * Assigns rhs to this Plugin and returns a reference to this Plugin. + */ + Plugin &operator=(const Plugin &rhs); + /** + * @return true if the plugin is equal to rhs; otherwise returns false + * @see #operator!= + */ + bool operator==(const Plugin &rhs) const; + /** + * @return true if the plugin is different to rhs; otherwise returns false + * @see #operator== + */ + bool operator!=(const Plugin &rhs) const; + /** + * sets if the plugin is enabled or not + */ + void setEnabled(bool enabled); + /** + * returns true if this plugin is enabled, else it returns false + */ + bool isEnabled() const; + /** + * returns true if the last enabled state is different to the current + * enabled state, else it returns false + */ + bool isDifferent() const; + /** + * @return true if the Plugin object is empty + */ + bool isNull() const; + /** + * @return the name of the plugin, NOT the library name + * @see #libName + */ + const QString &name() const; + /** + * @return the icon of the plugin + */ + QPixmap icon() const; + /** + * @return library name of the plugin + */ + QCString libName() const; + /** + * @return path to the .desktop file + */ + const QString &fileName() const; + /** + * @return the plugin object + */ + KSim::PluginObject *plugin() const; + /** + * @return the view object of the plugin + */ + KSim::PluginView *view() const; + /** + * @return the config object of the plugin + */ + KSim::PluginPage *configPage() const; + /** + * a null plugin, provided for convenience. + * currently only used in KSim::PluginLoader + */ + static KSim::Plugin null; + private: + void init(KSim::PluginObject *plugin, const KDesktopFile &file); + + class Private; + Private *d; + }; + + /** + * Please do not use this class directly, + * use pluginList() from KSim::PluginLoader instead + * @author Robbie Ward + */ + class KDE_EXPORT PluginList : public QValueList + { + public: + /** + * constructs a null list + */ + PluginList() : QValueList() {} + /** + * constructs a copy of @p list + */ + PluginList(const PluginList &list) : QValueList(list) {} + /** + * constructs a copy of @p list + */ + PluginList(const QValueList &list) + : QValueList(list) {} + /** + * constructs a list with just one item + */ + PluginList(const Plugin &plugin) { append(plugin); } + ~PluginList() {} + }; +} +#endif diff --git a/ksim/library/pluginloader.cpp b/ksim/library/pluginloader.cpp new file mode 100644 index 0000000..be2d2bf --- /dev/null +++ b/ksim/library/pluginloader.cpp @@ -0,0 +1,326 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "pluginloader.h" +#include "pluginloader.moc" + +#include +#include +#include +#include +#include +#include +#include + +#include + +class KSim::PluginInfo::Private +{ + public: +}; + +KSim::PluginInfo::~PluginInfo() +{ +} + +const QString &KSim::PluginInfo::name() const +{ + return m_name; +} + +QCString KSim::PluginInfo::libName(bool includePrefix) const +{ + return (includePrefix ? "ksim_" + m_libName : m_libName); +} + +const QString &KSim::PluginInfo::location() const +{ + return m_location; +} + +KSim::PluginInfo::PluginInfo() +{ +} + +class KSim::PluginLoader::Private +{ + public: + typedef KSim::PluginObject *(PluginPtr)(const char *); + KSim::PluginList pluginList; + QString error; + QString lib; + bool lastLoaded; + static const char *const ksimString; +}; + +const char *const KSim::PluginLoader::Private::ksimString = "ksim_"; + +KSim::PluginLoader *KSim::PluginLoader::m_instance = 0; // initialize pointer +KSim::PluginLoader &KSim::PluginLoader::self() +{ + if (!m_instance) // is it the first call? + m_instance = new PluginLoader; // create sole instance + + return *m_instance; // address of sole instance +} + +KSim::PluginLoader::~PluginLoader() +{ + unloadAllPlugins(); + delete d; +} + +bool KSim::PluginLoader::loadPlugin(const KDesktopFile &file) +{ + switch (createPlugin(file)) { + case KSim::PluginLoader::EmptyLibName: + KMessageBox::error(0, i18n("KSim was unable to load the plugin %1" + " due to the X-KSIM-LIBRARY property being empty in the" + " plugins desktop file").arg(file.readName())); + return false; + break; + case KSim::PluginLoader::LibNotFound: + KMessageBox::error(0, i18n("KSim was unable to load the plugin %1" + " due to not being able to find the plugin, check that the plugin" + " is installed and is in your $KDEDIR/lib path").arg(file.readName())); + return false; + break; + case KSim::PluginLoader::UnSymbols: + KMessageBox::error(0, i18n("An error occurred while trying \n" + "to load the plugin '%1'. \nThis could be caused by the" + " following:
      \n
    • The plugin doesn't have the %2" + " macro
    • \n
    • The plugin has been damaged or has" + " some unresolved symbols
    • \n
    \nLast" + " error message that occurred: \n%3
    ") + .arg(d->lib.prepend("ksim_")).arg("KSIM_INIT_PLUGIN") + .arg(d->error)); + return false; + break; + default: + break; + } + + return true; +} + +bool KSim::PluginLoader::unloadPlugin(const QCString &name) +{ + if (name.isEmpty()) + return false; + + // see if our plugin is loaded + KSim::Plugin plugin = find(name); + if (plugin.isNull()) + return false; + + // try to unload the library + kdDebug(2003) << "Unloading plugin " << plugin.libName() << endl; + KLibLoader::self()->unloadLibrary(plugin.libName()); + d->pluginList.remove(plugin); + return true; +} + +void KSim::PluginLoader::unloadAllPlugins() +{ + kdDebug(2003) << "Unloading all plugins" << endl; + + // Go through the plugin list and unload each plugin; + KSim::PluginList::ConstIterator it; + for (it = d->pluginList.begin(); it != d->pluginList.end(); ++it) { + KLibLoader::self()->unloadLibrary((*it).libName()); + } + + // Clear the plugin list; + d->pluginList.clear(); + KLibLoader::cleanUp(); +} + +bool KSim::PluginLoader::isLoaded(const KSim::Plugin &info) const +{ + return isLoaded(info.libName()); +} + +bool KSim::PluginLoader::isLoaded(const QCString &library) const +{ + if (library.isEmpty()) + return false; + + return !find(library).isNull(); +} + +KSim::PluginInfo KSim::PluginLoader::findPluginInfo(const QString &name, + SearchType type) const +{ + QString location; + + switch (type) { + case Name: { + QStringList files = KGlobal::dirs()->findAllResources("data", "ksim/monitors/*.desktop"); + QStringList::ConstIterator it; + for (it = files.begin(); it != files.end(); ++it) { + KDesktopFile file((*it)); + if (file.readName() == name) { + location = (*it); + break; + } + } + break; + } + case LibName: { + QStringList files = KGlobal::dirs()->findAllResources("data", "ksim/monitors/*.desktop"); + QStringList::ConstIterator it; + for (it = files.begin(); it != files.end(); ++it) { + KDesktopFile file((*it)); + if (file.readEntry("X-KSIM-LIBRARY") == name) { + location = (*it); + break; + } + } + break; + } + case DesktopFile: { + if (!KDesktopFile::isDesktopFile(name)) + return KSim::PluginInfo(); + + location = name; + break; + } + } + + KDesktopFile file(location); + KSim::PluginInfo info; + info.m_name = file.readName(); + info.m_libName = file.readEntry("X-KSIM-LIBRARY").local8Bit(); + info.m_location = location; + return info; +} + +KSim::Plugin &KSim::PluginLoader::find(const QCString &libName) +{ + if (libName.isEmpty()) + return KSim::Plugin::null; + + QCString library(libName); + if (libName.find(Private::ksimString) == -1) + library.prepend(Private::ksimString); + + KSim::PluginList::Iterator it; + for (it = d->pluginList.begin(); it != d->pluginList.end(); ++it) { + if ((*it).libName() == library) + return (*it); + } + + return KSim::Plugin::null; +} + +const KSim::Plugin &KSim::PluginLoader::find(const QCString &libName) const +{ + if (libName.isEmpty()) + return KSim::Plugin::null; + + QCString library(libName); + if (libName.find(Private::ksimString) == -1) + library.prepend(Private::ksimString); + + KSim::PluginList::ConstIterator it; + for (it = d->pluginList.begin(); it != d->pluginList.end(); ++it) { + if ((*it).libName() == library) + return (*it); + } + + return KSim::Plugin::null; +} + +KSim::Plugin &KSim::PluginLoader::find(const KSim::PluginInfo &info) +{ + return find(info.libName()); +} + +const KSim::Plugin &KSim::PluginLoader::find(const KSim::PluginInfo &info) const +{ + return find(info.libName()); +} + +const KSim::PluginList &KSim::PluginLoader::pluginList() const +{ + return d->pluginList; +} + +KSim::PluginList &KSim::PluginLoader::pluginList() +{ + return d->pluginList; +} + +const KSim::Plugin &KSim::PluginLoader::plugin() const +{ + return (d->lastLoaded ? d->pluginList.last() : KSim::Plugin::null); +} + +KSim::Plugin &KSim::PluginLoader::plugin() +{ + return (d->lastLoaded ? d->pluginList.last() : KSim::Plugin::null); +} + +KSim::PluginLoader::PluginLoader() : QObject(0, "PluginLoader") +{ + d = new KSim::PluginLoader::Private; + d->lastLoaded = false; +} + +void KSim::PluginLoader::cleanup() +{ + if (!m_instance) + return; + + delete m_instance; + m_instance = 0; +} + +KSim::PluginLoader::ErrorCode KSim::PluginLoader::createPlugin(const KDesktopFile &file) +{ + d->error = QString::null; + QCString pluginName(file.readEntry("X-KSIM-LIBRARY").local8Bit()); + if (pluginName.isEmpty()) + return EmptyLibName; + + QCString libName(Private::ksimString + pluginName); + KLibrary *library = KLibLoader::self()->library(libName); + if (!library) + return LibNotFound; + + QCString symbol("init_plugin"); + if (Private::PluginPtr *create = (Private::PluginPtr *)(library->symbol(symbol))) { + d->pluginList.append(KSim::Plugin(create(pluginName), file)); + d->lib = QString::null; + d->lastLoaded = true; + } + else { + d->error = KLibLoader::self()->lastErrorMessage().isEmpty() ? + i18n("Unable to get last error message") : + KLibLoader::self()->lastErrorMessage(); + + KLibLoader::self()->unloadLibrary(libName); + d->lib = pluginName; + d->lastLoaded = false; + return UnSymbols; + } + + emit pluginLoaded(d->pluginList.last()); + return LibLoaded; +} diff --git a/ksim/library/pluginloader.h b/ksim/library/pluginloader.h new file mode 100644 index 0000000..f101973 --- /dev/null +++ b/ksim/library/pluginloader.h @@ -0,0 +1,183 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLUGINLOADER_H +#define PLUGINLOADER_H + +#include "pluginglobal.h" +#include + +#include + +namespace KSim +{ + class KDE_EXPORT PluginInfo + { + friend class PluginLoader; + public: + ~PluginInfo(); + + /** + * @return the name of the plugin + */ + const QString &name() const; + /** + * @return the library name of the plugin + */ + QCString libName(bool includePrefix = false) const; + /** + * @return the location of the desktop file + */ + const QString &location() const; + + private: + PluginInfo(); + + QString m_name; + QString m_location; + QCString m_libName; + + class Private; + Private *d; + }; + + /** + * Provides a loader for the plugins + * @author Robbie Ward + */ + class KDE_EXPORT PluginLoader : public QObject + { + Q_OBJECT + friend class MainView; + public: + enum SearchType { Name = 0, DesktopFile, LibName }; + enum ErrorCode { EmptyLibName = -3, LibNotFound = -2, + UnSymbols = -1, LibLoaded = 0 }; + + /** + * @return a reference to the instance + */ + static PluginLoader &self(); + /** + * loads a plugin, example: + *
    +       *   KDesktopFile deskfile("/home/user/foo.desktop");
    +       *   KSim::PluginLoader::self().loadPlugin(deskFile);
    +       * 
    + * you can then use @ref pluginList() to access the plugin, view, + * config page and plugin information + * @param file is the desktop file of the lib + * @return true if the plugin is successfully loaded + */ + bool loadPlugin(const KDesktopFile &file); + /** + * unloads a loaded plugin and removes plugin entries from pluginList() + */ + bool unloadPlugin(const QCString &name); + /** + * unloads all loaded plugins + */ + void unloadAllPlugins(); + /** + * convenience function + * + * returns true if info is loaded + */ + bool isLoaded(const KSim::Plugin &info) const; + /** + * returns true if library is loaded + */ + bool isLoaded(const QCString &library) const; + /** + * finds the plugins desktopfile and returns information + * on the plugin + * @return a KSim::PluginInfo object + * @see KSim::PluginInfo + */ + KSim::PluginInfo findPluginInfo(const QString &name, + SearchType type = DesktopFile) const; + /** + * looks through the list of loaded plugins and returns + * the one that matches libName, or returns + * KSim::Plugin::null if a plugin could not be found. + * + * if libName does not start with "ksim_" then the function + * will prepend this automatically. + * @return a KSim::Plugin object + * @see KSim::Plugin + */ + KSim::Plugin &find(const QCString &libName); + /** + * convenience function, see the above function for details. + */ + const KSim::Plugin &find(const QCString &libName) const; + /** + * equivalent to find(info.libName()); + */ + KSim::Plugin &find(const KSim::PluginInfo &info); + /** + * convenience function, see the above function for details. + */ + const KSim::Plugin &find(const KSim::PluginInfo &info) const; + /** + * provides plugin(), view(), config page and plugin information + * @see KSim::Plugin KSim::PluginList + */ + const KSim::PluginList &pluginList() const; + /** + * Overloaded member function, This behaves essentially like + * the above function + */ + KSim::PluginList &pluginList(); + /** + * @return a reference to the last plugin loaded (or a null plugin + * if the plugin was unable to load) + */ + const KSim::Plugin &plugin() const; + /** + * Overloaded member function, This behaves essentially like + * the above function + */ + KSim::Plugin &plugin(); + + signals: + void pluginLoaded(const KSim::Plugin &); + + protected: + /** + * constructor for PluginLoader, use self() to get an instance + */ + PluginLoader(); + ~PluginLoader(); + + private: + PluginLoader(const PluginLoader &); + PluginLoader &operator=(const PluginLoader &); + /** + * Deletes the instance and cleans up after itself + */ + static void cleanup(); + ErrorCode createPlugin(const KDesktopFile &file); + + class Private; + Private *d; + static PluginLoader *m_instance; + }; +} +#endif diff --git a/ksim/library/pluginmodule.cpp b/ksim/library/pluginmodule.cpp new file mode 100644 index 0000000..f267197 --- /dev/null +++ b/ksim/library/pluginmodule.cpp @@ -0,0 +1,174 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "pluginmodule.h" +#include "pluginmodule.moc" + +#include +#include +#include +#include +#include +#include +#include + + +class KSim::PluginObject::Private +{ + public: + QCString name; + QString configName; +}; + +KSim::PluginObject::PluginObject(const QCString &name) +{ + d = new PluginObject::Private; + d->name = name; + d->configName = "ksim_" + name; +} + +KSim::PluginObject::~PluginObject() +{ + delete d; +} + +const char *KSim::PluginObject::instanceName() const +{ + return kapp->aboutData()->appName(); +} + +const QCString &KSim::PluginObject::name() const +{ + return d->name; +} + +void KSim::PluginObject::setConfigFileName(const QString &name) +{ + if (d->configName == name) + return; + + d->configName = name; + if (name.find("ksim") == -1) + d->configName.prepend("ksim_"); +} + +const QString &KSim::PluginObject::configFileName() const +{ + return d->configName; +} + +class KSim::PluginPage::Private +{ + public: + KConfig *config; + KSim::PluginObject *parent; +}; + +KSim::PluginPage::PluginPage(KSim::PluginObject *parent, const char *name) + : QWidget(0, name) +{ + d = new PluginPage::Private; + d->parent = parent; + if (parent && !parent->configFileName().isEmpty()) + d->config = new KConfig(parent->configFileName() + "rc"); + else { + kdWarning() << className() << ": Can not create the config() " + "pointer due to the parent being null" << endl; + d->config = 0; + } +} + +KSim::PluginPage::~PluginPage() +{ + delete d->config; + delete d; +} + +KConfig *KSim::PluginPage::config() const +{ + if (d) + return d->config; + else + return 0; +} + +class KSim::PluginView::Private +{ + public: + PluginObject *parent; + QPopupMenu *popupMenu; + KConfig *config; +}; + +KSim::PluginView::PluginView(KSim::PluginObject *parent, const char *name) + : QWidget(0, name) +{ + d = new PluginView::Private; + d->parent = parent; + d->popupMenu = new QPopupMenu(this); + d->popupMenu->insertItem(i18n("About"), this, + SLOT(showAbout()), 0, -1, 0); + + if (parent && !parent->configFileName().isEmpty()) + d->config = new KConfig(parent->configFileName() + "rc"); + else { + kdWarning() << className() << ": Can not create the config() " + "pointer due to the parent being null" << endl; + d->config = 0; + } +} + +KSim::PluginView::~PluginView() +{ + delete d->popupMenu; + delete d->config; + delete d; + d = 0; +} + +KConfig *KSim::PluginView::config() const +{ + return d->config; +} + +QPopupMenu *KSim::PluginView::menu() const +{ + return d->popupMenu; +} + +void KSim::PluginView::doCommand() +{ + emit runCommand(name()); +} + +void KSim::PluginView::mousePressEvent(QMouseEvent *ev) +{ + if (ev->button() == QMouseEvent::LeftButton) + doCommand(); +} + +KSim::PluginObject *KSim::PluginView::parentPlugin() const +{ + return d->parent; +} + +void KSim::PluginView::showAbout() +{ + parentPlugin()->showAbout(); +} diff --git a/ksim/library/pluginmodule.h b/ksim/library/pluginmodule.h new file mode 100644 index 0000000..1cc6a1c --- /dev/null +++ b/ksim/library/pluginmodule.h @@ -0,0 +1,205 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLUGINMODULE_H +#define PLUGINMODULE_H + +#include + +#include + +class QPopupMenu; +class KConfig; + +#define KSIM_INIT_PLUGIN(className) \ +extern "C" { \ + KDE_EXPORT KSim::PluginObject *init_plugin(const char *name) { \ + return new className(name); \ + } \ +} + +namespace KSim +{ + class PluginView; + class PluginPage; + + /** + * The base class for ksim modules. + * + * To init a plugin so KSim can load your plugin just do: + *
    +   *   // MyPluginModule is the class that inherits KSim::PluginObject
    +   *   KSIM_INIT_PLUGIN(MyPluginModule);
    +   * 
    + * @see KSim::PluginView KSim::PluginPage + * @author Robbie Ward + */ + class KDE_EXPORT PluginObject + { + public: + /** + * constructor for PluginObject + */ + PluginObject(const QCString &name); + /** + * destructor for PluginObject + */ + virtual ~PluginObject(); + + /** + * creates a new View page, re-implement this + * to return your main view class + */ + virtual KSim::PluginView *createView(const char *) = 0; + /** + * creates a new Config page, re-implement this + * to return you config class + */ + virtual KSim::PluginPage *createConfigPage(const char *) = 0; + /** + * re-implement this to show your about dialog + */ + virtual void showAbout() = 0; + /** + * @return the instance name of the app + */ + const char *instanceName() const; + /** + * @return the name of the plugin + */ + const QCString &name() const; + /** + * sets the configuration file name to @p name + */ + void setConfigFileName(const QString &name); + /** + * @return the config filename the plugin should use + * or name() if the filename hasn't been set + */ + const QString &configFileName() const; + + private: + PluginObject(); + PluginObject(const PluginObject &); + PluginObject &operator=(const PluginObject &); + + class Private; + Private *d; + }; + + /** + * Provides you with a config page + * + * re-implement readConfig() and saveConfig() for your + * classes reading and saving functions and use + * the config() to gain access to your config file + * @author Robbie Ward + */ + class KDE_EXPORT PluginPage : public QWidget + { + Q_OBJECT + public: + /** + * constructor for PluginPage + */ + PluginPage(KSim::PluginObject *parent, const char *name); + /** + * destructor for PluginPage + */ + virtual ~PluginPage(); + + /** + * called when apply or ok button is clicked in KSimPref + * use this to save your plugin options + */ + virtual void saveConfig() = 0; + /** + * called when apply or ok button is clicked in KSimPref + * use this to read your plugin options + */ + virtual void readConfig() = 0; + /* + * use this to get a config object unique to the plugin name, + * eg: the plugin foo would have the config file foorc + */ + KConfig *config() const; + + signals: + void pageChanged(); + + protected: + PluginObject *parentPlugin() const; + + private: + class Private; + Private *d; + }; + + /** + * inherit from this class to get your base view + * + * use config() to get an instance of your config file, + * reimplement reparseConfig() to recreate your view + * when apply or ok gets clicked in the config dialog + * @author Robbie Ward + */ + class KDE_EXPORT PluginView : public QWidget + { + Q_OBJECT + public: + /** + * constructor for PluginView + */ + PluginView(KSim::PluginObject *parent, const char *name); + /** + * destructor for PluginView + */ + virtual ~PluginView(); + + /* + * use this to get a config object unique to the plugin name, + * eg: the plugin foo would have the config file foorc + */ + KConfig *config() const; + /** + * the plugins popup menu + */ + QPopupMenu *menu() const; + /** + * reimplement to recreate your view when KSim requests this + */ + virtual void reparseConfig() = 0; + void doCommand(); + + signals: + void runCommand(const QCString &); + + protected: + virtual void mousePressEvent(QMouseEvent *); + PluginObject *parentPlugin() const; + + private slots: + void showAbout(); + + private: + class Private; + Private *d; + }; +} +#endif diff --git a/ksim/library/progress.cpp b/ksim/library/progress.cpp new file mode 100644 index 0000000..fd923d2 --- /dev/null +++ b/ksim/library/progress.cpp @@ -0,0 +1,231 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "progress.h" +#include "progress.moc" + +#include +#include +#include +#include + +#include + +class KSim::Progress::Private +{ + public: + QPixmap meterPixmap; + QRect rectOrigin; + ProgressType type; + int krellDepth; + int value; + int minValue; + int maxValue; +}; + +KSim::Progress::Progress(int maxValue, + QWidget *parent, const char *name, + WFlags fl) : KSim::Label(parent, name, fl) +{ + init(maxValue); + configureObject(); +} + +KSim::Progress::Progress(int maxValue, + int type, const QString &label, QWidget *parent, + const char *name, WFlags fl) + : KSim::Label(type, label, parent, name, fl) +{ + init(maxValue); + configureObject(); +} + +KSim::Progress::Progress(int maxValue, + int type, const QString &label, int value, + QWidget *parent, const char *name, WFlags fl) + : KSim::Label(type, label, parent, name, fl) +{ + init(maxValue, value); + configureObject(); +} + +KSim::Progress::Progress(int maxValue, + int type, QWidget *parent, + const char *name, WFlags fl) + : KSim::Label(type, parent, name, fl) +{ + init(maxValue); + configureObject(); +} + +KSim::Progress::Progress(int maxValue, int type, + ProgressType progressType, + QWidget *parent, const char *name, WFlags fl) + : KSim::Label(type, parent, name, fl) +{ + init(maxValue, 0, progressType); + configureObject(); +} + +KSim::Progress::~Progress() +{ + delete d; +} + +int KSim::Progress::value() const +{ + return d->value; +} + +int KSim::Progress::minValue() const +{ + return d->minValue; +} + +int KSim::Progress::maxValue() const +{ + return d->maxValue; +} + +const QRect &KSim::Progress::rectOrigin() const +{ + return d->rectOrigin; +} + +void KSim::Progress::configureObject(bool repaintWidget) +{ + KSim::Label::configureObject(false); + + if (d->type == Panel) { + setMeterPixmap(themeLoader().current().splitPixmap(KSim::Theme::KrellPanel)); + setThemePixmap(themeLoader().current().panelPixmap(type())); + } + else { + setMeterPixmap(themeLoader().current().splitPixmap(KSim::Theme::KrellMeter)); + } + + if (repaintWidget) + update(); +} + +QSize KSim::Progress::sizeHint() const +{ + QSize hint(Label::sizeHint()); + + if (d->meterPixmap.height() > hint.height()) + hint.setHeight(d->meterPixmap.height()); + + return hint; +} + +void KSim::Progress::reset() +{ + KSim::Label::clear(); + setMinValue(0); + setMaxValue(0); + setValue(0); +} + +void KSim::Progress::setValue(int value) +{ + if (value == d->value) + return; + + d->value = value; + if (value < minValue()) + d->value = minValue(); + + if (value > maxValue()) + d->value = maxValue(); + + update(); +} + +void KSim::Progress::setMinValue(int minValue) +{ + if (d->minValue == minValue) + return; + + if (!(minValue > maxValue())) { + d->minValue = minValue; + update(); + } +} + +void KSim::Progress::setMaxValue(int maxValue) +{ + if (d->maxValue == maxValue) + return; + + if (!(maxValue < minValue())) { + d->maxValue = maxValue; + update(); + } +} + +void KSim::Progress::setOrigin(const QRect &origin) +{ + d->rectOrigin = origin; +} + +void KSim::Progress::setMeterPixmap(const QPixmap &pixmap) +{ + QSize oldSize = sizeHint(); + d->meterPixmap = pixmap; + relayoutLabel(oldSize); +} + +int KSim::Progress::xLocation() const +{ + int position = d->rectOrigin.width() - d->meterPixmap.width(); + int rangePos = maxValue() - minValue(); + int valuePos = value() - minValue(); + + int returnValue = 0; + if (rangePos) + returnValue = position * valuePos / rangePos; + + return returnValue; +} + +void KSim::Progress::paintEvent(QPaintEvent *ev) +{ + KSim::Label::paintEvent(ev); + drawMeter(); +} + +void KSim::Progress::resizeEvent(QResizeEvent *ev) +{ + KSim::Label::resizeEvent(ev); + setOrigin(rect()); +} + +void KSim::Progress::drawMeter() +{ + bitBlt(this, xLocation(), 2, &d->meterPixmap); +} + +void KSim::Progress::init(int maxValue, int value, ProgressType type) +{ + d = new Private; + d->type = type; + d->value = d->minValue = 0; + d->maxValue = maxValue; + setValue(value); +} diff --git a/ksim/library/progress.h b/ksim/library/progress.h new file mode 100644 index 0000000..570894a --- /dev/null +++ b/ksim/library/progress.h @@ -0,0 +1,181 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIM__PROGRESS_H +#define KSIM__PROGRESS_H + +#include "label.h" + +#include + +namespace KSim +{ + /** + * provides a label with a progress bar meter + * @author Robbie Ward + */ + class KDE_EXPORT Progress : public KSim::Label + { + Q_OBJECT + public: + enum ProgressType { Panel, Meter }; + /** + * constructs a KSim::Progress + * + * @param maxValue is the maximum value + * that the progress bar will show + * @param label is the text that will be displayed + * @param parent is the parent widget + */ + Progress(int maxValue, QWidget *parent, + const char *name = 0, WFlags fl = 0); + /** + * constructs a KSim::Progress + * + * @param maxValue is the maximum value + * that the progress bar will show + * @param type is the theme type + * @param label is the text that will be displayed + * @param parent is the parent widget + */ + Progress(int maxValue, int type, const QString &label, + QWidget *parent, const char *name = 0, WFlags fl = 0); + /** + * constructs a KSim::Progress + * + * @param maxValue is the maximum value + * that the progress bar will show + * @param type is the theme type + * @param label is the text that will be displayed + * @param value is the initial value to be displayed + * @param parent is the parent widget + */ + Progress(int maxValue, int type, const QString &label, + int value, QWidget *parent, const char *name = 0, + WFlags fl = 0); + /** + * constructs a KSim::Progress + * + * @param maxValue is the maximum value + * that the progress bar will show + * @param type is the theme type + * @param parent is the parent widget + */ + Progress(int maxValue, int type, QWidget *parent, + const char *name = 0, WFlags fl = 0); + /** + * constructs a KSim::Progress + * + * @param maxValue is the maximum value + * that the progress bar will show + * @param type is the theme type + * @param progressType is onr of Progress::ProgressType + * @param parent is the parent widget + */ + Progress(int maxValue, int type, + ProgressType progressType, + QWidget *parent, const char *name = 0, + WFlags fl = 0); + /** + * destructs KSim::Chart + */ + virtual ~Progress(); + + /** + * @return the current value + */ + int value() const; + /** + * @return the minimum value + */ + int minValue() const; + /** + * @return the maximum value + */ + int maxValue() const; + + /** + * @return the area that the progress meter will be drawn + */ + const QRect &rectOrigin() const; + /** + * reimplemented for internal reasons + */ + virtual void configureObject(bool repaintWidget = true); + /** + * reimplemented for internal reasons + */ + virtual QSize sizeHint() const; + + public slots: + /** + * calls KSim::Label::clear() and resets the value(), + * maxValue() and minValue() to 0 + */ + virtual void reset(); + /** + * sets the current value the progress bar will display + */ + void setValue(int); + /** + * sets the minimum value the progress bar will display + */ + void setMinValue(int); + /** + * sets the maximum value the progress bar will display + */ + void setMaxValue(int); + + protected: + /** + * sets the area that the progess bar will be drawn + */ + void setOrigin(const QRect &); + /** + * sets the progress bar pixmap + */ + void setMeterPixmap(const QPixmap &); + /** + * @return the pixel position where the meter should be drawn + */ + int xLocation() const; + /** + * reimplemented for internal reasons + */ + virtual void paintEvent(QPaintEvent *); + /** + * reimplemented for internal reasons + */ + virtual void resizeEvent(QResizeEvent *); + /** + * paints the meter image onto the widget + */ + void drawMeter(); + + private: + /** + * inits the widget + */ + void init(int, int = 0, ProgressType = Meter); + + class Private; + Private *d; + }; +} +#endif diff --git a/ksim/library/themeloader.cpp b/ksim/library/themeloader.cpp new file mode 100644 index 0000000..7c42dcd --- /dev/null +++ b/ksim/library/themeloader.cpp @@ -0,0 +1,1266 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "themeloader.h" +#include +#include "themetypes.h" +#include "common.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class KSim::Theme::Private +{ + public: + Private(const QValueVector &names, + const QStringList &list) : fileNames(names), + imageTypes(list) {} + + QStringList file; + QStringList dFile; + KConfig *globalReader; + QString altTheme; + QString location; + const QValueVector &fileNames; + const QStringList &imageTypes; + int alternative; + int font; + bool recolour; + + QString readOption(const QString &entry, + bool useGlobal = true, + const QString &defValue = QString::null) + { + QString text; + QStringList::ConstIterator it; + for (it = file.begin(); it != file.end(); ++it) { + if ((*it).find(entry) != -1) { + text = QStringList::split("=", (*it))[1].stripWhiteSpace(); + } + } + + if (!text.isEmpty() || dFile.isEmpty()) + return text; + + QStringList::ConstIterator it2; + for (it2 = dFile.begin(); it2 != dFile.end(); ++it) { + if ((*it2).find(entry) != -1) { + text = QStringList::split("=", (*it2))[1].stripWhiteSpace(); + } + } + + if (!text.isEmpty()) + return text; + + if (!globalReader || !useGlobal) + return defValue; + + text = globalReader->readEntry(entry, defValue); + return text; + } +}; + +class KSim::ThemeLoader::Private +{ + public: + QValueVector fileNames; + QStringList imageTypes; + KConfig *globalReader; + bool recolour; + QColor pixelColour; +}; + +bool KSim::Theme::operator==(const KSim::Theme &rhs) const +{ + return d == rhs.d; +} + +bool KSim::Theme::operator!=(const KSim::Theme &rhs) const +{ + return !(operator==(rhs)); +} + +KSim::Theme &KSim::Theme::operator=(const KSim::Theme &rhs) +{ + if (*this == rhs) + return *this; + + delete d; + d = rhs.d; + return *this; +} + +KSim::Theme::~Theme() +{ + delete d; +} + +const QString &KSim::Theme::path() const +{ + return d->location; +} + +QString KSim::Theme::name() const +{ + QString name = d->location; + if (name.endsWith("/")) + name.remove(name.length() - 1, 1); + + return name.remove(0, name.findRev("/") + 1); +} + +QString KSim::Theme::author() const +{ + QString author(d->readOption("author", false)); + return author.replace(QRegExp("\""), QString::null); +} + +int KSim::Theme::fontItem() const +{ + return d->font; +} + +int KSim::Theme::alternative() const +{ + return d->alternative; +} + +int KSim::Theme::alternatives() const +{ + return d->readOption("theme_alternatives").toInt(); +} + +int KSim::Theme::chartWidthRef(int defValue) const +{ + return internalNumEntry("chart_width_ref", defValue); +} + +int KSim::Theme::chartWidthMin(int defValue) const +{ + return internalNumEntry("chart_width_min", defValue); +} + +bool KSim::Theme::scaling(bool defValue) const +{ + return internalNumEntry("allow_scaling", defValue); +} + +int KSim::Theme::frameTopHeight(int defValue) const +{ + return KMIN(2, internalNumEntry("frame_top_height", defValue)); +} + +int KSim::Theme::frameBottomHeight(int defValue) const +{ + return KMIN(2, internalNumEntry("frame_bottom_height", defValue)); +} + +int KSim::Theme::frameLeftWidth(int defValue) const +{ + return KMIN(2, internalNumEntry("frame_left_width", defValue)); +} + +int KSim::Theme::frameRightWidth(int defValue) const +{ + return KMIN(2, internalNumEntry("frame_right_width", defValue)); +} + +QRect KSim::Theme::frameTopBorder(const QRect &defValue) const +{ + return internalRectEntry("frame_top_border", defValue); +} + +QRect KSim::Theme::frameBottomBorder(const QRect &defValue) const +{ + return internalRectEntry("frame_bottom_border", defValue); +} + +QRect KSim::Theme::frameLeftBorder(const QRect &defValue) const +{ + return internalRectEntry("frame_left_border", defValue); +} + +QRect KSim::Theme::frameRightBorder(const QRect &defValue) const +{ + return internalRectEntry("frame_right_border", defValue); +} + +QColor KSim::Theme::chartInColour(const QColor &defValue) const +{ + if (d->recolour) + return QApplication::palette().active().background(); + + return internalColourEntry("chart_in_color", defValue); +} + +QColor KSim::Theme::chartInColourGrid(const QColor &defValue) const +{ + return internalColourEntry("chart_in_color_grid", defValue); +} + +QColor KSim::Theme::chartOutColour(const QColor &defValue) const +{ + if (d->recolour) + return QApplication::palette().active().background(); + + return internalColourEntry("chart_out_color", defValue); +} + +QColor KSim::Theme::chartOutColourGrid(const QColor &defValue) const +{ + return internalColourEntry("chart_out_color_grid", defValue); +} + +bool KSim::Theme::bgGridMode(bool defValue) const +{ + return internalNumEntry("bg_grid_mode", defValue); +} + +int KSim::Theme::rxLedX(int defValue) const +{ + return internalNumEntry("rx_led_x", defValue); +} + +int KSim::Theme::rxLedY(int defValue) const +{ + return internalNumEntry("rx_led_y", defValue); +} + +int KSim::Theme::txLedX(int defValue) const +{ + return internalNumEntry("tx_led_x", defValue); +} + +int KSim::Theme::txLedY(int defValue) const +{ + return internalNumEntry("tx_led_y", defValue); +} + +int KSim::Theme::mailFrames(int defValue) const +{ + return internalNumEntry("decal_mail_frames", defValue); +} + +int KSim::Theme::mailDelay(int defValue) const +{ + return internalNumEntry("decal_mail_delay", defValue); +} + +int KSim::Theme::krellSliderDepth(int defValue) const +{ + return internalNumEntry("krell_slider_depth", defValue); +} + +int KSim::Theme::krellSliderXHot(int defValue) const +{ + return internalNumEntry("krell_slider_x_hot", defValue); +} + +QRect KSim::Theme::sliderPanel(const QRect &defValue) const +{ + return internalRectEntry("bg_slider_panel_border", defValue); +} + +QRect KSim::Theme::sliderMeter(const QRect &defValue) const +{ + return internalRectEntry("bg_slider_meter_border", defValue); +} + +QRect KSim::Theme::timerBorder(const QRect &defValue) const +{ + return internalRectEntry("bg_timer_border", defValue); +} + +QRect KSim::Theme::buttonPanelBorder(const QRect &defValue) const +{ + return internalRectEntry("button_panel_border", defValue); +} + +QRect KSim::Theme::buttonMeterBorder(const QRect &defValue) const +{ + return internalRectEntry("button_meter_border", defValue); +} + +QFont KSim::Theme::largeFont() const +{ + QString font(internalStringEntry("large_font", QString::null)); + + if (font.isEmpty()) + return QApplication::font(); + + QFont themeFont; + themeFont.setRawName(font.replace(QRegExp("\""), QString::null)); + return themeFont; +} + +QFont KSim::Theme::normalFont() const +{ + QString font(internalStringEntry("normal_font", QString::null)); + + if (font.isEmpty()) + return QApplication::font(); + + QFont themeFont; + themeFont.setRawName(font.replace(QRegExp("\""), QString::null)); + return themeFont; +} + +QFont KSim::Theme::smallFont() const +{ + QString font(internalStringEntry("small_font", QString::null)); + + if (font.isEmpty()) + return QApplication::font(); + + QFont themeFont; + themeFont.setRawName(font.replace(QRegExp("\""), QString::null)); + return themeFont; +} + +QFont KSim::Theme::currentFont() const +{ + switch (fontItem()) { + case 0: + return smallFont(); + break; + case 1: + return normalFont(); + break; + case 2: + return largeFont(); + break; + case 3: + return KSim::ThemeLoader::currentFont(); + break; + case 4: + return KGlobalSettings::generalFont(); + break; + } + + return QFont(); +} + +QString KSim::Theme::meterPixmap(int type, bool useDefault) const +{ + QString imageFile = createType(type, d->location); + QString text; + QString file = d->fileNames[7]; + + QStringList::ConstIterator it; + for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) { + if (QFile::exists(imageFile + file + d->altTheme + "." + *it)) { + text = imageFile + file + d->altTheme + "." + *it; + break; + } + else + if (QFile::exists(d->location + file + d->altTheme + "." + *it)) { + text = d->location + file + d->altTheme + "." + *it; + break; + } + } + + if (text.isNull() && useDefault) + return KSim::ThemeLoader::defaultUrl() + d->fileNames[7] + ".png"; + + return text; +} + +QString KSim::Theme::panelPixmap(int type, bool useDefault) const +{ + QString imageFile = createType(type, d->location); + QString text; + QString file = d->fileNames[6]; + + QStringList::ConstIterator it; + for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) { + if (QFile::exists(imageFile + file + d->altTheme + "." + *it)) { + text = imageFile + file + d->altTheme + "." + *it; + break; + } + else + if (QFile::exists(d->location + file + d->altTheme + "." + *it)) { + text = d->location + file + d->altTheme + "." + *it; + break; + } + } + + if (text.isNull() && useDefault) + return KSim::ThemeLoader::defaultUrl() + d->fileNames[6] + ".png"; + + return text; +} + +QString KSim::Theme::ledPixmap(int type, bool useDefault) const +{ + QString imageFile = createType(type, d->location); + QString text; + QString file = d->fileNames[30]; + + QStringList::ConstIterator it; + for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) { + if (QFile::exists(imageFile + file + d->altTheme + "." + *it)) { + text = imageFile + file + d->altTheme + "." + *it; + break; + } + else + if (QFile::exists(d->location + file + d->altTheme + "." + *it)) { + text = d->location + file + d->altTheme + "." + *it; + break; + } + } + + if (text.isNull() && useDefault) + return KSim::ThemeLoader::defaultUrl() + d->fileNames[30] + ".png"; + + return text; +} + +QString KSim::Theme::framePixmap(int type, bool useDefault) const +{ + QString text; + QString file; + + switch (type) { + case Types::TopFrame: + file = d->fileNames[0]; + break; + case Types::BottomFrame: + file = d->fileNames[1]; + break; + case Types::LeftFrame: + file = d->fileNames[2]; + break; + case Types::RightFrame: + file = d->fileNames[3]; + break; + } + + QStringList::ConstIterator it; + for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) { + if (QFile::exists(d->location + file + d->altTheme + "." + *it)) { + text = d->location + file + d->altTheme + "." + *it; + break; + } + } + + if (text.isNull() && useDefault) { + switch (type) { + case Types::TopFrame: + return KSim::ThemeLoader::defaultUrl() + d->fileNames[0] + ".png"; + break; + case Types::BottomFrame: + return KSim::ThemeLoader::defaultUrl() + d->fileNames[1] + ".png"; + break; + case Types::LeftFrame: + return KSim::ThemeLoader::defaultUrl() + d->fileNames[2] + ".png"; + break; + case Types::RightFrame: + return KSim::ThemeLoader::defaultUrl() + d->fileNames[3] + ".png"; + break; + } + } + + return text; +} + +QString KSim::Theme::chartPixmap(bool useDefault) const +{ + return loader(4, useDefault); +} + +QString KSim::Theme::gridPixmap(bool useDefault) const +{ + return loader(5, useDefault); +} + +QString KSim::Theme::krellPanelPixmap(bool useDefault) const +{ + return loader(14, useDefault); +} + +QString KSim::Theme::krellMeterPixmap(bool useDefault) const +{ + return loader(15, useDefault); +} + +QString KSim::Theme::krellSliderPixmap(bool useDefault) const +{ + return loader(16, useDefault); +} + +QString KSim::Theme::dataInPixmap(bool useDefault) const +{ + return loader(18, useDefault); +} + +QString KSim::Theme::dataOutPixmap(bool useDefault) const +{ + return loader(20, useDefault); +} + +QString KSim::Theme::mailPixmap(bool useDefault) const +{ + QString imageFile = createType(KSim::Types::Mail, d->location); + QString text; + QString file = d->fileNames[25]; + + QStringList::ConstIterator it; + for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) { + if (QFile::exists(imageFile + file + d->altTheme + "." + *it)) { + text = imageFile + file + d->altTheme + "." + *it; + break; + } + else + if (QFile::exists(d->location + file + d->altTheme + "." + *it)) { + text = d->location + file + d->altTheme + "." + *it; + break; + } + } + + if (text.isNull() && useDefault) + return KSim::ThemeLoader::defaultUrl() + + createType(KSim::Types::Mail, QString::null) + file + ".png"; + + return text; +} + +QPixmap KSim::Theme::splitPixmap(PixmapType type, uint itemNo, + bool useDefault) const +{ + return pixmapToList(type, itemNo, useDefault)[itemNo]; +} + +QValueList KSim::Theme::pixmapToList(PixmapType type, + int limitAmount, bool useDefault) const +{ + QImage image; + int xOffset = 0; + int yOffset = 0; + int depth = 0; + + switch (type) { + case KrellPanel: + depth = readIntEntry("StylePanel", "*.krell_depth"); + xOffset = readIntEntry("StylePanel", "*.krell_x_hot"); + yOffset = readIntEntry("StylePanel", "*.krell_yoff"); + image.load(krellPanelPixmap(useDefault)); + kdDebug(2003) << "KSim::Theme: type = KrellPanel" << endl; + break; + case KrellMeter: + depth = readIntEntry("StyleMeter", "*.krell_depth"); + xOffset = readIntEntry("StyleMeter", "*.krell_x_hot"); + yOffset = readIntEntry("StyleMeter", "*.krell_yoff"); + image.load(krellMeterPixmap(useDefault)); + kdDebug(2003) << "KSim::Theme: type = KrellMeter" << endl; + break; + case KrellSlider: + depth = krellSliderDepth(); + image.load(krellSliderPixmap(useDefault)); + kdDebug(2003) << "KSim::Theme: type = KrellSlider" << endl; + break; + default: + return QValueList(); + break; + } + + if (image.isNull()) + return QValueList(); + + QValueList list; + int size = image.height(); + if (depth) + size = image.height() / depth; + + KSim::ThemeLoader::self().reColourImage(image); + QPixmap pixmap = image; + QPixmap newPixmap(image.width() - xOffset, size); + + for (int i = 0; i < (depth + 1); ++i) { + newPixmap.fill(); + + if (pixmap.mask()) { + QBitmap mask(newPixmap.size()); + bitBlt(&mask, 0, 0, pixmap.mask(), xOffset, yOffset, + image.width() - xOffset, size); + newPixmap.setMask(mask); + } + + bitBlt(&newPixmap, 0, 0, &pixmap, xOffset, yOffset, + image.width() - xOffset, size); + + list.append(newPixmap); + + if (limitAmount == i) + break; + } + + kdDebug(2003) << "KSim::Theme: size = " << size << endl; + kdDebug(2003) << "KSim::Theme: depth = " << depth << endl; + kdDebug(2003) << "KSim::Theme: xOffset = " << xOffset << endl; + kdDebug(2003) << "KSim::Theme: yOffset = " << xOffset << endl; + + return list; +} + +int KSim::Theme::transparency(const QString &itemType, + const QString &entry) const +{ + return readIntEntry(itemType, entry); +} + +bool KSim::Theme::textShadow(const QString &itemType, + const QString &entry) const +{ + if (d->recolour) + return false; + + QString shadow = readEntry(itemType, entry); + if (shadow.isEmpty() || shadow.findRev("none") != -1) + return false; + + return true; +} + +QColor KSim::Theme::shadowColour(const QString &itemType, + const QString &entry) const +{ + return readColourEntry(itemType, entry, 1); +} + +QColor KSim::Theme::textColour(const QString &itemType, + const QString &entry) const +{ + if (d->recolour) + return KGlobalSettings::textColor(); + + return readColourEntry(itemType, entry, 0); +} + +int KSim::Theme::readIntEntry(const QString &itemType, + const QString &entry) const +{ + QString entryName = itemType + " " + entry; + return internalNumEntry(entryName, 0); +} + +QRect KSim::Theme::readRectEntry(const QString &itemType, + const QString &entry) const +{ + QString entryName = itemType + " " + entry; + return internalRectEntry(entryName, QRect()); +} + +QString KSim::Theme::readEntry(const QString &itemType, + const QString &entry) const +{ + QString entryName = itemType + " " + entry; + return internalStringEntry(entryName, QString::null); +} + +QString KSim::Theme::readColourEntry(const QString &itemType, + const QString &entry, int row) const +{ + QString color = readEntry(itemType, entry); + if (color.isEmpty()) + color = QString::fromLatin1("#ffffff #ffffff"); + + return QStringList::split(' ', color)[row]; +} + +QFont KSim::Theme::readFontEntry(const QString &itemType, + const QString &entry) const +{ + const QString &font = readEntry(itemType, entry); + + // If only there was a better way of doing this + if (font == "small_font") + return smallFont(); + else + if (font == "normal_font") + return normalFont(); + else + if (font == "large_font") + return largeFont(); + + return QFont(); +} + +bool KSim::Theme::fontColours(int type, const QString &string, QFont &font, + QColor &text, QColor &shadow, bool &showShadow) const +{ + QString key = KSim::Types::typeToString(type, false); + bool repaint = false; + + // set colours from the string 'key' + if (!readEntry(string, key + ".textcolor").isEmpty()) { + text= textColour(string, key + ".textcolor"); + shadow = shadowColour(string, key + ".textcolor"); + showShadow = textShadow(string, key + ".textcolor"); + repaint = true; + } + else { + text= textColour(string, "*.textcolor"); + shadow = shadowColour(string, "*.textcolor"); + showShadow = textShadow(string, "*.textcolor"); + } + + // set fonts from the string 'key' + if (!readEntry(string, key + ".font").isEmpty()) { + if (KSim::ThemeLoader::currentFontItem() != 3) { + font = readFontEntry(string, key + ".font"); + repaint = true; + } + } + else { + font = currentFont(); + } + + return repaint; +} + +bool KSim::Theme::fontColours(const KSim::Base *const base, QFont &font, + QColor &text, QColor &shadow, bool &showShadow) const +{ + if (!base) + return false; + + return fontColours(base->type(), base->configString(), font, + text, shadow, showShadow); +} + +KSim::Theme::Theme() +{ + d = 0; +} + +KSim::Theme::Theme(const QString &url, const QString &fileName, int alt, + const QValueVector &vector, const QStringList &list, + KConfig *globalReader) +{ + create(vector, list, globalReader); + init(url, fileName, alt); + + KSim::Config::config()->setGroup("Misc"); + d->recolour = KSim::Config::config()->readBoolEntry("ReColourTheme", false); +} + +void KSim::Theme::create(const QValueVector &vector, + const QStringList &list, KConfig *globalReader) +{ + d = new Private(vector, list); + d->globalReader = globalReader; +} + +void KSim::Theme::init(const QString &url, const QString &fileName, int alt) +{ + d->altTheme = KSim::ThemeLoader::alternativeAsString(alt); + d->location = url; + d->alternative = alt; + d->font = KSim::ThemeLoader::currentFontItem(); + + d->file = QStringList::split("\n", parseConfig(url, fileName)); + + if (alt != 0) + d->dFile = QStringList::split("\n", parseConfig(url, "gkrellmrc")); +} + +void KSim::Theme::reparse(const QString &url, const QString &fileName, int alt) +{ + init(url, fileName, alt); +} + +QString KSim::Theme::parseConfig(const QString &url, + const QString &fileName) +{ + return KSim::ThemeLoader::self().parseConfig(url, fileName); +} + +QString KSim::Theme::loader(int value, bool useDefault) const +{ + QString text; + QString file = d->fileNames[value]; + + QStringList::ConstIterator it; + for (it = d->imageTypes.begin(); it != d->imageTypes.end(); ++it) { + if (QFile::exists(d->location + file + d->altTheme + "." + *it)) { + text = d->location + file + d->altTheme + "." + *it; + break; + } + } + + if (text.isNull() && useDefault) + return KSim::ThemeLoader::defaultUrl() + d->fileNames[value] + ".png"; + + return text; +} + +QString KSim::Theme::createType(int type, const QString &text) const +{ + if (type == Types::None) + return text; + + return text + KSim::Types::typeToString(type); +} + +void KSim::Theme::setRecolour(bool value) +{ + if (!d) + return; + + d->recolour = value; +} + +// Keep the ugliness here to make the rest +// of the class readable +int KSim::Theme::internalNumEntry(const QString &entry, int defValue) const +{ + return d->readOption(entry, true, QString::number(defValue)).toInt(); +} + +QRect KSim::Theme::internalRectEntry(const QString &entry, + const QRect &defValue) const +{ + QString rect; + rect += QString::number(defValue.left()); + rect += ","; + rect += QString::number(defValue.top()); + rect += ","; + rect += QString::number(defValue.width()); + rect += ","; + rect += QString::number(defValue.height()); + + QStringList list = QStringList::split(",", d->readOption(entry, true, rect)); + QRect rect2(list[0].toInt(), list[1].toInt(), list[2].toInt(), list[3].toInt()); + + return rect2; +} + +QColor KSim::Theme::internalColourEntry(const QString &entry, + const QColor &defValue) const +{ + return d->readOption(entry, true, defValue.name()); +} + +QString KSim::Theme::internalStringEntry(const QString &entry, + const QString &defValue) const +{ + return d->readOption(entry, true, defValue); +} + +// check if the dir is writable, if not generate the new file in the home dir +#define KSIM_THEME_URL(url) \ +{ \ +} + +KSim::ThemeLoader *KSim::ThemeLoader::m_self = 0; // initialize pointer +KSim::ThemeLoader &KSim::ThemeLoader::self() +{ + if (!m_self) { // is it the first call? + m_self = new KSim::ThemeLoader; // create sole instance + qAddPostRoutine(cleanup); + } + + return *m_self; // address of sole instance +} + +bool KSim::ThemeLoader::isDifferent() const +{ + // if the theme path, theme alternative or the + // specified font has changed then we should + // return true, else false + + KSim::Config::config()->setGroup("Misc"); + bool recolour = KSim::Config::config()->readBoolEntry("ReColourTheme", false); + + return (current().path() != currentUrl() + || current().alternative() != currentAlternative() + || current().fontItem() != currentFontItem() + || d->recolour != recolour); +} + +void KSim::ThemeLoader::reload() +{ + reColourItems(); + grabColour(); + + if (!isDifferent()) + return; + + if (currentUrl() != defaultUrl()) { + if (!d->globalReader) + d->globalReader = new KConfig(defaultUrl() + "gkrellmrc_ksim"); + } + else { + delete d->globalReader; + d->globalReader = 0; + } + + if (m_theme.d) + m_theme.d->globalReader = d->globalReader; + + QString fileName = QString::fromLatin1("gkrellmrc") + alternativeAsString(); + m_theme.reparse(currentUrl(), fileName, currentAlternative()); +} + +const KSim::Theme &KSim::ThemeLoader::current() const +{ + return m_theme; +} + +KSim::Theme KSim::ThemeLoader::theme(const QString &url, + const QString &rcFile, int alt) const +{ + return KSim::Theme(url, rcFile, alt, d->fileNames, + d->imageTypes, d->globalReader); +} + +void KSim::ThemeLoader::reColourImage(QImage &image) +{ + if (!d->recolour || image.isNull()) + return; + + QColor color = QApplication::palette().active().background(); + QImage output(image.width(), image.height(), 32); + output.setAlphaBuffer(image.hasAlphaBuffer()); + + Q_UINT32 r = color.red(); + Q_UINT32 g = color.green(); + Q_UINT32 b = color.blue(); + Q_UINT32 *write = reinterpret_cast(output.bits()); + Q_UINT32 *read = reinterpret_cast(image.bits()); + int size = image.width() * image.height(); + + for (int pos = 0; pos < size; pos++) + { + QRgb basePix = static_cast(*read); + + // Here, we assume that source is really gray, so R=G=B=I + // Use blue since it's very easy to extract. + Q_UINT32 i = qBlue(basePix); + + Q_UINT32 cr = (r * i + 128) >> 8; // Fixed point.. + Q_UINT32 cg = (g * i + 128) >> 8; + Q_UINT32 cb = (b * i + 128) >> 8; + + Q_UINT32 alpha = qAlpha(basePix); + *write = qRgba(cr, cg, cb, alpha); + write++; + read++; + } + + image = output; +} + +QString KSim::ThemeLoader::parseConfig(const QString &url, + const QString &fileName) +{ + QFile origFile(url + fileName); + + if (!origFile.open(IO_ReadOnly)) + return QString::null; + + QTextStream origStream(&origFile); + QString text; + QRegExp reg("\\*"); // regexp for '*' chars + QRegExp number("[0-9]+"); // regexp for all numbers + QRegExp numbers("[0-9]+,[0-9]+,[0-9]+,[0-9]+"); // regexp for int,int,int,int + QRegExp minus("[a-zA-Z]+ \\- [a-zA-Z]+"); // regexp for 'someText - someText' + while (!origStream.atEnd()) { + QString line(origStream.readLine().simplifyWhiteSpace()); + + if (line.find(reg) == 0) // find the location of the * comments + // replace all * comments with # comments so KConfig doesn't complain + line.replace(reg, "#"); + + if (line.find("#") == -1) { // find the location of the string 'gkrellmms' + if (line.findRev("=") == -1) { // if found we check for the string '=' + int numLoc = line.findRev(numbers); + if (numLoc != -1) + // if '=' doesn't exist we add one so KConfig doesn't complain + line.insert(numLoc, " = "); + + numLoc = line.findRev(number); + if (numLoc != -1) + // if '=' doesn't exist we add one so KConfig doesn't complain + line.insert(numLoc, " = "); + + numLoc = line.findRev(minus); + if (numLoc != -1) + // replace the '-' with an '=' so KConfig doesn't get confused + line.replace(QRegExp("-"), "="); + } + } + + text.append(line).append('\n'); + } + + return text; +} + +// GKrellM themes seem to be rather inconsistant +// so the following code changes the dir structure +// of a theme to be more consistant, but the dir structure +// is still compliant with GKrellM. +void KSim::ThemeLoader::parseDir(const QString &url, int alt) +{ + if ( !QFileInfo( url ).isWritable() && currentName() != "ksim" ) + { + QString homePath = QDir::current().path(); + homePath = locateLocal( "data", "ksim" ) + + QString::fromLatin1( "/themes" ) + + homePath.right( homePath.length() + - homePath.findRev( QRegExp( "\\/" ), + homePath.length() ) ); + + if ( !QFile::exists( homePath ) ) + KStandardDirs::makeDir( homePath ); + + kdWarning() << "Cant write to current dir, setting dir to " + << homePath << endl; + + QDir::setCurrent( homePath ); + } + + int alternatives = ++alt; + + QStringList formats; + QStringList panels; + QStringList meters; + + formats << "png" << "jpg" << "jpeg" << "gif" << "xpm"; + panels << "inet" << "net" << "proc" << "cpu" << "disk"; + meters << "mem" << "fs" << "mail" << "apm" << "uptime" + << "clock" << "cal" << "timer" << "host" << "swap"; + + QDir directory; + for (int i = 0; i < alternatives; ++i) { + QString altString = KSim::ThemeLoader::alternativeAsString(i); + if (alternatives == 1 || i == 0) + altString = QString::null; + + QStringList::ConstIterator format; + for (format = formats.begin(); format != formats.end(); ++format) { + // go through the meters array and move the files to the correct dir/filename + QStringList::Iterator meter; + for (meter = meters.begin(); meter != meters.end(); ++meter) { + QString bgMeter = QString::fromLatin1("bg_meter_"); + if (QFile::exists(bgMeter + (*meter) + altString + "." + (*format))) { + if (KStandardDirs::makeDir(url + (*meter))) + directory.rename(bgMeter + (*meter) + altString + "." + (*format), + (*meter) + "/bg_meter" + altString + "." + (*format)); + } + } + + // go through the panels array and move the files to the correct dir/filename + QStringList::ConstIterator panel; + for (panel = panels.begin(); panel != panels.end(); ++panel) { + QString bgPanel = QString::fromLatin1("bg_panel_"); + if (QFile::exists(bgPanel + (*panel) + altString + "." + (*format))) { + if (KStandardDirs::makeDir(url + (*panel))) + directory.rename(bgPanel + (*panel) + altString + "." + (*format), + (*panel) + "/bg_panel" + altString + "." + (*format)); + } + } + + // fix stupid themes that have a bg_panel image in the host dir + QString tempFile = QString::fromLatin1("host/bg_panel"); + if (QFile::exists(tempFile + altString + "." + (*format))) + directory.rename(tempFile + altString + "." + (*format), "host/bg_meter" + + altString + "." + (*format)); + + // move decal_net_leds* to the net folder to be more consistant + tempFile = QString::fromLatin1("decal_net_leds"); + if (QFile::exists(tempFile + altString + "." + (*format))) { + if (KStandardDirs::makeDir(url + "net")) + directory.rename(tempFile + altString + "." + (*format), + "net/decal_net_leds" + altString + "." + (*format)); + } + } + } +} + +void KSim::ThemeLoader::validate() +{ + if (!QFile::exists(currentUrl())) { + KSim::Config::config()->setGroup("Theme"); + KSim::Config::config()->writeEntry("Name", "ksim"); + KSim::Config::config()->writeEntry("Alternative", 0); + KSim::Config::config()->sync(); + } +} + +void KSim::ThemeLoader::themeColours(QWidget *widget) +{ + widget->setEraseColor(d->pixelColour); +} + +QString KSim::ThemeLoader::currentName() +{ + KSim::Config::config()->setGroup("Theme"); + return KSim::Config::config()->readEntry("Name", "ksim"); +} + +QString KSim::ThemeLoader::currentUrl() +{ + KSim::Config::config()->setGroup("Theme"); + QString folder(KSim::Config::config()->readEntry("Name")); + folder.prepend("ksim/themes/").append("/"); + QString dirName(KGlobal::dirs()->findResourceDir("data", folder)); + dirName += folder; + + return dirName; +} + +QString KSim::ThemeLoader::defaultUrl() +{ + return KGlobal::dirs()->findDirs("data", "ksim/themes/ksim").first(); +} + +int KSim::ThemeLoader::currentAlternative() +{ + KSim::Config::config()->setGroup("Theme"); + int alternative = KSim::Config::config()->readNumEntry("Alternative"); + + if ( alternative > self().current().alternatives() ) + alternative = self().current().alternatives(); + + return alternative; +} + +QString KSim::ThemeLoader::alternativeAsString(int alt) +{ + int alternative = (alt == -1 ? currentAlternative() : alt); + return (alternative == 0 ? QString::null : QString::fromLatin1("_") + + QString::number(alternative)); +} + +QFont KSim::ThemeLoader::currentFont() +{ + if (currentFontItem() != 3) + return self().current().currentFont(); + + KSim::Config::config()->setGroup("Theme"); + return KSim::Config::config()->readFontEntry("Font"); +} + +int KSim::ThemeLoader::currentFontItem() +{ + KSim::Config::config()->setGroup("Theme"); + return KSim::Config::config()->readNumEntry("FontItem", 0); +} + +KSim::ThemeLoader::ThemeLoader() +{ + m_self = this; + + d = new Private; + d->imageTypes << "png" << "jpg" << "jpeg" << "xpm" << "gif"; + + if (currentUrl() != defaultUrl()) + d->globalReader = new KConfig(defaultUrl() + "gkrellmrc_ksim"); + else + d->globalReader = 0; + + d->fileNames.resize(31); + d->fileNames[0] = "frame_top"; + d->fileNames[1] = "frame_bottom"; + d->fileNames[2] = "frame_left"; + d->fileNames[3] = "frame_right"; + d->fileNames[4] = "bg_chart"; + d->fileNames[5] = "bg_grid"; + d->fileNames[6] = "bg_panel"; + d->fileNames[7] = "bg_meter"; + d->fileNames[8] = "bg_slider_panel"; + d->fileNames[9] = "bg_slider_meter"; + d->fileNames[10] = "button_panel_in"; + d->fileNames[11] = "button_panel_out"; + d->fileNames[12] = "button_meter_in"; + d->fileNames[13] = "button_meter_out"; + d->fileNames[14] = "krell_panel"; + d->fileNames[15] = "krell_meter"; + d->fileNames[16] = "krell_slider"; + d->fileNames[17] = "decal_misc"; + d->fileNames[18] = "data_in"; + d->fileNames[19] = "data_in_grid"; + d->fileNames[20] = "data_out"; + d->fileNames[21] = "data_out_grid"; + d->fileNames[22] = "krell"; + d->fileNames[23] = "spacer_top"; + d->fileNames[24] = "spacer_bottom"; + d->fileNames[25] = "decal_mail"; + d->fileNames[26] = "krell_penguin"; + d->fileNames[27] = "bg_volt"; + d->fileNames[28] = "decal_timer_button"; + d->fileNames[29] = "bg_timer"; + d->fileNames[30] = "decal_net_leds"; + + m_theme.create(d->fileNames, d->imageTypes, d->globalReader); + + QString fileName = QString::fromLatin1("gkrellmrc") + alternativeAsString(); + m_theme.init(currentUrl(), fileName, currentAlternative()); + + reColourItems(); + grabColour(); +} + +KSim::ThemeLoader::~ThemeLoader() +{ + delete d->globalReader; + delete d; +} + +void KSim::ThemeLoader::cleanup() +{ + if (!m_self) + return; + + delete m_self; + m_self = 0; +} + +void KSim::ThemeLoader::reColourItems() +{ + KSim::Config::config()->setGroup("Misc"); + d->recolour = KSim::Config::config()->readBoolEntry("ReColourTheme", false); + m_theme.setRecolour(d->recolour); +} + +void KSim::ThemeLoader::grabColour() +{ + KSim::Config::config()->setGroup("Theme"); + QPoint pos(2, 2); + pos = KSim::Config::config()->readPointEntry("PixelLocation", &pos); + + QImage image(current().meterPixmap(Types::None)); + reColourImage(image); + d->pixelColour = image.pixel(pos.x(), pos.y()); +} diff --git a/ksim/library/themeloader.h b/ksim/library/themeloader.h new file mode 100644 index 0000000..c20afe0 --- /dev/null +++ b/ksim/library/themeloader.h @@ -0,0 +1,511 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef THEMELOADER_H +#define THEMELOADER_H + +#include +#include +#include +#include +#include + +#include + +class QStringList; +template class QValueVector; +class KConfig; +class QWidget; + +namespace KSim +{ + class Base; + + /** + * a class containing various information + * about a theme, use KSim::ThemeLoader to + * get an instance + * @author Robbie Ward + * @short Provides a loader for the themes + */ + class KDE_EXPORT Theme + { + friend class ThemeLoader; + public: + enum PixmapType { KrellPanel = 0, KrellMeter, KrellSlider }; + ~Theme(); + bool operator==(const KSim::Theme &rhs) const; + bool operator!=(const KSim::Theme &rhs) const; + KSim::Theme &operator=(const KSim::Theme &rhs); + /** + * @return the theme path + */ + const QString &path() const; + /** + * @return the name of the theme + */ + QString name() const; + /** + * @return the author of the theme + */ + QString author() const; + /** + * @return the set font item for the theme + */ + int fontItem() const; + /** + * @return the amount of alternatives the theme has + */ + int alternative() const; + /** + * @return the amount of alternatives the theme has + */ + int alternatives() const; + /** + * @return the width leds should be scaled to (if scaling() returns true) + */ + int chartWidthRef(int defValue = 0) const; + int chartWidthMin(int defValue = 0) const; + /** + * @return true if sacling should be enabled + */ + bool scaling(bool defValue = false) const; + /** + * @return the height of the top frame + */ + int frameTopHeight(int defValue = 0) const; + /** + * @return the height of the bottom frame + */ + int frameBottomHeight(int defValue = 0) const; + /** + * @return the width of the left frame + */ + int frameLeftWidth(int defValue = 0) const; + /** + * @return the width of the right frame + */ + int frameRightWidth(int defValue = 0) const; + /** + * @return a rect of the top frame border + */ + QRect frameTopBorder(const QRect &defValue = QRect()) const; + /** + * @return a rect of the bottom frame border + */ + QRect frameBottomBorder(const QRect &defValue = QRect()) const; + /** + * @return a rect of the left frame border + */ + QRect frameLeftBorder(const QRect &defValue = QRect()) const; + /** + * @return a rect of the right frame border + */ + QRect frameRightBorder(const QRect &defValue = QRect()) const; + /** + * @return the color of the chart in + */ + QColor chartInColour(const QColor &defValue = QColor()) const; + /** + * @return the color of the chart in grid + */ + QColor chartInColourGrid(const QColor &defValue = QColor()) const; + /** + * @return the color of the chart out + */ + QColor chartOutColour(const QColor &defValue = QColor()) const; + /** + * @return the color of the chart out grid + */ + QColor chartOutColourGrid(const QColor &defValue = QColor()) const; + /** + * if false then the grid lines should be drawn at the + * top and bottom of the graphs + */ + bool bgGridMode(bool defValue = false) const; + /** + * @return the X location of the receive led + */ + int rxLedX(int defValue = 0) const; + /** + * @return the Y location of the receive led + */ + int rxLedY(int defValue = 0) const; + /** + * @return the X location of the send led + */ + int txLedX(int defValue = 0) const; + /** + * @return the Y location of the send led + */ + int txLedY(int defValue = 0) const; + /** + * @return the amount of mail frames + */ + int mailFrames(int defValue = 0) const; + /** + * @return the mail check delay + */ + int mailDelay(int defValue = 0) const; + /** + * @return the slider depth + */ + int krellSliderDepth(int defValue = 7) const; + /** + * @return the vertical location of the start of the image + */ + int krellSliderXHot(int defValue = 0) const; + /** + * @return the area for the slider panel + */ + QRect sliderPanel(const QRect &defValue = QRect()) const; + /** + * @return the area for the slider meter + */ + QRect sliderMeter(const QRect &defValue = QRect()) const; + /** + * @return the border for the timer label/button + */ + QRect timerBorder(const QRect &defValue = QRect()) const; + /** + * @return the border for the panel button + */ + QRect buttonPanelBorder(const QRect &defValue = QRect()) const; + /** + * @return the border for the meter button + */ + QRect buttonMeterBorder(const QRect &defValue = QRect()) const; + /** + * @return the large font that the theme specifies + */ + QFont largeFont() const; + /** + * @return the normal font that the theme specifies + */ + QFont normalFont() const; + /** + * @return the small font that the theme specifies + */ + QFont smallFont() const; + /** + * @return the current font to be used + * according to fontItem() + */ + QFont currentFont() const; + /** + * @return the meter image (bg_meter.[png|jpg|gif]) + * of the current theme, if type is specified then it will + * look in the folder type. + * + * it will first look in the dir 'type' if no image is found + * it will drop back a dir + * @param type is one of: none, apm, cal, clock, fs, + * host, mail, mem, swap, timer, uptime + */ + QString meterPixmap(int type, bool useDefault = true) const; + /** + * @return the meter image (bg_panel.[png|jpg|gif]) + * of the current theme, it will first look in the dir 'type' + * if no image is found it will drop back a dir + * @param type is one of: net, inet + */ + QString panelPixmap(int type, bool useDefault = true) const; + /** + * @return the decal net leds image + * (usually decal_net_leds.[png|jpg|gif]) of the + * current theme, it will first look in the dir 'type' + * if no image is found it will drop back a dir + * @param type is one of: net, inet + */ + QString ledPixmap(int type, bool useDefault = true) const; + /** + * @return the frame image of the current theme, + * @param type is one of: top, bottom, left, right + */ + QString framePixmap(int type, bool useDefault = true) const; + /** + * @return the krell chart image (bg_chart.[png|jpg|gif]) + * of the current theme + */ + QString chartPixmap(bool useDefault = true) const; + /** + * @return the krell grid image (bg_grid.[png|jpg|gif]) + * of the current theme + */ + QString gridPixmap(bool useDefault = true) const; + /** + * @return the krell panel image (krell_panel.[png|jpg|gif]) + * of the current theme + */ + QString krellPanelPixmap(bool useDefault = true) const; + /** + * @return the krell meter image (krell_meter.[png|jpg|gif]) + * of the current theme + */ + QString krellMeterPixmap(bool useDefault = true) const; + /** + * @return the krell slider image (krell_slider.[png|jpg|gif]) + * of the current theme + */ + QString krellSliderPixmap(bool useDefault = true) const; + /** + * @return the data in image (data_in.[png|jpg|gif]) + * of the current theme + */ + QString dataInPixmap(bool useDefault = true) const; + /** + * @return the data out image (data_out.[png|jpg|gif]) + * of the current theme + */ + QString dataOutPixmap(bool useDefault = true) const; + /** + * @return the mail image (mail/decal_mail.[png|jpg|gif]) + * of the current theme + */ + QString mailPixmap(bool useDefault = true) const; + /** + * @return a segmant of an image, using @p itemNo to + * get the segmant and from the ImageType @p type + */ + QPixmap splitPixmap(PixmapType type, uint itemNo = 0, + bool useDefault = true) const; + /** + * Same as the above function but returns an array of pixmaps + * with the maximum size of limitAmount, or all the pixmaps if @p + * limitAmount is -1 (default) + * @return an array of pixmaps + */ + QValueList pixmapToList(PixmapType type, + int limitAmount = -1, bool useDefault = true) const; + /** + * returns the transparency level from the specified keys + */ + int transparency(const QString &, const QString &) const; + /** + * @return true if shadow text is enabled + */ + bool textShadow(const QString &, const QString &) const; + /** + * @return the shadow color (if any) for the specified keys + */ + QColor shadowColour(const QString &, const QString &) const; + /** + * @return the text color for the specified keys + */ + QColor textColour(const QString &, const QString &) const; + /** + * reads an entry and returns it as an int + */ + int readIntEntry(const QString &, const QString &) const; + /** + * @return a rect from the specified keys + */ + QRect readRectEntry(const QString &, const QString &) const; + /** + * reads an entry from the specified keys + */ + QString readEntry(const QString &, const QString &) const; + /** + * reads a color entry from the specified keys + */ + QString readColourEntry(const QString &, const QString &, int) const; + /** + * reads a font entry from the specified keys + */ + QFont readFontEntry(const QString &, const QString &) const; + /** + * sets the font, textColour, shadowColour and showShadow to + * the fonts and colours KSim should use depending on type and + * string. + * + * returns true if one of the parameters were changed using + * type and string, else the parameters will be set to the current + * colours and font that KSim should use and returns false. + * + * example usage: + *
    +       *   QFont font;
    +       *   QColor textColour, shadowColour;
    +       *   bool showShadow;
    +       *   if (KSim::ThemeLoader::self().current().fontColours(type(), configString(), font,
    +       *      textColour, shadowColour, showShadow)
    +       *   {
    +       *     setFont(font);
    +       *     // Do something with textColour, shadowColour and showShadow
    +       *   }
    +       * 
    + * @param type is the theme type you want, generally if you're calling this + * from a KSim::Base (or derived from) object then use type() + * @param string is the config string entry you want the function to read + * from, generally if you're calling this from a KSim::Base (or derived from) + * object then use configString() + */ + bool fontColours(int type, const QString &string, QFont &font, + QColor &textColour, QColor &shadowColour, bool &showShadow) const; + /** + * convenience function. + * + * collects the theme type and config key from the base pointer + */ + bool fontColours(const KSim::Base *const base, QFont &font, + QColor &textColour, QColor &shadowColour, bool &showShadow) const; + + Theme(const KSim::Theme &); + + private: + Theme(); + Theme(const QString &url, const QString &fileName, int alt, + const QValueVector &vector, const QStringList &list, + KConfig *globalReader); + void create(const QValueVector &, const QStringList &, KConfig *); + void init(const QString &url, const QString &fileName, int alt); + void reparse(const QString &url, const QString &fileName, int alt); + QString parseConfig(const QString &, const QString &); + QString loader(int, bool useDefault = true) const; + QString createType(int, const QString &) const; + void setRecolour(bool); + + int internalNumEntry(const QString &, int) const; + QRect internalRectEntry(const QString &, const QRect &) const; + QColor internalColourEntry(const QString &, const QColor &) const; + QString internalStringEntry(const QString &, const QString &) const; + + class Private; + Private *d; + }; + + /** + * returns a class Theme containing + * information of the current theme or + * of the theme path specified + * @author Robbie Ward + * @short Provides a loader for the themes + */ + class KDE_EXPORT ThemeLoader + { + public: + /** + * @return a reference to the instance + */ + static ThemeLoader &self(); + /** + * @return true if the theme has changed + */ + bool isDifferent() const; + /** + * Updates the info to the current theme + */ + void reload(); + /** + * @return the current theme that is set + */ + const KSim::Theme ¤t() const; + /** + * @return a theme from the path specified + * @param url is the path of the theme dir + * @param rcFile is the filename of the config file (optional) + * @param alt is the theme alternative number (optional) + */ + KSim::Theme theme(const QString &url, + const QString &rcFile = "gkrellmrc", int alt = 0) const; + /** + * re-colours an image to the current KDE + * color scheme + */ + void reColourImage(QImage &image); + /** + * changes some of the entries in the config file so kconfig + * can handle the file better. + * @return the location of the config file + */ + QString parseConfig(const QString &url, const QString &file); + /** + * change the dir structure of a theme directory + * so KSim can understand them better + */ + void parseDir(const QString &url, int alt); + /** + * checks if the themeUrl entry is valid, + * if not it then reverts the current theme + * to the default url + */ + void validate(); + /** + * sets the pallete of the current theme + */ + void themeColours(QWidget *); + /** + * @return current theme name + */ + static QString currentName(); + /** + * @return current theme url, if there is no current theme + * then it will return the default theme + */ + static QString currentUrl(); + /** + * @return the default theme url + */ + static QString defaultUrl(); + /** + * @return the current theme alternative + */ + static int currentAlternative(); + /** + * @return the current theme alternative as a string, eg if the + * current theme alt is 1 then this will return '_1'. + * if there is no theme alt this will return a null string. + * + * if this is set to -1 (the default) then the current alternative + * will be used + */ + static QString alternativeAsString(int alt = -1); + /** + * @return the font of the theme if the theme font is set to custom + */ + static QFont currentFont(); + /** + * @return the font item of the theme, eg: 0 would be the small font + */ + static int currentFontItem(); + + protected: + /** + * Default constructor, use self() to get an instance + */ + ThemeLoader(); + ~ThemeLoader(); + + private: + ThemeLoader(const ThemeLoader &); + ThemeLoader &operator=(const ThemeLoader &); + /** + * Deletes the instance and cleans up after itself + */ + static void cleanup(); + void reColourItems(); + void grabColour(); + + class Private; + Private *d; + KSim::Theme m_theme; + static ThemeLoader *m_self; + }; +} +#endif diff --git a/ksim/library/themetypes.h b/ksim/library/themetypes.h new file mode 100644 index 0000000..805302c --- /dev/null +++ b/ksim/library/themetypes.h @@ -0,0 +1,81 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef THEMETYPES_H +#define THEMETYPES_H + +namespace KSim +{ + namespace Types + { + /** + * available types for the frames + */ + enum FrameType + { + TopFrame = 0, + BottomFrame, + LeftFrame, + RightFrame + }; + + /** + * available theme types + */ + enum ThemeType + { + None = -1, + Apm, + Cal, + Clock, + Fs, + Host, + Mail, + Mem, + Swap, + Timer, + Uptime, + Net, + Inet + }; + + /** + * @return the ThemeType enum as a QString + */ + inline QString typeToString(int type, bool incSlash = true) + { + if (type == Types::None) + return QString::null; + + // This array MUST be in the same order + // as the ThemeType enum + const char *typeNames[] = { + "apm", "cal", "clock", + "fs", "host", "mail", + "mem", "swap", "timer", + "uptime", "net", "inet", 0 + }; + + QString returnString; + returnString.setLatin1(typeNames[type]); + return incSlash ? returnString + QString::fromLatin1("/") : returnString; + } + } +} +#endif diff --git a/ksim/monitorprefs.cpp b/ksim/monitorprefs.cpp new file mode 100644 index 0000000..1e67945 --- /dev/null +++ b/ksim/monitorprefs.cpp @@ -0,0 +1,98 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "monitorprefs.h" +#include "monitorprefs.moc" + +#include +#include +#include +#include +#include + +#include +#include + +KSim::MonitorPrefs::MonitorPrefs(QWidget *parent, const char *name) + : KListView(parent, name) +{ + addColumn(i18n("Monitor")); + addColumn(i18n("Description")); + addColumn(i18n("LMB Command")); + + setItemsRenameable(true); + setRenameable(0, false); + setRenameable(2, true); + setDragEnabled(true); + setAcceptDrops(true); + setAllColumnsShowFocus(true); + setSelectionMode(QListView::Single); + + // Scan for .desktop files and enter them into the KListView + m_locatedFiles = KGlobal::dirs()->findAllResources("data", "ksim/monitors/*.desktop"); + m_locatedFiles.sort(); + QStringList::ConstIterator it; + for (it = m_locatedFiles.begin(); it != m_locatedFiles.end(); ++it) { + KDesktopFile file((*it), true); + (void)(new QCheckListItem(this, file.readName(), QCheckListItem::CheckBox))->setText(1, file.readComment()); + } + + sort(); + setSorting(-1, false); +} + +KSim::MonitorPrefs::~MonitorPrefs() +{ +} + +void KSim::MonitorPrefs::saveConfig(KSim::Config *config) +{ + QCheckListItem *item; + QStringList::ConstIterator it; + for (it = m_locatedFiles.begin(); it != m_locatedFiles.end(); ++it) { + KSim::PluginInfo info = KSim::PluginLoader::self().findPluginInfo((*it)); + item = static_cast(findItem(info.name(), 0)); + config->setEnabledMonitor(info.libName(), item->isOn()); + config->setMonitorCommand(info.libName(), item->text(2)); + config->setMonitorLocation(info.libName(), itemIndex(item)); + } +} + +void KSim::MonitorPrefs::readConfig(KSim::Config *config) +{ + int location; + QCheckListItem *origItem; + QStringList::ConstIterator it; + for (it = m_locatedFiles.begin(); it != m_locatedFiles.end(); ++it) { + KSim::PluginInfo info = KSim::PluginLoader::self().findPluginInfo((*it)); + location = config->monitorLocation(info.libName()); + origItem = static_cast(findItem(info.name(), 0)); + origItem->setOn(config->enabledMonitor(info.libName())); + origItem->setText(2, config->monitorCommand(info.libName())); + if (QListViewItem *item = itemAtIndex(location)) { + if (location) { + origItem->moveItem(item->itemAbove()); + } + else { + origItem->moveItem(firstChild()); + firstChild()->moveItem(origItem); + } + } + } +} diff --git a/ksim/monitorprefs.h b/ksim/monitorprefs.h new file mode 100644 index 0000000..6cb4798 --- /dev/null +++ b/ksim/monitorprefs.h @@ -0,0 +1,45 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef MONITORPREFS_H +#define MONITORPREFS_H + +#include +#include + +namespace KSim +{ + class Config; + + class MonitorPrefs : public KListView + { + Q_OBJECT + public: + MonitorPrefs(QWidget *parent, const char *name=0); + ~MonitorPrefs(); + + public slots: + void saveConfig(KSim::Config *); + void readConfig(KSim::Config *); + + private: + QStringList m_locatedFiles; + }; +} +#endif diff --git a/ksim/monitors/Makefile.am b/ksim/monitors/Makefile.am new file mode 100644 index 0000000..7e5c863 --- /dev/null +++ b/ksim/monitors/Makefile.am @@ -0,0 +1,9 @@ +if supports_i8k +i8k_SUBDIR = i8k +endif + +if include_ksim_monitors_snmp +SNMP_SUBDIR = snmp +endif + +SUBDIRS = filesystem net lm_sensors cpu disk $(i8k_SUBDIR) $(SNMP_SUBDIR) diff --git a/ksim/monitors/cpu/Makefile.am b/ksim/monitors/cpu/Makefile.am new file mode 100644 index 0000000..beaebd2 --- /dev/null +++ b/ksim/monitors/cpu/Makefile.am @@ -0,0 +1,16 @@ +kde_module_LTLIBRARIES = ksim_cpu.la +ksim_cpu_la_SOURCES = ksimcpu.cpp + +ksim_cpu_la_LIBADD = ../../library/libksimcore.la +ksim_cpu_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) + +EXTRA_DIST = cpu.desktop + +INCLUDES= -I$(top_srcdir)/ksim/library \ + $(all_includes) + +METASOURCES = AUTO +KDE_ICON = AUTO + +mon_DATA = cpu.desktop +mondir = $(kde_datadir)/ksim/monitors diff --git a/ksim/monitors/cpu/cpu.desktop b/ksim/monitors/cpu/cpu.desktop new file mode 100644 index 0000000..c8130ec --- /dev/null +++ b/ksim/monitors/cpu/cpu.desktop @@ -0,0 +1,94 @@ +[Desktop Entry] +Icon=ksim_cpu +Name=CPU +Name[af]=Sve +Name[ar]=وحدة المعالجة المركزية +Name[bg]=Процесори +Name[cs]=Procesor +Name[el]=KME +Name[eo]=Procezilo +Name[fa]=واحد پردازش مرکزی +Name[fr]=Processeur +Name[he]=מעבד +Name[hi]=सीपीयू +Name[hr]=Procesor +Name[is]=Örgjörvi +Name[kk]=Процессор +Name[mk]=Процесор +Name[pl]=procesor +Name[ru]=Процессор +Name[sk]=Procesor +Name[sl]=CPE +Name[sv]=Processor +Name[ta]= சிபியு +Name[tg]=ВПМ +Name[th]=ซีพียู +Name[tr]=İşlemci +Name[uk]=ЦП +Name[uz]=Protsessor +Name[uz@cyrillic]=Процессор +Name[wa]=Processeu +Comment=CPU Monitor Plugin +Comment[af]=Sve Monitor Inplak +Comment[ar]=ملحق مراقبة وحدة المعالجة المركزيّة +Comment[bg]=Мониторинг на процесора(ите) +Comment[bs]=Dodatak za nadzor CPUa +Comment[ca]=Monitor de CPU +Comment[cs]=Modul pro monitorování procesoru +Comment[cy]=Atodyn Monitro CPU +Comment[da]=CPU-overvågnings-plugin +Comment[de]=CPU-Nutzungsanzeige +Comment[el]=Πρόσθετο εποπτείας KME +Comment[eo]=Prozecilo-observila kromaĵo +Comment[es]=Extensión de monitorización de la CPU +Comment[et]=Protsessori monitooring +Comment[eu]=CPU Plugin Begiralea +Comment[fa]=وصلۀ نمایشگر واحد پردازش مرکزی +Comment[fi]=Suorittimentarkkailusovelma +Comment[fr]=Module de surveillance du processeur +Comment[ga]=Breiseán Monatóireachta LAP +Comment[he]=תוסף צג מעבד +Comment[hi]=सीपीयू मॉनीटर प्लगइन +Comment[hu]=CPU-figyelő bővítőmodul +Comment[is]=Örgjörva eftirlitsíforrit +Comment[it]=Plugin di controllo CPU +Comment[ja]=CPU モニタプラグイン +Comment[ka]= პროცესორის მონიტორის მოდული +Comment[kk]=Процессорды бақылау модулі +Comment[km]=កម្មវិធី​ជំនួយ​នៃ​កម្មវិធី​ត្រួតពិនិត្យ​ថាស CPU Monitor +Comment[lt]=CPU stebėtojo priedas +Comment[mk]=Приклучок за следење на процесорот +Comment[ms]=Plug masuk Pemerhati CPU +Comment[nb]=Programtillegg for CPU-overvåkning +Comment[nds]=CPU-Kiekmoduul +Comment[ne]=CPU मोनिटर प्लगइन +Comment[nl]=CPU monitor-plugin +Comment[nn]=Programtillegg for CPU-overvaking +Comment[pa]=CPU ਨਿਗਰਾਨੀ ਪਲੱਗਿੰਨ +Comment[pl]=Stan procesora +Comment[pt]='Plugin' de monitorização do processador +Comment[pt_BR]=Plug-in de monitoramento da CPU +Comment[ro]=Modul monitorizare CPU +Comment[ru]=Монитор процессора +Comment[sk]=Modul pre monitorovanie CPU +Comment[sl]=Vstavek za opazovanje stanja CPE +Comment[sr]=Прикључак за надгледање CPU-а +Comment[sr@Latn]=Priključak za nadgledanje CPU-a +Comment[sv]=Insticksprogram för processoraktivitet +Comment[ta]= சிபியு கண்காணி சொருகுப்பொருள் +Comment[tg]=Модули Дидабони ВПМ +Comment[th]=ปลั๊กอินสอดส่องซีพียู +Comment[tr]=İşlemci İzleyici Eklentisi +Comment[uk]=Втулок датчика ЦП +Comment[uz]=Protsessorni nazorat qilish plagini +Comment[uz@cyrillic]=Процессорни назорат қилиш плагини +Comment[wa]=Tchôke-divins di corwaitaedje do CPU +Comment[xh]=Iplagi yangaphakathi ye Monitor CPU +Comment[zh_CN]=CPU 监视器插件 +Comment[zh_TW]=CPU 監視器外掛程式 +Comment[zu]=I-plugin Yomlawuli we-CPU +X-KSIM-VERSION=0.1 +X-KSIM-LIBRARY=cpu +X-KSIM-AUTHOR=Robbie Ward +X-KSIM-EMAIL=linuxphreak@gmx.co.uk +X-KSIM-COPYRIGHT=(C) 2001 Robbie Ward diff --git a/ksim/monitors/cpu/cr16-device-ksim_cpu.png b/ksim/monitors/cpu/cr16-device-ksim_cpu.png new file mode 100644 index 0000000..c9d8d08 Binary files /dev/null and b/ksim/monitors/cpu/cr16-device-ksim_cpu.png differ diff --git a/ksim/monitors/cpu/ksimcpu.cpp b/ksim/monitors/cpu/ksimcpu.cpp new file mode 100644 index 0000000..9e6d089 --- /dev/null +++ b/ksim/monitors/cpu/ksimcpu.cpp @@ -0,0 +1,514 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "ksimcpu.h" +#include "ksimcpu.moc" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef Q_OS_BSD4 +#include +#if defined(__DragonFly__) +#include +#include +#include +#include + +#elif defined Q_OS_FREEBSD +#if __FreeBSD_version < 500101 +#include +#else +#include +#endif +#else +#include +#endif +#include +#include +#include +#ifdef Q_OS_NETBSD +#include +#endif +#endif + +#define CPU_NAME(cpu) "Cpu" + QString::number(cpu) + "_options" +#define CPU_SPEED 1000 + +KSIM_INIT_PLUGIN(CpuPlugin) + +CpuPlugin::CpuPlugin(const char *name) + : KSim::PluginObject(name) +{ + setConfigFileName(instanceName()); +} + +CpuPlugin::~CpuPlugin() +{ +} + +KSim::PluginView *CpuPlugin::createView(const char *className) +{ + return new CpuView(this, className); +} + +KSim::PluginPage *CpuPlugin::createConfigPage(const char *className) +{ + return new CpuConfig(this, className); +} + +void CpuPlugin::showAbout() +{ + QString version = kapp->aboutData()->version(); + + KAboutData aboutData(instanceName(), + I18N_NOOP("KSim CPU Plugin"), version.latin1(), + I18N_NOOP("A cpu monitor plugin for KSim"), + KAboutData::License_GPL, "(C) 2001 Robbie Ward"); + + aboutData.addAuthor("Robbie Ward", I18N_NOOP("Author"), + "linuxphreak@gmx.co.uk"); + + KAboutApplication(&aboutData).exec(); +} + +CpuView::CpuView(KSim::PluginObject *parent, const char *name) + : KSim::PluginView(parent, name) +{ +#ifdef Q_OS_LINUX + m_procStream = 0L; + if ((m_procFile = fopen("/proc/stat", "r"))) + m_procStream = new QTextStream(m_procFile, IO_ReadOnly); +#endif + + m_mainLayout = new QVBoxLayout(this); + QSpacerItem *item = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding); + m_mainLayout->addItem(item); + + m_firstTime = true; + + m_cpus = createList(); + addDisplay(); + + m_timer = new QTimer(this); + connect(m_timer, SIGNAL(timeout()), SLOT(updateView())); + m_timer->start(CPU_SPEED); + updateView(); +} + +CpuView::~CpuView() +{ +#ifdef Q_OS_LINUX + delete m_procStream; + + if (m_procFile) + fclose(m_procFile); +#endif + + cleanup(m_cpus); +} + +void CpuView::reparseConfig() +{ + CpuList cpus = createList(); + if (m_cpus != cpus) { + if (m_timer->isActive()) + m_timer->stop(); + + cleanup(m_cpus); + m_cpus = cpus; + addDisplay(); + m_timer->start(CPU_SPEED); + } +} + +void CpuView::updateView() +{ + if (m_cpus.isEmpty()) + return; + + CpuList::Iterator it; + for (it = m_cpus.begin(); it != m_cpus.end(); ++it) { + Cpu ¤t = (*it); + CpuData cpuData; + updateCpu(cpuData, current.number()); + + QString text = current.format(); + current.setData(cpuData); + cpuData -= current.oldData(); + int cpuDiff = 0; + int total = cpuData.sys + cpuData.user + cpuData.nice + cpuData.idle; + +// kdDebug(2003) << "name = " << cpuData.name << endl; +// kdDebug(2003) << "user = " << cpuData.user << endl; +// kdDebug(2003) << "nice = " << cpuData.nice << endl; +// kdDebug(2003) << "sys = " << cpuData.sys << endl; +// kdDebug(2003) << "idle = " << cpuData.idle << endl; + + if (!m_firstTime) { + if (text.find("%T") != -1) + cpuDiff = cpuData.sys + cpuData.user + cpuData.nice; + else if (text.find("%t") != -1) + cpuDiff = cpuData.sys + cpuData.user; + else if (text.find("%s") != -1) + cpuDiff = cpuData.sys; + else if (text.find("%u") != -1) + cpuDiff = cpuData.user; + else if (text.find("%n") != -1) + cpuDiff = cpuData.nice; + + cpuDiff *= 100; + + if ( total > 0 ) + cpuDiff /= total; + + if (cpuDiff > 100) + cpuDiff = 100; + } + + current.chart()->setText(i18n("%1%").arg(cpuDiff)); + current.chart()->setValue(cpuDiff, 0); + current.label()->setValue(cpuDiff); + } + + m_firstTime = false; +} + +void CpuView::updateCpu(CpuData &cpu, int cpuNumber) +{ +#ifdef Q_OS_LINUX + if (!m_procStream) + return; + + bool cpuFound = false; + QString output; + QString parser; + QString cpuString; + cpuString.setNum(cpuNumber).prepend("cpu"); + + // Parse the proc file + while (!m_procStream->atEnd()) { + parser = m_procStream->readLine(); + // remove all the entries apart from the line containing 'cpuString' + if (!cpuFound && parser.find(QRegExp(cpuString)) != -1) { + output = parser; + cpuFound = true; + } + } + + QStringList cpuList = QStringList::split(' ', output); + + if (!cpuList.isEmpty()) { + cpu.name = cpuList[0].stripWhiteSpace(); + cpu.user = cpuList[1].toULong(); + cpu.nice = cpuList[2].toULong(); + cpu.sys = cpuList[3].toULong(); + cpu.idle = cpuList[4].toULong(); + } + + fseek(m_procFile, 0L, SEEK_SET); +#endif + +#ifdef __DragonFly__ + struct kinfo_cputime cp_time; + if (kinfo_get_sched_cputime(&cp_time)) + err(1, "kinfo_get_sched_cputime"); + cpu.user = cp_time.cp_user; + cpu.nice = cp_time.cp_nice; + cpu.sys = cp_time.cp_sys; + cpu.idle = cp_time.cp_idle; +#elif defined(Q_OS_FREEBSD) +#warning "add support for SMP on FreeBSD" + Q_UNUSED(cpuNumber); + static int name2oid[2] = { 0, 3 }; + static int oidCpuTime[CTL_MAXNAME + 2]; + static size_t oidCpuTimeLen = sizeof(oidCpuTime); + long cpuTime[CPUSTATES]; + size_t cpuTimeLen = sizeof(cpuTime); + static char name[] = "kern.cp_time"; + static int initialized = 0; + + if (!initialized) { + if (sysctl(name2oid, 2, oidCpuTime, &oidCpuTimeLen, + name, strlen(name)) < 0) + return; + + oidCpuTimeLen /= sizeof(int); + initialized = 1; + } + + if (sysctl(oidCpuTime, oidCpuTimeLen, + cpuTime, &cpuTimeLen, 0, 0) < 0) + return; + + cpu.user = cpuTime[CP_USER]; + cpu.nice = cpuTime[CP_NICE]; + cpu.sys = cpuTime[CP_SYS]; + cpu.idle = cpuTime[CP_IDLE]; +#endif + +#if defined(Q_OS_NETBSD) +#define KERN_CPTIME KERN_CP_TIME +#endif +#if defined(Q_OS_OPENBSD) || defined(Q_OS_NETBSD) +//#warning "add support for SMP on OpenBSD and NetBSD" + int name2oid[2] = { CTL_KERN, KERN_CPTIME }; + long cpuTime[CPUSTATES]; + size_t cpuTimeLen = sizeof(cpuTime); + + if (sysctl(name2oid, 2, &cpuTime, &cpuTimeLen, + 0, 0) < 0) + return; + + cpu.user = cpuTime[CP_USER]; + cpu.nice = cpuTime[CP_NICE]; + cpu.sys = cpuTime[CP_SYS]; + cpu.idle = cpuTime[CP_IDLE]; +#endif +} + +CpuView::CpuList CpuView::createList() +{ + config()->setGroup("CpuPlugin"); + CpuList list; + + int number = 0; + QStringList cpus = config()->readListEntry("Cpus"); + QStringList::ConstIterator it; + for (it = cpus.begin(); it != cpus.end(); ++it) { + list.append(Cpu((*it), config()->readEntry(CPU_NAME(number), + "%T"), number)); + + ++number; + } + + return list; +} + +void CpuView::addDisplay() +{ + CpuList::Iterator it; + for (it = m_cpus.begin(); it != m_cpus.end(); ++it) { + KSim::Progress *progress = addLabel(); + KSim::Chart *chart = addChart(); + //KSim::Progress *progress = addLabel(); + + (*it).setDisplay(chart, progress); + } +} + +void CpuView::cleanup(CpuList &list) +{ + CpuList::Iterator it; + for (it = list.begin(); it != list.end(); ++it) + (*it).cleanup(); + + list.clear(); +} + +KSim::Chart *CpuView::addChart() +{ + KSim::Chart *chart = new KSim::Chart(false, 0, this); + chart->show(); + m_mainLayout->addWidget(chart); + + return chart; +} + +KSim::Progress *CpuView::addLabel() +{ + KSim::Progress *progress = new KSim::Progress(100, + KSim::Types::None, KSim::Progress::Panel, this); + + progress->show(); + m_mainLayout->addWidget(progress); + + return progress; +} + +CpuConfig::CpuConfig(KSim::PluginObject *parent, const char *name) + : KSim::PluginPage(parent, name) +{ + QVBoxLayout * mainLayout = new QVBoxLayout( this ); + mainLayout->setSpacing( 6 ); + + m_listView = new KListView(this); + m_listView->addColumn(i18n("Available CPUs")); + m_listView->addColumn(i18n("Chart Format")); + m_listView->setAllColumnsShowFocus(true); + m_listView->setSelectionMode(QListView::Single); + connect( m_listView, SIGNAL( doubleClicked( QListViewItem * ) ), + SLOT( modify( QListViewItem * ) ) ); + + mainLayout->addWidget( m_listView ); + + QHBoxLayout * layout = new QHBoxLayout; + layout->setSpacing( 6 ); + + QSpacerItem * spacer = new QSpacerItem( 20, 20, + QSizePolicy::Expanding, QSizePolicy::Minimum ); + layout->addItem(spacer); + + m_modify = new QPushButton( this ); + m_modify->setText( i18n( "Modify..." ) ); + connect( m_modify, SIGNAL( clicked() ), SLOT( modify() ) ); + layout->addWidget( m_modify ); + mainLayout->addLayout( layout ); + + m_legendBox = new QGroupBox(this); + m_legendBox->setColumnLayout(0, Qt::Vertical); + m_legendBox->setTitle(i18n("Chart Legend")); + m_legendBox->layout()->setSpacing(0); + m_legendBox->layout()->setMargin(0); + + m_legendLayout = new QVBoxLayout(m_legendBox->layout()); + m_legendLayout->setAlignment(Qt::AlignTop); + m_legendLayout->setSpacing(6); + m_legendLayout->setMargin(11); + + m_totalNiceLabel = new QLabel(i18n("%T - Total CPU time (sys + user + nice)"), m_legendBox); + m_legendLayout->addWidget(m_totalNiceLabel); + + m_totalLabel = new QLabel(i18n("%t - Total CPU time (sys + user)"), m_legendBox); + m_legendLayout->addWidget(m_totalLabel); + + m_sysLabel = new QLabel(i18n("%s - Total sys time"), m_legendBox); + m_legendLayout->addWidget(m_sysLabel); + + m_userLabel = new QLabel(i18n("%u - Total user time"), m_legendBox); + m_legendLayout->addWidget(m_userLabel); + + m_niceLabel = new QLabel(i18n("%n - Total nice time"), m_legendBox); + m_legendLayout->addWidget(m_niceLabel); + + mainLayout->addWidget( m_legendBox ); + + for (uint i = 0; i < addCpus(); ++i) + { + QCheckListItem *item = new QCheckListItem(m_listView, i18n("cpu %1").arg(i), QCheckListItem::CheckBox); + item->setText(1, "%T"); + } +} + +CpuConfig::~CpuConfig() +{ +} + +void CpuConfig::readConfig() +{ + config()->setGroup("CpuPlugin"); + QStringList enabledCpus(config()->readListEntry("Cpus")); + + int cpuNum = 0; + QStringList::ConstIterator it; + for (it = enabledCpus.begin(); it != enabledCpus.end(); ++it) { + if (QCheckListItem *item = + static_cast(m_listView->findItem((*it), 0))) { + item->setOn(true); + item->setText(1, config()->readEntry(CPU_NAME(cpuNum), "%T")); + } + ++cpuNum; + } +} + +void CpuConfig::saveConfig() +{ + config()->setGroup("CpuPlugin"); + + int cpuNum = 0; + QStringList enabledCpus; + for (QListViewItemIterator it(m_listView); it.current(); ++it) { + config()->writeEntry(CPU_NAME(cpuNum), it.current()->text(1)); + if (static_cast(it.current())->isOn()) + enabledCpus.append(it.current()->text(0)); + ++cpuNum; + } + + config()->writeEntry("Cpus", enabledCpus); +} + +uint CpuConfig::addCpus() +{ +#ifdef Q_OS_LINUX + QStringList output; + QString parser; + QFile file("/proc/stat"); + if (!file.open(IO_ReadOnly)) + return 0; + + // Parse the proc file + QTextStream procStream(&file); + while (!procStream.atEnd()) { + parser = procStream.readLine(); + if (QRegExp("cpu").search(parser, 0) != -1 + && QRegExp("cpu0").search(parser, 0) == -1) { + output.append(parser); + } + } + + return output.count(); +#endif + +#ifdef Q_OS_BSD4 + int mib[] = { CTL_HW, HW_NCPU }; // hw.ncpu + uint cpu; + size_t cpuLen = sizeof(cpu); + if (sysctl(mib, 2, &cpu, &cpuLen, NULL, 0) < 0) + return 0; + + return cpu; +#endif +} + +void CpuConfig::modify( QListViewItem * item ) +{ + if ( !item ) + return; + + bool ok = false; + QString text = KInputDialog::getText( i18n( "Modify CPU Format" ), i18n( "Chart format:" ), + item->text( 1 ), &ok, this ); + + if ( ok ) + item->setText( 1, text ); +} + +void CpuConfig::modify() +{ + modify( m_listView->selectedItem() ); +} diff --git a/ksim/monitors/cpu/ksimcpu.h b/ksim/monitors/cpu/ksimcpu.h new file mode 100644 index 0000000..b129ec0 --- /dev/null +++ b/ksim/monitors/cpu/ksimcpu.h @@ -0,0 +1,228 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIMCPU_H +#define KSIMCPU_H + +#include +#include +#include + +#include + +class QPushButton; +class QTextStream; +class QVBoxLayout; +class QHBoxLayout; +class QCheckBox; +class QLabel; +class QGroupBox; +class QTimer; +class QListViewItem; +class KListView; + +class CpuPlugin : public KSim::PluginObject +{ + public: + CpuPlugin(const char *name); + ~CpuPlugin(); + + virtual KSim::PluginView *createView(const char *); + virtual KSim::PluginPage *createConfigPage(const char *); + + virtual void showAbout(); +}; + +class CpuView : public KSim::PluginView +{ + Q_OBJECT + public: + CpuView(KSim::PluginObject *parent, const char *name); + ~CpuView(); + + virtual void reparseConfig(); + + private slots: + void updateView(); + + private: + class CpuData + { + public: + CpuData() { user = nice = sys = idle = 0; } + + QString name; + unsigned long user; + unsigned long nice; + unsigned long sys; + unsigned long idle; + + CpuData &operator-=(const CpuData &rhs) + { + if (name != rhs.name) + return *this; + + user -= rhs.user; + nice -= rhs.nice; + sys -= rhs.sys; + idle -= rhs.idle; + return *this; + } + }; + + class Cpu + { + public: + Cpu() + { + m_num = 0; + m_chart = 0; + m_label = 0; + } + + Cpu(const QString &name, + const QString &format, + int number) + : m_name(name), + m_format(format), + m_num(number) + { + m_chart = 0; + m_label = 0; + } + + ~Cpu() + { + } + + bool operator==(const Cpu &rhs) const + { + return m_name == rhs.m_name && + m_format == rhs.m_format; + } + + bool operator!=(const Cpu &rhs) const + { + return !operator==(rhs); + } + + void cleanup() + { + delete m_chart; + delete m_label; + } + + void setData(const CpuData &data) + { + m_old = m_data; + m_data = data; + } + + const CpuData &oldData() const + { + return m_old; + } + + const QString &format() const + { + return m_format; + } + + int number() const + { + return m_num; + } + + void setDisplay(KSim::Chart *chart, KSim::Progress *label) + { + m_chart = chart; + m_label = label; + m_label->setText(m_name); + } + + KSim::Chart *chart() + { + return m_chart; + } + + KSim::Progress *label() + { + return m_label; + } + + private: + CpuData m_data; + CpuData m_old; + QString m_name; + QString m_format; + KSim::Chart *m_chart; + KSim::Progress *m_label; + int m_num; + }; + + typedef QValueList CpuList; + void updateCpu(CpuData &cpu, int cpuNumber); + CpuList createList(); + + void addDisplay(); + void cleanup(CpuList &); + + KSim::Chart *addChart(); + KSim::Progress *addLabel(); + + QTimer *m_timer; + QVBoxLayout *m_mainLayout; + bool m_firstTime; + CpuList m_cpus; + +#ifdef __linux__ + FILE *m_procFile; + QTextStream *m_procStream; +#endif +}; + +class CpuConfig : public KSim::PluginPage +{ + Q_OBJECT + public: + CpuConfig(KSim::PluginObject *parent, const char *name); + ~CpuConfig(); + + virtual void saveConfig(); + virtual void readConfig(); + + private slots: + void modify( QListViewItem * ); + void modify(); + + private: + uint addCpus(); + + KListView *m_listView; + QGroupBox *m_legendBox; + QLabel *m_totalNiceLabel; + QLabel *m_totalLabel; + QLabel *m_sysLabel; + QLabel *m_userLabel; + QLabel *m_niceLabel; + QVBoxLayout *m_legendLayout; + + QPushButton * m_modify; +}; +#endif diff --git a/ksim/monitors/disk/Makefile.am b/ksim/monitors/disk/Makefile.am new file mode 100644 index 0000000..ce9f79c --- /dev/null +++ b/ksim/monitors/disk/Makefile.am @@ -0,0 +1,15 @@ +kde_module_LTLIBRARIES = ksim_disk.la +ksim_disk_la_SOURCES = ksimdisk.cpp + +ksim_disk_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +ksim_disk_la_LIBADD = $(LIB_DEVSTAT) ../../library/libksimcore.la + +EXTRA_DIST = disk.desktop + +INCLUDES= -I$(top_srcdir)/ksim/library \ + $(all_includes) + +METASOURCES = AUTO + +mon_DATA = disk.desktop +mondir = $(kde_datadir)/ksim/monitors diff --git a/ksim/monitors/disk/configure.in.in b/ksim/monitors/disk/configure.in.in new file mode 100644 index 0000000..19b0e8f --- /dev/null +++ b/ksim/monitors/disk/configure.in.in @@ -0,0 +1,13 @@ +AC_CHECK_LIB(devstat, selectdevs, +[ + LIB_DEVSTAT="-ldevstat" +], +[ + AC_CHECK_LIB(devstat, devstat_selectdevs, + [ + LIB_DEVSTAT="-ldevstat" + ] + ) +]) + +AC_SUBST(LIB_DEVSTAT) diff --git a/ksim/monitors/disk/disk.desktop b/ksim/monitors/disk/disk.desktop new file mode 100644 index 0000000..f048878 --- /dev/null +++ b/ksim/monitors/disk/disk.desktop @@ -0,0 +1,106 @@ +[Desktop Entry] +Comment=Disk Monitor Plugin +Comment[af]=Disket Monitor Inplak +Comment[ar]=ملحق مراقبة القرص +Comment[bg]=Мониторинг на входно-изходите операции с диска +Comment[bs]=Dodatak za nadzor diska +Comment[ca]=Monitor de disc +Comment[cs]=Modul pro monitorování disku +Comment[cy]=Atodyn Monitro Disg +Comment[da]=Diskovervågnings-plugin +Comment[de]=Hilfsprogramm zur Festplattenüberwachung +Comment[el]=Πρόσθετο εποπτείας δίσκου +Comment[eo]=Disk-observa kromaĵo +Comment[es]=Extensión de monitorización de disco +Comment[et]=Ketta monitooring +Comment[eu]=Diskoaren Plugin Begiralea +Comment[fa]=وصلۀ نمایشگر دیسک +Comment[fi]=Levyntarkkailusovelma +Comment[fr]=Module de surveillance du disque +Comment[ga]=Breiseán Monatóireachta Diosca +Comment[he]=תוסף צג דיסק +Comment[hi]=डिस्क मॉनीटर प्लगइन +Comment[hu]=Lemezfigyelő bővítőmodul +Comment[is]=Disk eftirlitsforrit +Comment[it]=Plugin di controllo disco +Comment[ja]=ディスクモニタプラグイン +Comment[ka]= დისკის მონიტორის მოდული +Comment[kk]=Дискін бақылау модулі +Comment[km]=កម្មវិធី​ជំនួយ​នៃ​កម្មវិធី​ត្រួតពិនិត្យ​ថាស +Comment[lt]=Disko stebėtojo priedas +Comment[mk]=Приклучок за следење на дискот +Comment[ms]=Plug masuk Pemerhati Monitor +Comment[nb]=Programtillegg for diskovervåkning +Comment[nds]=Fastplaat-Kiekmoduul +Comment[ne]=डिस्क मोनिटर प्लगइन +Comment[nl]=Disk monitor-plugin +Comment[nn]=Programtillegg for diskovervaking +Comment[pa]=ਡਿਸਕ ਨਿਗਰਾਨ ਪਲੱਗਿੰਨ +Comment[pl]=Stan dysku +Comment[pt]='Plugin' de Monitorização do Disco +Comment[pt_BR]=Plug-in de monitoramento do Disco +Comment[ro]=Modul monitorizare disc +Comment[ru]=Монитор дискового пространства +Comment[sk]=Modul pre monitorovanie disku +Comment[sl]=Vstavek za opazovanje diska +Comment[sr]=Прикључак за надгледање диска +Comment[sr@Latn]=Priključak za nadgledanje diska +Comment[sv]=Insticksprogram för diskövervakning +Comment[ta]= வட்டு கண்காணி சொருகுப்பொருள் +Comment[tg]=Модули Дидабони Диск +Comment[th]=ปลั๊กอินตรวจการทำงานดิสก์ +Comment[tr]=Disk İzleyici Eklentisi +Comment[uk]=Втулок датчика диску +Comment[uz]=Diskni nazorat qilish plagini +Comment[uz@cyrillic]=Дискни назорат қилиш плагини +Comment[wa]=Tchôke-divins di corwaitaedje del deure plake +Comment[xh]=Iplagi efakiweyo ye Monitor Yediski +Comment[zh_CN]=磁盘监视器插件 +Comment[zh_TW]=磁碟監視器外掛程式 +Comment[zu]=I-plugin Yomlawuli Wediski +Icon=hdd_mount +Name=Disk +Name[af]=Disket +Name[ar]=قرص +Name[bg]=Дискове +Name[br]=Pladenn +Name[ca]=Disc +Name[el]=Δίσκος +Name[eo]=Disko +Name[es]=Disco +Name[et]=Ketas +Name[eu]=Diskoa +Name[fa]=دیسک +Name[fi]=Levy +Name[ga]=Diosca +Name[he]=דיסק +Name[hi]=डिस्क +Name[hu]=Lemez +Name[is]=Diskur +Name[it]=Disco +Name[ja]=ディスク +Name[kk]=Дискі +Name[km]=ថាស +Name[lt]=Diskas +Name[lv]=Disks +Name[mk]=Диск +Name[ms]=Cakera +Name[nds]=Fastplaat +Name[ne]=डिस्क +Name[pa]=ਡਿਸਕ +Name[pl]=Dysk +Name[pt]=Disco +Name[pt_BR]=Disco +Name[ro]=Disc +Name[ru]=Диск +Name[sr]=Диск +Name[ta]=வட்டு +Name[tg]=Диск +Name[th]=ดิสก์ +Name[uk]=Диск +Name[uz@cyrillic]=Диск +Name[wa]=Deure plake +Name[xh]=Idiski +Name[zh_CN]=磁盘 +Name[zu]=Idiski +X-KSIM-LIBRARY=disk diff --git a/ksim/monitors/disk/ksimdisk.cpp b/ksim/monitors/disk/ksimdisk.cpp new file mode 100644 index 0000000..2fe3560 --- /dev/null +++ b/ksim/monitors/disk/ksimdisk.cpp @@ -0,0 +1,570 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "ksimdisk.h" +#include "ksimdisk.moc" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if defined(__DragonFly__) +#include +#include +#include +#include +#include +#elif defined(Q_OS_FREEBSD) +#include +#if __FreeBSD_version < 500101 +#include +#else +#include +#endif +#include +#include +#endif + +#ifdef Q_OS_LINUX +#include +#endif + +#include + +#define DISK_SPEED 1000 + +KSIM_INIT_PLUGIN(DiskPlugin) + +DiskPlugin::DiskPlugin(const char *name) + : KSim::PluginObject(name) +{ + setConfigFileName(instanceName()); +} + +DiskPlugin::~DiskPlugin() +{ +} + +KSim::PluginView *DiskPlugin::createView(const char *className) +{ + return new DiskView(this, className); +} + +KSim::PluginPage *DiskPlugin::createConfigPage(const char *className) +{ + return new DiskConfig(this, className); +} + +void DiskPlugin::showAbout() +{ + QString version = kapp->aboutData()->version(); + + KAboutData aboutData(instanceName(), + I18N_NOOP("KSim Disk Plugin"), version.latin1(), + I18N_NOOP("A disk monitor plugin for KSim"), + KAboutData::License_GPL, "(C) 2001 Robbie Ward"); + + aboutData.addAuthor("Robbie Ward", I18N_NOOP("Author"), + "linuxphreak@gmx.co.uk"); + + KAboutApplication(&aboutData).exec(); +} + +DiskView::DiskView(KSim::PluginObject *parent, const char *name) + : KSim::PluginView(parent, name) +{ +#ifdef Q_OS_LINUX + m_bLinux24 = true; + m_procStream = 0L; + if ((m_procFile = fopen("/proc/stat", "r"))) + m_procStream = new QTextStream(m_procFile, IO_ReadOnly); +#endif + + config()->setGroup("DiskPlugin"); + m_list = config()->readListEntry("Disks", QStringList() << "complete"); + m_useSeperatly = config()->readBoolEntry("UseSeperatly", true); + + m_firstTime = 1; + m_addAll = false; + m_layout = new QVBoxLayout(this); + QSpacerItem *item = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding); + m_layout->addItem(item); + + init(); + + m_timer = new QTimer(this); + connect(m_timer, SIGNAL(timeout()), SLOT(updateDisplay())); + m_timer->start(DISK_SPEED); + updateDisplay(); +} + +DiskView::~DiskView() +{ +#ifdef Q_OS_LINUX + delete m_procStream; + + if (m_procFile) + fclose(m_procFile); +#endif +} + +void DiskView::reparseConfig() +{ + config()->setGroup("DiskPlugin"); + QStringList list = config()->readListEntry("Disks", QStringList() << "complete"); + m_useSeperatly = config()->readBoolEntry("UseSeperatly", true); + + if (list != m_list) { + m_list = list; + m_timer->stop(); + cleanup(); + + QPtrListIterator it(m_diskList); + for (; it.current(); ++it) { + delete it.current()->first; + delete it.current()->second; + } + + m_diskList.clear(); + init(); + m_timer->start(DISK_SPEED); + updateDisplay(); + } +} + +DiskView::DiskData DiskView::findDiskData(const DiskList& diskList, QString diskName) +{ + if (diskName == "complete") + diskName = i18n("All Disks"); + + DiskView::DiskList::ConstIterator disk; + for (disk = diskList.begin(); disk != diskList.end(); ++disk) + if ((*disk).name == diskName) + return *disk; + + // Not found + DiskView::DiskData dummy; + dummy.name = "["+diskName+"]"; + return dummy; +} + +// Kind of messy code, dont ya think? +void DiskView::updateDisplay() +{ + DiskList diskList; + + updateData(diskList); + + if (m_addAll) + { + DiskData all; + all.name = i18n("All Disks"); + + for (DiskList::ConstIterator disk = diskList.begin(); + disk != diskList.end(); ++disk) + { + all += (*disk); + } + + diskList.prepend(all); + } + + // merge all the disks into one + QPtrListIterator it(m_diskList); + for (int i = 0; it.current(); ++it, ++i) { + DiskData diskData = findDiskData(diskList, m_list[i]); + m_data[i].second = m_data[i].first; + m_data[i].first = diskData; + diskData -= m_data[i].second; + unsigned long diff = diskData.readBlocks + diskData.writeBlocks; + if (m_firstTime) + diff = diskData.readBlocks = diskData.writeBlocks = 0; + + if (m_useSeperatly) { + it.current()->first->setValue(diskData.readBlocks, diskData.writeBlocks); + it.current()->first->setText(i18n("in: %1k") + .arg(KGlobal::locale()->formatNumber((float)diskData.readBlocks / 1024.0, 1)), + i18n("out: %1k").arg(KGlobal::locale()->formatNumber((float)diskData.writeBlocks / 1024.0, 1))); + } + else { + it.current()->first->setValue(diff, 0); + it.current()->first->setText(i18n("%1k") + .arg(KGlobal::locale()->formatNumber((float)diff / 1024.0, 1))); + } + + it.current()->second->setMaxValue(it.current()->first->maxValue()); + it.current()->second->setText(diskData.name); + it.current()->second->setValue(diff); + } + + m_firstTime = 0; +} + +void DiskView::updateData(DiskList &disks) +{ +#ifdef Q_OS_LINUX + if (!m_procStream) + return; + + m_procStream->device()->reset(); + fseek(m_procFile, 0L, SEEK_SET); + + if (m_bLinux24) + { + // here we need a regexp to match something like: + // (3,0):(108911,48080,1713380,60831,1102644) + QRegExp regexp("\\([0-9]+,[0-9]+\\):\\([0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\\)"); + QString content = m_procStream->read(); + if (content.find("disk_io") == -1) + { + m_bLinux24 = false; + + delete m_procStream; + m_procStream = 0; + fclose(m_procFile); + + if ((m_procFile = fopen("/proc/diskstats", "r"))) + m_procStream = new QTextStream(m_procFile, IO_ReadOnly); + + updateData(disks); + return; + } + int idx = 0; + while ((idx = regexp.search(content, idx)) != -1) + { + idx += regexp.matchedLength(); + QString diskStr = regexp.cap(0); + diskStr.replace(':', ','); + diskStr.replace(QRegExp("\\)?\\(?"), QString::null); + + QStringList list = QStringList::split(',', diskStr); + if (list.count() < 7) + continue; + + DiskData diskData; + diskData.major = list[0].toInt(); + diskData.minor = list[1].toInt(); + diskData.name = diskName( diskData.major, diskData.minor ); + diskData.total = list[2].toULong(); + diskData.readIO = list[3].toULong(); + diskData.readBlocks = list[4].toULong(); + diskData.writeIO = list[5].toULong(); + diskData.writeBlocks = list[6].toULong(); + disks.append(diskData); + } + } + else + { + // 3 0 hda 564142 160009 14123957 12369403 1052983 2801992 30905928 78981451 0 4531584 91518334 + // The 11 fields after the device name are defined as follows: + // Field 1 -- # of reads issued + // This is the total number of reads completed successfully. + // Field 2 -- # of reads merged, + // Reads and writes which are adjacent to each other may be merged for + // efficiency. Thus two 4K reads may become one 8K read before it is + // ultimately handed to the disk, and so it will be counted (and queued) + // as only one I/O. This field lets you know how often this was done. + // Field 3 -- # of sectors read + // This is the total number of sectors read successfully. + // Field 4 -- # of milliseconds spent reading + // This is the total number of milliseconds spent by all reads (as + // measured from __make_request() to end_that_request_last()). + // Field 5 -- # of writes completed + // This is the total number of writes completed successfully. + // Field 6 -- # of writes merged + // See field 2 + // Field 7 -- # of sectors written + // This is the total number of sectors written successfully. + // Field 8 -- # of milliseconds spent writing + // This is the total number of milliseconds spent by all writes (as + // measured from __make_request() to end_that_request_last()). + // Field 9 -- # of I/Os currently in progress + // The only field that should go to zero. Incremented as requests are + // given to appropriate request_queue_t and decremented as they finish. + // Field 10 -- # of milliseconds spent doing I/Os + // This field is increases so long as field 9 is nonzero. + // Field 11 -- weighted # of milliseconds spent doing I/Os + // This field is incremented at each I/O start, I/O completion, I/O + // merge, or read of these stats by the number of I/Os in progress + // (field 9) times the number of milliseconds spent doing I/O since the + // last update of this field. This can provide an easy measure of both + // I/O completion time and the backlog that may be accumulating. + QString content = m_procStream->read(); + QStringList lines = QStringList::split('\n', content); + + for(QStringList::ConstIterator it = lines.begin(); + it != lines.end(); ++it) + { + QString diskStr = (*it).simplifyWhiteSpace(); + QStringList list = QStringList::split(' ', diskStr); + if (list.count() < 14) + continue; + + DiskData diskData; + diskData.major = list[0].toInt(); + diskData.minor = list[1].toInt(); + diskData.name = list[2]; + diskData.readIO = 0; + diskData.readBlocks = list[3+2].toULong(); + diskData.writeIO = 0; + diskData.writeBlocks = list[7+2].toULong(); + diskData.total = diskData.readBlocks + diskData.writeBlocks; + disks.append(diskData); + } + } + +#endif + +#ifdef Q_OS_FREEBSD +#if defined(__DragonFly__) || __FreeBSD_version < 500107 +#define devstat_getdevs(fd, stats) getdevs(stats) +#define devstat_selectdevs selectdevs +#define bytes_read(dev) (dev).bytes_read +#define bytes_written(dev) (dev).bytes_written +#else +#define bytes_read(dev) (dev).bytes[DEVSTAT_READ] +#define bytes_written(dev) (dev).bytes[DEVSTAT_WRITE] +#endif + + statinfo diskStats; + bzero(&diskStats, sizeof(diskStats)); + diskStats.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); + bzero(diskStats.dinfo, sizeof(struct devinfo)); + int deviceAmount; + int selected; + int selections; + long generation; + device_selection *deviceSelect = 0; + + if (devstat_getdevs(NULL, &diskStats) < 0) + return; + + deviceAmount = diskStats.dinfo->numdevs; + if (devstat_selectdevs(&deviceSelect, &selected, &selections, + &generation, diskStats.dinfo->generation, + diskStats.dinfo->devices, deviceAmount, + 0, 0, 0, 0, DS_SELECT_ONLY, 10, 1) < 0) + return; + + unsigned long readBlocks = 0, writeBlocks = 0, blockSize; + for (int i = 0; i < deviceAmount; ++i) { + int disk; + devstat device; + disk = deviceSelect[i].position; + device = diskStats.dinfo->devices[disk]; + blockSize = (device.block_size <= 0 ? 512 : device.block_size); + readBlocks = bytes_read(device) / blockSize; + writeBlocks = bytes_written(device) / blockSize; + + DiskData diskData; + diskData.name = device.device_name + + QString::number(device.unit_number); + diskData.major = device.device_number; + diskData.minor = 0; + diskData.total = readBlocks + writeBlocks; + diskData.readIO = 0; + diskData.readBlocks = readBlocks; + diskData.writeIO = 0; + diskData.writeBlocks = writeBlocks; + disks.append(diskData); + } + + free(deviceSelect); + free(diskStats.dinfo); +#endif +} + +QString DiskView::diskName( int major, int minor ) const +{ +#ifdef Q_OS_LINUX + QString returnValue; + switch ( major ) + { + case IDE0_MAJOR: + returnValue.prepend(QString::fromLatin1("hda")); + break; + case IDE1_MAJOR: + returnValue.prepend(QString::fromLatin1("hdc")); + break; + case IDE3_MAJOR: + returnValue.prepend(QString::fromLatin1("hde")); + break; + case SCSI_DISK0_MAJOR: + returnValue.prepend(QString::fromLatin1("sda")); + break; + case SCSI_GENERIC_MAJOR: + returnValue.prepend(QString::fromLatin1("sg0")); + break; + } + + returnValue.at(2) = returnValue.at(2).latin1() + minor; + return returnValue; +#else + Q_UNUSED(major); + Q_UNUSED(minor); + return 0; +#endif +} + +DiskView::DiskPair *DiskView::addDisk() +{ + KSim::Chart *chart = new KSim::Chart(false, 0, this); + chart->show(); + m_layout->addWidget(chart); + + KSim::Progress *progress = new KSim::Progress(0, KSim::Types::None, + KSim::Progress::Panel, this); + progress->show(); + m_layout->addWidget(progress); + + return new DiskPair(chart, progress); +} + +void DiskView::init() +{ + m_data.resize(m_list.size()); + + QStringList::ConstIterator it; + for (it = m_list.begin(); it != m_list.end(); ++it) { + if ((*it) == "complete") + m_addAll = true; + + m_diskList.append(addDisk()); + } +} + +void DiskView::cleanup() +{ + m_data.clear(); + m_addAll = false; +} + +DiskConfig::DiskConfig(KSim::PluginObject *parent, const char *name) + : KSim::PluginPage(parent, name) +{ + m_layout = new QVBoxLayout(this); + m_layout->setSpacing(6); + + m_listview = new KListView(this); + m_listview->addColumn(i18n("Disks")); + m_layout->addWidget(m_listview); + + QHBoxLayout *layout = new QHBoxLayout; + layout->setSpacing(6); + + QSpacerItem *spacer = new QSpacerItem(20, 20, + QSizePolicy::Expanding, QSizePolicy::Minimum); + layout->addItem(spacer); + + m_add = new QPushButton(this); + m_add->setText(i18n("Add...")); + connect(m_add, SIGNAL(clicked()), SLOT(addItem())); + layout->addWidget(m_add); + + m_remove = new QPushButton(this); + m_remove->setText(i18n("Remove")); + connect(m_remove, SIGNAL(clicked()), SLOT(removeItem())); + layout->addWidget(m_remove); + m_layout->addLayout(layout); + + m_buttonBox = new QVButtonGroup(i18n("Disk Styles"), this); + m_layout->addWidget(m_buttonBox); + + m_totalButton = new QRadioButton(m_buttonBox); + m_totalButton->setText(i18n("Display the read and write data as one")); + m_bothButton = new QRadioButton(m_buttonBox); + m_bothButton->setText(i18n("Display the read and write data" + "\nseparately as in/out data")); + + QSpacerItem *vSpacer = new QSpacerItem(20, 20, + QSizePolicy::Minimum, QSizePolicy::Expanding); + m_layout->addItem(vSpacer); +} + +DiskConfig::~DiskConfig() +{ +} + +void DiskConfig::readConfig() +{ + config()->setGroup("DiskPlugin"); + m_buttonBox->setButton(config()->readBoolEntry("UseSeperatly", true)); + QStringList list = config()->readListEntry("Disks"); + + QStringList::ConstIterator it; + for (it = list.begin(); it != list.end(); ++it) { + QString text = ((*it) == "complete" ? i18n("All Disks") : (*it)); + if (!m_listview->findItem(text, 0)) + new QListViewItem(m_listview, text); + } +} + +void DiskConfig::saveConfig() +{ + QStringList list; + for (QListViewItemIterator it(m_listview); it.current(); ++it) { + if (it.current()->text(0) == i18n("All Disks")) + list.append("complete"); + else + list.append(it.current()->text(0)); + } + + config()->setGroup("DiskPlugin"); + config()->writeEntry("UseSeperatly", (bool)m_buttonBox->id(m_buttonBox->selected())); + config()->writeEntry("Disks", list); +} + +void DiskConfig::addItem() +{ + bool ok = false; + QString text = KInputDialog::getText(i18n("Add Disk Device"), i18n("Disk name:"), + QString::null, &ok, this); + + if (text.startsWith("/dev/")) + text = text.mid(5); + + if (ok) + new QListViewItem(m_listview, text); +} + +void DiskConfig::removeItem() +{ + if (!m_listview->selectedItem()) + return; + + QListViewItem *item = m_listview->selectedItem(); + delete item; +} diff --git a/ksim/monitors/disk/ksimdisk.h b/ksim/monitors/disk/ksimdisk.h new file mode 100644 index 0000000..de4c8ba --- /dev/null +++ b/ksim/monitors/disk/ksimdisk.h @@ -0,0 +1,154 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIMDISK_H +#define KSIMDISK_H + +#include +#include +#include +#include +#include +#include + +class QTextStream; +class QTimer; +class KListView; +class QVBoxLayout; +class QVButtonGroup; +class QRadioButton; +class QPushButton; +namespace KSim +{ + class Chart; + class Progress; +} + +class DiskPlugin : public KSim::PluginObject +{ + public: + DiskPlugin(const char *name); + ~DiskPlugin(); + + virtual KSim::PluginView *createView(const char *); + virtual KSim::PluginPage *createConfigPage(const char *); + + virtual void showAbout(); +}; + +class DiskView : public KSim::PluginView +{ + Q_OBJECT + public: + DiskView(KSim::PluginObject *parent, const char *name); + ~DiskView(); + + virtual void reparseConfig(); + + private slots: + void updateDisplay(); + + private: + class DiskData + { + public: + DiskData() + { + major = minor = readIO = readBlocks = + writeIO = writeBlocks = 0; + } + + DiskData &operator+=(const DiskData &rhs) + { + total += rhs.total; + readIO += rhs.readIO; + readBlocks += rhs.readBlocks; + writeIO += rhs.writeIO; + writeBlocks += rhs.writeBlocks; + return *this; + } + + DiskData &operator-=(const DiskData &rhs) + { + total -= rhs.total; + readIO -= rhs.readIO; + readBlocks -= rhs.readBlocks; + writeIO -= rhs.writeIO; + writeBlocks -= rhs.writeBlocks; + return *this; + } + + QString name; + int major; + int minor; + unsigned long total; + unsigned long readIO; + unsigned long readBlocks; + unsigned long writeIO; + unsigned long writeBlocks; + }; + + typedef QValueList DiskList; + typedef QPair DiskPair; + + void updateData(DiskList &disks); + QString diskName( int, int ) const; + DiskPair *addDisk(); + DiskData findDiskData(const DiskList& diskList, QString diskName); + + void init(); + void cleanup(); + + QValueVector > m_data; + QTimer *m_timer; + bool m_bLinux24; + FILE *m_procFile; + QTextStream *m_procStream; + QVBoxLayout *m_layout; + QPtrList m_diskList; + int m_firstTime; + bool m_useSeperatly; + QStringList m_list; + bool m_addAll; +}; + +class DiskConfig : public KSim::PluginPage +{ + Q_OBJECT + public: + DiskConfig(KSim::PluginObject *parent, const char *name); + ~DiskConfig(); + + virtual void saveConfig(); + virtual void readConfig(); + + private slots: + void addItem(); + void removeItem(); + + private: + QVBoxLayout *m_layout; + KListView *m_listview; + QPushButton *m_add; + QPushButton *m_remove; + QVButtonGroup *m_buttonBox; + QRadioButton *m_totalButton; + QRadioButton *m_bothButton; +}; +#endif diff --git a/ksim/monitors/filesystem/DFree.desktop b/ksim/monitors/filesystem/DFree.desktop new file mode 100644 index 0000000..78ffdb1 --- /dev/null +++ b/ksim/monitors/filesystem/DFree.desktop @@ -0,0 +1,87 @@ +[Desktop Entry] +Icon=hdd_unmount +Name=DFree +Name[af]=Dfree +Name[bg]=Дялове +Name[ca]=Disc lliure +Name[cs]=Volný disk +Name[eo]=Diskuzo +Name[et]=Vaba kettaruum +Name[he]=מחיצות +Name[hi]=डी-फ्री +Name[it]=Disco libero +Name[kk]=Тіркеген бөлімдер +Name[ko]=디스크 사용량 +Name[ne]=डिफ्रि +Name[pt_BR]=Disco Livre +Name[ru]=Смонтированные разделы +Name[sk]=Voľný disk +Name[sv]=Ledigt diskutrymme +Name[ta]= Dபிரீ +Name[tg]=DОзод +Name[th]=พื้นที่ว่างของดิสก์ +Comment=Mounted Partitions Monitor +Comment[af]=Gekoppelde Partisies Monitor +Comment[ar]=مراقب الأقسام المضمومة +Comment[bg]=Мониторинг на монтираните дялове +Comment[bs]=Nadzor montiranih particija +Comment[ca]=Monitor de les particions muntades +Comment[cs]=Monitor připojených diskových oddílů +Comment[cy]=Monitr Rhaniadau Mowntiedig +Comment[da]=Overvågning af monterede partitioner +Comment[de]=Anzeige für eingebundene Laufwerke +Comment[el]=Επόπτης προσαρτημένων κατατμήσεων +Comment[eo]=Vidigilo por la kroĉitaj subdiskoj +Comment[es]=Monitor de particiones montadas +Comment[et]=Ühendatud partitsioonide monitooring +Comment[eu]=Muntatutako Partizioen Begiralea +Comment[fa]=نمایشگر افرازهای سوارشده +Comment[fi]=Liitettyjen osioiden valvonta +Comment[fr]=Surveillant des lecteurs montés +Comment[ga]=Monatóir Rannta Feistithe +Comment[he]=צג מחיצות מחוברות +Comment[hi]=माउन्टेड पार्टीशन्स मॉनीटर +Comment[hu]=Lemezcsatlakoztatás-figyelő +Comment[is]=Eftirlit með tengdum disksneiðum +Comment[it]=Controllo delle partizioni montate +Comment[ja]=マウントされたパーティションのモニタ +Comment[ka]= მონტირებული პარტიციების მონიტორი +Comment[kk]=Тіркеген бөлімдерді бақылау +Comment[km]=កម្មវិធី​ត្រួតពិនិត្យ​ភាគ​ដែល​បាន​ម៉ោន +Comment[lt]=Sumontuotų skirsnių stebėtojas +Comment[mk]=Монитор на монтираните партиции +Comment[ms]=Pemerhati Partisi yang telah Dilekapkan +Comment[nb]=Overvåkning av monterte partisjoner +Comment[nds]=Kieker för inhangte Partitschonen +Comment[ne]=माउन्ट गरिएको विभाजन मोनिटर +Comment[nl]=Monitor van aangekoppelde partities +Comment[nn]=Overvaking av monterte partisjonar +Comment[pa]=ਮਾਊਂਟ ਭਾਗ ਨਿਗਰਾਨ +Comment[pl]=Stan zamontowanych partycji +Comment[pt]=Monitor de Partições Montadas +Comment[pt_BR]=Monitor das Partições Montadas +Comment[ro]=Monitor partiţii montate +Comment[ru]=Монитор смонтированных разделов +Comment[sk]=Monitor pripojených diskových oddielov +Comment[sl]=Nadzornik priklopljenih razdelkov +Comment[sr]=Надгледање монтираних партиција +Comment[sr@Latn]=Nadgledanje montiranih particija +Comment[sv]=Övervakar monterade partitioner +Comment[ta]=ஏற்றப்பட்ட பகுக்கப்பட்ட கண்காணி +Comment[tg]=Дидабони Қисмҳои Насбшуда +Comment[th]=สอดส่องพาร์ติชันที่เมานท์ไว้แล้ว +Comment[tr]=Bağlanmış Disk Bölümü İzleyici +Comment[uk]=Монітор змонтованих розділів +Comment[uz]=Diskning ulangan qismlarini nazorat qilish plagini +Comment[uz@cyrillic]=Дискнинг уланган қисмларини назорат қилиш плагини +Comment[wa]=Corwaitoe des montêyès pårticions +Comment[xh]=Ulwahlulo Lonyuso lwe Monitor +Comment[zh_CN]=已挂载分区监视器 +Comment[zh_TW]=已掛載的分割區監視器 +Comment[zu]=Umlawuli Wezahlukaniso Ezinyukile +X-KSIM-VERSION=0.1 +X-KSIM-LIBRARY=filesystem +X-KSIM-PREFS=File System +X-KSIM-AUTHOR=Robbie Ward +X-KSIM-EMAIL=linuxphreak@gmx.co.uk +X-KSIM-COPYRIGHT=(C) 2001 Robbie Ward diff --git a/ksim/monitors/filesystem/Makefile.am b/ksim/monitors/filesystem/Makefile.am new file mode 100644 index 0000000..7da7012 --- /dev/null +++ b/ksim/monitors/filesystem/Makefile.am @@ -0,0 +1,16 @@ +kde_module_LTLIBRARIES = ksim_filesystem.la +ksim_filesystem_la_SOURCES = ksimfsystem.cpp fsystemconfig.cpp \ + fsystemiface.skel filesystemwidget.cpp filesystemstats.cpp + +ksim_filesystem_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +ksim_filesystem_la_LIBADD = ../../library/libksimcore.la + +EXTRA_DIST = DFree.desktop + +INCLUDES= -I$(top_srcdir)/ksim/library \ + $(all_includes) + +METASOURCES = AUTO + +mon_DATA = DFree.desktop +mondir = $(kde_datadir)/ksim/monitors diff --git a/ksim/monitors/filesystem/configure.in.in b/ksim/monitors/filesystem/configure.in.in new file mode 100644 index 0000000..8fd7a61 --- /dev/null +++ b/ksim/monitors/filesystem/configure.in.in @@ -0,0 +1,2 @@ +AC_CHECK_HEADERS(sys/mnttab.h mntent.h sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h sys/ucred.h sys/loadavg.h) +AC_CHECK_FUNCS(statvfs) diff --git a/ksim/monitors/filesystem/filesystemstats.cpp b/ksim/monitors/filesystem/filesystemstats.cpp new file mode 100644 index 0000000..eeb5c62 --- /dev/null +++ b/ksim/monitors/filesystem/filesystemstats.cpp @@ -0,0 +1,224 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "filesystemstats.h" + +#include +#include +#include + +#include + +#include + +#include +#include + +#if defined(HAVE_SYS_STATVFS_H) && !defined(__DragonFly__) +#include +#elif defined( HAVE_SYS_STATFS_H ) +#include +#endif +#ifdef HAVE_SYS_VFS_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_MNTENT_H +#include +#ifdef _HPUX_SOURCE +#define _PATH_MOUNTED MNTTAB +#endif +#endif +#ifdef HAVE_SYS_UCRED_H +#include +#endif +#ifdef HAVE_SYS_MNTTAB_H +#include +#undef HAVE_MNTENT_H +#define _PATH_MOUNTED MNTTAB +#endif + +#include +#include + +#if defined(HAVE_STATVFS) && !defined(__DragonFly__) +typedef struct statvfs ksim_statfs; +#define ksim_getfsstat getvfsstat +#elif defined( HAVE_STATFS ) || defined( Q_OS_FREEBSD ) +typedef struct statfs ksim_statfs; +#define ksim_getfsstat getfsstat +#else +typedef struct // fall back for (possibly) non-supported systems +{ + int f_blocks; + int f_bfree; +} ksim_statfs; +#endif + +int fsystemStats( const char * file, ksim_statfs & stats ) +{ +#if defined(HAVE_STATVFS) && !defined(__DragonFly__) + return statvfs( file, &stats ); +#elif defined( HAVE_STATFS ) || defined( Q_OS_FREEBSD ) + return statfs( file, &stats ); +#else // fall back for (possibly) non-supported systems + (void)file; + + stats.f_blocks = 0; + stats.f_bfree = 0; + return -1; +#endif +} + +#ifdef HAVE_SYS_MNTTAB_H +#define USE_MNTENT + +typedef struct +{ + const char * mnt_dir; + const char * mnt_fsname; + const char * mnt_type; +} ksim_mntent; + +FILE * setmntent( const char * mtab, const char * mode ) +{ + return fopen( mtab, mode ); +} + +int endmntent( FILE * file ) +{ + return fclose( file ); +} + +ksim_mntent * ksim_getmntent( FILE * file ) +{ + ksim_mntent * entry; + struct mnttab tab; + + if ( getmntent( file, &tab ) != 0 ) + return NULL; + + entry = new ksim_mntent; + entry->mnt_dir = tab.mnt_mountp; + entry->mnt_fsname = tab.mnt_special; + entry->mnt_type = tab.mnt_fstype; + return entry; +} + +#define delete_mntent( x ) delete x +#elif defined( HAVE_MNTENT_H ) +#define USE_MNTENT + +// Dummy setup +typedef struct mntent ksim_mntent; +ksim_mntent * ksim_getmntent( FILE * file ) +{ + return getmntent( file ); +} + +#define delete_mntent( x ) +#elif defined( HAVE_SYS_UCRED_H ) || defined( HAVE_SYS_MOUNT_H ) +#define USE_FSSTAT +#else +#define USE_FAILSAFE +#endif + +FilesystemStats::List FilesystemStats::readEntries() +{ + List list; + +#ifdef USE_MNTENT + FILE * fp = setmntent( _PATH_MOUNTED, "r" ); + ksim_mntent * point; + + while ( ( point = ksim_getmntent( fp ) ) != 0 ) + { + Entry entry; + entry.dir = point->mnt_dir; + entry.fsname = point->mnt_fsname; + entry.type = point->mnt_type; + list.append( entry ); + + delete_mntent( point ); + } + + endmntent( fp ); +#endif + +#ifdef USE_FSSTAT + ksim_statfs sfs[32]; + int fs_count; + if ( ( fs_count = ksim_getfsstat( sfs, sizeof( sfs ), 0 ) ) != -1 ) + { + for ( int i = 0; i < fs_count; i++ ) + { + Entry entry; + entry.dir = sfs[i].f_mntonname; + entry.fsname = sfs[i].f_mntfromname; + +#ifndef __osf__ + entry.type = sfs[i].f_fstypename; +#endif + + list.append( entry ); + } + } +#endif + +#ifdef USE_FAILSAFE + QFile file( QString::fromLatin1( _PATH_MOUNTED ) ); + + if ( !file.open( IO_ReadOnly ) ) + return list; + + QTextStream stream( &file ); + + while ( !stream.atEnd() ) + { + QStringList line = QStringList::split( " ", stream.readLine() ); + + Entry entry; + entry.dir = line[1].stripWhiteSpace(); + entry.fsname = line[0].stripWhiteSpace(); + entry.type = line[2].stripWhiteSpace(); + list.append( entry ); + } +#endif + + return list; +} + +bool FilesystemStats::readStats( const QString & mntPoint, int & totalBlocks, int & freeBlocks ) +{ + ksim_statfs sysStats; + if ( fsystemStats( QFile::encodeName( mntPoint ).data(), sysStats ) < 0 ) + { + kdError() << "While reading filesystem information for " << mntPoint << endl; + totalBlocks = 0; + freeBlocks = 0; + } + + totalBlocks = sysStats.f_blocks; + freeBlocks = sysStats.f_bfree; + + // Return true if our filesystem is statable + return totalBlocks > 0; +} diff --git a/ksim/monitors/filesystem/filesystemstats.h b/ksim/monitors/filesystem/filesystemstats.h new file mode 100644 index 0000000..3ea8f74 --- /dev/null +++ b/ksim/monitors/filesystem/filesystemstats.h @@ -0,0 +1,40 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FILESYSTEMSTATS_H +#define FILESYSTEMSTATS_H + +#include +#include + +namespace FilesystemStats +{ + struct Entry + { + QString dir; + QString fsname; + QString type; + }; + + typedef QValueList List; + List readEntries(); + bool readStats( const QString &, int &, int & ); + +} +#endif diff --git a/ksim/monitors/filesystem/filesystemwidget.cpp b/ksim/monitors/filesystem/filesystemwidget.cpp new file mode 100644 index 0000000..0428ee3 --- /dev/null +++ b/ksim/monitors/filesystem/filesystemwidget.cpp @@ -0,0 +1,232 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "filesystemwidget.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +FilesystemWidget::Filesystem::Filesystem() +{ + m_display = 0; +} + +FilesystemWidget::Filesystem::Filesystem(KSim::Progress *display, + const QString &point) +{ + m_display = display; + m_mountPoint = point; +} + +FilesystemWidget::Filesystem::~Filesystem() +{ + delete m_display; +} + +KSim::Progress *FilesystemWidget::Filesystem::display() const +{ + return m_display; +} + +const QString &FilesystemWidget::Filesystem::mountPoint() const +{ + return m_mountPoint; +} + +const QString &FilesystemWidget::Filesystem::text() const +{ + return m_display->text(); +} + +int FilesystemWidget::Filesystem::value() const +{ + return m_display->value(); +} + +void FilesystemWidget::Filesystem::setText(const QString &text) +{ + if (!m_display) + return; + + m_display->setText(text); +} + +void FilesystemWidget::Filesystem::setValue(int value) +{ + if (!m_display) + return; + + m_display->setValue(value); +} + +FilesystemWidget::FilesystemWidget(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + m_list.setAutoDelete(true); + m_layout = new QVBoxLayout(this); + m_process = 0; +} + +FilesystemWidget::~FilesystemWidget() +{ + delete m_process; +} + +void FilesystemWidget::append(int max, const QString &mountPoint) +{ + KSim::Progress *progress = new KSim::Progress(max, this); + progress->installEventFilter(this); + progress->show(); + m_layout->addWidget(progress); + + m_list.append(new Filesystem(progress, mountPoint)); +} + +void FilesystemWidget::setText(uint id, const QString &text) +{ + if (id > m_list.count()) + return; + + m_list.at(id)->setText(text); +} + +void FilesystemWidget::setValue(uint id, int value) +{ + if (id > m_list.count()) + return; + + m_list.at(id)->setValue(value); +} + +void FilesystemWidget::clear() +{ + m_list.clear(); +} + +bool FilesystemWidget::eventFilter(QObject *o, QEvent *e) +{ + if (!o->isA("KSim::Progress")) + return QWidget::eventFilter(o, e); + + KSim::Progress *progressBar = 0; + int i = 0; + QPtrListIterator it(m_list); + Filesystem *filesystem; + while ((filesystem = it.current()) != 0) { + ++it; + + if (filesystem->display() == o) { + progressBar = filesystem->display(); + break; + } + + ++i; + } + + if (o == progressBar && e->type() == QEvent::MouseButtonPress) + { + switch(static_cast(e)->button()) { + case QMouseEvent::RightButton: + showMenu(i); + break; + default: + break; + case QMouseEvent::LeftButton: + if (parentWidget()->inherits("KSim::PluginView")) + static_cast(parentWidget())->doCommand(); + break; + } + + return true; + } + + return QWidget::eventFilter(o, e); +} + +void FilesystemWidget::receivedStderr(KProcess *, char *buffer, int length) +{ + m_stderrString.setLatin1(buffer, length); +} + +void FilesystemWidget::processExited(KProcess *) +{ + delete m_process; + m_process = 0; + kdDebug(2003) << "Deleting KProcess pointer" << endl; + + if (m_stderrString.isEmpty()) + return; + + QStringList errorList = QStringList::split("\n", m_stderrString); + QString message = i18n("The following errors occurred:
      "); + + QStringList::Iterator it; + for (it = errorList.begin(); it != errorList.end(); ++it) { + message += QString::fromLatin1("
    • %1
    • ") + .arg((*it).replace(QRegExp("[u]?mount: "), QString::null)); + } + + message += QString::fromLatin1("
    "); + KMessageBox::sorry(0, message); +} + +void FilesystemWidget::createProcess(const QString &command, const QString &point) +{ + m_process = new KProcess(); + connect(m_process, + SIGNAL(receivedStderr(KProcess *, char *, int)), + SLOT(receivedStderr(KProcess *, char *, int))); + connect(m_process, + SIGNAL(processExited(KProcess *)), + SLOT(processExited(KProcess *))); + + (*m_process) << command << point; + void(m_process->start(KProcess::NotifyOnExit, KProcess::Stderr)); +} + +void FilesystemWidget::showMenu(uint id) +{ + if (id > m_list.count()) + return; + + QPopupMenu menu; + menu.insertItem(SmallIcon("hdd_mount"), i18n("&Mount Device"), 1); + menu.insertItem(SmallIcon("hdd_unmount"), i18n("&Unmount Device"), 2); + + switch (menu.exec(QCursor::pos())) { + case 1: + createProcess("mount", m_list.at(id)->mountPoint()); + break; + case 2: + createProcess("umount", m_list.at(id)->mountPoint()); + break; + } +} + +#include "filesystemwidget.moc" diff --git a/ksim/monitors/filesystem/filesystemwidget.h b/ksim/monitors/filesystem/filesystemwidget.h new file mode 100644 index 0000000..d169b9a --- /dev/null +++ b/ksim/monitors/filesystem/filesystemwidget.h @@ -0,0 +1,78 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FSYSTEM_WIDGET_H +#define FSYSTEM_WIDGET_H + +#include + +#include + +class KProcess; +class QVBoxLayout; + +class FilesystemWidget : public QWidget +{ + Q_OBJECT + public: + FilesystemWidget(QWidget *parent, const char *name); + ~FilesystemWidget(); + + void append(int, const QString &); + void setText(uint, const QString &); + void setValue(uint, int); + void clear(); + + protected: + bool eventFilter(QObject *, QEvent *); + + private slots: + void receivedStderr(KProcess *, char *, int); + void processExited(KProcess *); + + private: + class Filesystem + { + public: + Filesystem(); + Filesystem(KSim::Progress *, const QString &); + ~Filesystem(); + + KSim::Progress *display() const; + const QString &mountPoint() const; + const QString &text() const; + int value() const; + + void setText(const QString &); + void setValue(int); + + QString m_mountPoint; + KSim::Progress *m_display; + }; + + void createProcess(const QString &, const QString &); + void showMenu(uint); + + typedef QPtrList ProgressList; + ProgressList m_list; + QVBoxLayout *m_layout; + KProcess *m_process; + QString m_stderrString; +}; +#endif diff --git a/ksim/monitors/filesystem/fsystemconfig.cpp b/ksim/monitors/filesystem/fsystemconfig.cpp new file mode 100644 index 0000000..9b07ee4 --- /dev/null +++ b/ksim/monitors/filesystem/fsystemconfig.cpp @@ -0,0 +1,184 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "fsystemconfig.h" +#include "fsystemconfig.moc" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class FSysViewItem : public QCheckListItem +{ + public: + FSysViewItem(QListView *parent, const QString &text1, + const QString &text2, const QString &text3) + : QCheckListItem(parent, text1, CheckBox) + { + setText(1, text2); + setText(2, text3); + } +}; + +FsystemConfig::FsystemConfig(KSim::PluginObject *parent, const char *name) + : KSim::PluginPage(parent, name) +{ + m_mainLayout = new QGridLayout(this); + m_mainLayout->setSpacing(6); + + m_availableMounts = new KListView(this); + m_availableMounts->addColumn(i18n("Mounted Partition")); + m_availableMounts->addColumn(i18n("Device")); + m_availableMounts->addColumn(i18n("Type")); + m_mainLayout->addMultiCellWidget(m_availableMounts, 0, 0, 0, 3); + + m_showPercentage = new QCheckBox(this); + m_showPercentage->setText(i18n("Show percentage")); + m_mainLayout->addMultiCellWidget(m_showPercentage, 1, 1, 0, 3); + + m_splitNames = new QCheckBox(this); + m_splitNames->setText(i18n("Display short mount point names")); + QWhatsThis::add(m_splitNames, i18n("This option shortens the text" + " to shrink down a mount point. E.G: a mount point /home/myuser" + " would become myuser.")); + m_mainLayout->addMultiCellWidget(m_splitNames, 2, 2, 0, 3); + + m_intervalLabel = new QLabel(this); + m_intervalLabel->setText( i18n("Update interval:")); + m_intervalLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, + QSizePolicy::Fixed)); + m_mainLayout->addMultiCellWidget(m_intervalLabel, 3, 3, 0, 0); + + m_updateTimer = new KIntSpinBox(this); + m_updateTimer->setValue(60); + QToolTip::add(m_updateTimer, i18n("0 means no update")); + m_mainLayout->addMultiCellWidget(m_updateTimer, 3, 3, 1, 1); + + QLabel *intervalLabel = new QLabel(this); + intervalLabel->setText(i18n("seconds")); + intervalLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, + QSizePolicy::Fixed)); + m_mainLayout->addMultiCellWidget(intervalLabel, 3, 3, 2, 2); + + m_entries = FilesystemStats::readEntries(); + getStats(); +} + +FsystemConfig::~FsystemConfig() +{ +} + +void FsystemConfig::readConfig() +{ + config()->setGroup("Fsystem"); + m_showPercentage->setChecked(config()->readBoolEntry("ShowPercentage", true)); + m_updateTimer->setValue(config()->readNumEntry("updateValue", 60)); + m_splitNames->setChecked(config()->readBoolEntry("ShortenEntries", false)); + + if (!m_availableMounts->childCount()) + return; + + QStringList list = config()->readListEntry("mountEntries"); + for (QListViewItemIterator it(m_availableMounts); it.current(); ++it) { + QString string = it.current()->text(0) + ":" + splitString(it.current()->text(0)); + static_cast(it.current())->setOn(list.contains(string) > 0); + } +} + +void FsystemConfig::saveConfig() +{ + config()->setGroup("Fsystem"); + config()->writeEntry("ShowPercentage", m_showPercentage->isChecked()); + config()->writeEntry("updateValue", m_updateTimer->value()); + config()->writeEntry("ShortenEntries", m_splitNames->isChecked()); + + QStringList list; + for (QListViewItemIterator it(m_availableMounts); it.current(); ++it) { + if (static_cast(it.current())->isOn()) + list.append(it.current()->text(0) + ":" + splitString(it.current()->text(0))); + } + + config()->writeEntry("mountEntries", list); +} + +void FsystemConfig::showEvent(QShowEvent *) +{ + // FIXME: Maybe this is the slow method of doing this? + // Eitherway, i need to find a way to only update the list + // if the amount of mounted partitions has changed + FilesystemStats::List entries = FilesystemStats::readEntries(); + if ( entries.count() == m_entries.count() ) + return; + + m_entries = entries; + + // Update the entries to take into account + // any mounted/unmounted filesystems + m_availableMounts->clear(); + getStats(); +} + +void FsystemConfig::getStats() +{ + int total = 0; + int free = 0; + + FilesystemStats::List::ConstIterator it; + for ( it = m_entries.begin(); it != m_entries.end(); ++it ) + { + if ( !FilesystemStats::readStats( ( *it ).dir, total, free ) ) + continue; + + if ( !m_availableMounts->findItem( ( *it ).dir, 0 ) ) + { + (void) new FSysViewItem( m_availableMounts, ( *it ).dir, + ( *it ).fsname, ( *it ).type ); + } + } + + if (!m_availableMounts->childCount()) + return; + + config()->setGroup("Fsystem"); + QStringList list = config()->readListEntry("mountEntries"); + for (QListViewItemIterator it(m_availableMounts); it.current(); ++it) { + QString string = it.current()->text(0) + ":" + splitString(it.current()->text(0)); + static_cast(it.current())->setOn(list.contains(string) > 0); + } +} + +QString FsystemConfig::splitString(const QString &string) const +{ + if (string == "/" || !m_splitNames->isChecked()) + return string; + + int location = string.findRev("/"); + QString newString(string); + return newString.remove(0, location + 1); +} diff --git a/ksim/monitors/filesystem/fsystemconfig.h b/ksim/monitors/filesystem/fsystemconfig.h new file mode 100644 index 0000000..353dcf8 --- /dev/null +++ b/ksim/monitors/filesystem/fsystemconfig.h @@ -0,0 +1,58 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FSYSTEMCONFIG_H +#define FSYSTEMCONFIG_H + +#include +#include "filesystemstats.h" + +class KIntSpinBox; +class KListView; +class QGridLayout; +class QCheckBox; +class QLabel; +class QListBoxItem; + +class FsystemConfig : public KSim::PluginPage +{ + Q_OBJECT + public: + FsystemConfig(KSim::PluginObject *parent, const char *name); + ~FsystemConfig(); + + virtual void saveConfig(); + virtual void readConfig(); + + protected: + void showEvent(QShowEvent *); + + private: + void getStats(); + QString splitString(const QString &string) const; + + QCheckBox *m_showPercentage; + QCheckBox *m_splitNames; + QLabel *m_intervalLabel; + KIntSpinBox *m_updateTimer; + KListView *m_availableMounts; + QGridLayout *m_mainLayout; + FilesystemStats::List m_entries; +}; +#endif // FILESYSTEM_H diff --git a/ksim/monitors/filesystem/fsystemiface.h b/ksim/monitors/filesystem/fsystemiface.h new file mode 100644 index 0000000..d590776 --- /dev/null +++ b/ksim/monitors/filesystem/fsystemiface.h @@ -0,0 +1,32 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 - 2004 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FSYSTEMIFACE_H +#define FSYSTEMIFACE_H + +#include + +class FsystemIface : virtual public DCOPObject +{ + K_DCOP + k_dcop: + virtual int totalFreeSpace() const = 0; +}; + +#endif // FSYSTEMIFACE_H diff --git a/ksim/monitors/filesystem/ksimfsystem.cpp b/ksim/monitors/filesystem/ksimfsystem.cpp new file mode 100644 index 0000000..3303f6d --- /dev/null +++ b/ksim/monitors/filesystem/ksimfsystem.cpp @@ -0,0 +1,202 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * $Id$ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ksimfsystem.h" +#include "fsystemconfig.h" +#include "filesystemwidget.h" +#include "filesystemstats.h" +#include + +KSIM_INIT_PLUGIN(PluginModule) + +PluginModule::PluginModule(const char *name) + : KSim::PluginObject(name) +{ + setConfigFileName(instanceName()); +} + +PluginModule::~PluginModule() +{ +} + +KSim::PluginView *PluginModule::createView(const char *className) +{ + return new Fsystem(this, className); +} + +KSim::PluginPage *PluginModule::createConfigPage(const char *className) +{ + return new FsystemConfig(this, className); +} + +void PluginModule::showAbout() +{ + QString version = kapp->aboutData()->version(); + + KAboutData aboutData(instanceName(), + I18N_NOOP("KSim FileSystem Plugin"), version.latin1(), + I18N_NOOP("A filesystem plugin for KSim"), + KAboutData::License_GPL, "(C) 2001 Robbie Ward"); + + aboutData.addAuthor("Robbie Ward", I18N_NOOP("Author"), + "linuxphreak@gmx.co.uk"); + aboutData.addAuthor("Jason Katz-Brown", I18N_NOOP("Some Fixes"), + "jason@katzbrown.com"); + aboutData.addAuthor("Heitham Omar", I18N_NOOP("FreeBSD ports"), + "super_ice@ntlworld.com"); + + KAboutApplication(&aboutData).exec(); +} + +Fsystem::Fsystem(KSim::PluginObject *parent, const char *name) + : DCOPObject("fsystem"), + KSim::PluginView(parent, name) +{ + config()->setGroup("Fsystem"); + QVBoxLayout *vbLayout = new QVBoxLayout(this); + vbLayout->setAutoAdd(true); + + QSpacerItem *item = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding); + vbLayout->addItem(item); + + m_mountEntries = makeList(config()->readListEntry("mountEntries")); + m_showPercentage = config()->readBoolEntry("ShowPercentage", true); + + m_widget = new FilesystemWidget(this, "FilesystemWidget"); + + createFreeInfo(); + + m_updateTimer = new QTimer(this); + connect(m_updateTimer, SIGNAL(timeout()), SLOT(updateFS())); + m_updateTimer->start(config()->readNumEntry("updateValue", 60) * 1000); +} + +Fsystem::~Fsystem() +{ +} + +void Fsystem::reparseConfig() +{ + config()->setGroup("Fsystem"); + + m_showPercentage = config()->readBoolEntry("ShowPercentage", true); + MountEntryList mountEntries = makeList(config()->readListEntry("mountEntries")); + + if (m_mountEntries != mountEntries) { + m_widget->clear(); + m_mountEntries = mountEntries; + createFreeInfo(); + } + + updateFS(); +} + +int Fsystem::totalFreeSpace() const +{ + int totalSize, totalFree; + int totalFreeSpace = 0; + MountEntryList::ConstIterator it; + for (it = m_mountEntries.begin(); it != m_mountEntries.end(); ++it) { + if ( FilesystemStats::readStats( ( *it ).first, totalSize, totalFree ) ) + totalFreeSpace += totalFree; + } + + return totalFreeSpace; +} + +void Fsystem::createFreeInfo() +{ + int total, free; + int i = 0; + MountEntryList::ConstIterator it; + for (it = m_mountEntries.begin(); it != m_mountEntries.end(); ++it) { + // returns the total space and free space from *it + // (the current mounted partition) + if ( !FilesystemStats::readStats( ( *it ).first, total, free ) ) + continue; + + int percent = 0; + if( total != 0) + percent = ((total - free) * 100) / total; + m_widget->append(total, (*it).first); + m_widget->setValue(i, total - free); + if (m_showPercentage) + m_widget->setText(i, ((*it).second.isEmpty() ? (*it).first : (*it).second) + + " - " + QString::number(percent) + "%"); + else + m_widget->setText(i, ((*it).second.isEmpty() ? (*it).first : (*it).second)); + i++; + } +} + +void Fsystem::updateFS() +{ + int total, free; + int i = 0; + MountEntryList::ConstIterator it; + for (it = m_mountEntries.begin(); it != m_mountEntries.end(); ++it) { + // returns the total space and free space from *it + // (the current mounted partition) + if ( !FilesystemStats::readStats( ( *it ).first, total, free ) ) + continue; + + int percent = 0; + if( total != 0 ) + percent = ((total - free) * 100) / total; + m_widget->setValue(i, total - free); + if (m_showPercentage) + m_widget->setText(i, ((*it).second.isEmpty() ? (*it).first : (*it).second) + + " - " + QString::number(percent) + "%"); + else + m_widget->setText(i, ((*it).second.isEmpty() ? (*it).first : (*it).second)); + i++; + } +} + +Fsystem::MountEntryList Fsystem::makeList(const QStringList &list) const +{ + MountEntryList newList; + QStringList splitList; + QStringList::ConstIterator it; + for (it = list.begin(); it != list.end(); ++it) { + splitList = QStringList::split(":", (*it)); + newList.append(qMakePair(splitList[0], splitList[1])); + } + + return newList; +} + +#include "ksimfsystem.moc" diff --git a/ksim/monitors/filesystem/ksimfsystem.h b/ksim/monitors/filesystem/ksimfsystem.h new file mode 100644 index 0000000..c3d403f --- /dev/null +++ b/ksim/monitors/filesystem/ksimfsystem.h @@ -0,0 +1,76 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FSYSTEM_H +#define FSYSTEM_H + +#include +#include "fsystemiface.h" + +class KPopupMenu; +class FilesystemWidget; +class QTimer; + +/** + * This class is the filesystem monitor plugin + * + * @author Robbie Ward + * @version 0.1 + */ +class PluginModule : public KSim::PluginObject +{ + public: + PluginModule(const char *name); + ~PluginModule(); + + virtual KSim::PluginView *createView(const char *); + virtual KSim::PluginPage *createConfigPage(const char *); + + virtual void showAbout(); +}; + +class Fsystem : public KSim::PluginView, public FsystemIface +{ + Q_OBJECT + public: + /** + * construtor of Fsystem, calls all init functions to create the plugin. + */ + Fsystem(KSim::PluginObject *parent, const char *name); + ~Fsystem(); + + virtual void reparseConfig(); + int totalFreeSpace() const; + + public slots: + void createFreeInfo(); + + private slots: + void updateFS(); + + private: + typedef QValueList > MountEntryList; + MountEntryList makeList(const QStringList &list) const; + + FilesystemWidget *m_widget; + QTimer *m_updateTimer; + MountEntryList m_mountEntries; + bool m_showPercentage; +}; +#endif diff --git a/ksim/monitors/i8k/Makefile.am b/ksim/monitors/i8k/Makefile.am new file mode 100644 index 0000000..d46a0d9 --- /dev/null +++ b/ksim/monitors/i8k/Makefile.am @@ -0,0 +1,15 @@ +kde_module_LTLIBRARIES = ksim_i8k.la +ksim_i8k_la_SOURCES = ksimi8k.cpp + +ksim_i8k_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +ksim_i8k_la_LIBADD = ../../library/libksimcore.la + +EXTRA_DIST = i8k.desktop + +INCLUDES= -I$(top_srcdir)/ksim/library \ + $(all_includes) + +METASOURCES = AUTO + +mon_DATA = i8k.desktop +mondir = $(kde_datadir)/ksim/monitors diff --git a/ksim/monitors/i8k/i8k.desktop b/ksim/monitors/i8k/i8k.desktop new file mode 100644 index 0000000..322fda3 --- /dev/null +++ b/ksim/monitors/i8k/i8k.desktop @@ -0,0 +1,62 @@ +[Desktop Entry] +Comment=Dell I8K Hardware Monitor Plugin +Comment[ar]=ملحق لمراقبة عتاد Dell I8K +Comment[bg]=Мониторинг на Dell I8K +Comment[bs]=Dell I8K dodatak za nadzor hardvera +Comment[ca]=Connector per a controlar el maquinari Dell I8K +Comment[cs]=Modul sledování hardwaru pro Dell I8K +Comment[cy]=Ategyn Arsylwydd Caledwedd Dell I8K +Comment[de]=Dell I8K Hardware Überwachungs-Plugin +Comment[el]=Πρόσθετο εποπτείας υλικού Dell I8K +Comment[es]=Extensión de monitorización de hardware para Dell I8K +Comment[et]=Dell I8K riistvara monitooringu plugin +Comment[eu]=Dell I8K Hardwarearen Plugin Begiralea +Comment[fa]=وصلۀ نمایشگر سخت‌افزار Dell I8K +Comment[fi]=Dell I8K-laitteistomonitoriliitännäinen +Comment[fr]=Module de surveillance du Dell l8K +Comment[ga]=Breiseán Monatóireachta Cruaearraí Dell I8K +Comment[hi]=डेल I8K हार्डवेयर मॉनीटर प्लगइन +Comment[hu]=Dell I8K hardvermonitor bővítőmodul +Comment[is]=Íforrit til að fylgjast með Dell I8K vélbúnaði +Comment[it]=Plugin di controllo hardware Dell I8K +Comment[ja]=Dell I8K ハードウェアモニタプラグイン +Comment[ka]=Dell I8K მოწყობილობათა მონიტორის მოდული +Comment[kk]=Dell I8K жабдықтарын бақылау модулі +Comment[km]=កម្មវិធី​ជំនួយ​របស់​កម្មវិធី​ត្រួតពិនិត្យផ្នែករឹង Dell I8K +Comment[lt]=Dell I8K aparatinės įrangos stebėjimo priedas +Comment[mk]=Приклучок за следење на хардверот Dell I8K +Comment[ms]=Plug masuk Pemerhati Perkakasan Dell I8K +Comment[nb]=Programtillegg for overvåkning av maskinvare Dell I8K +Comment[nds]=Kiekmoduul för Dell I8K-Hardware +Comment[ne]=डेल I8K हार्डवेयर मोनिटर प्लगइन +Comment[nl]=Dell I8000 Hardware Monitor-plugin +Comment[nn]=Programtillegg for overvaking av Dell I8K-maskinvare +Comment[pa]=Dell I8K ਜੰਤਰ ਨਿਗਰਾਨ ਪਲੱਗਿੰਨ +Comment[pl]=Wtyczka monitorowania Dell I8K +Comment[pt]='Plugin' de monitorização de hardware para o Dell I8K +Comment[pt_BR]=Plug-in de monitoramento do Hardware Dell I8K +Comment[ro]=Modul monitorizare Dell I8K +Comment[ru]=Модуль монитора оборудования Dell I8K +Comment[sk]=Modul pre monitorovanie hardware Dell I8K +Comment[sl]=Vstavek za opazovanje strojne opreme Dell I8K +Comment[sr]=Прикључак за надгледање Dell-овог I8K хардвера +Comment[sr@Latn]=Priključak za nadgledanje Dell-ovog I8K hardvera +Comment[sv]=Insticksprogram för Dell I8K-övervakning +Comment[ta]=டெல்I8K வன்பொருள் கண்காணி சொருகுபொருள் +Comment[tg]=Модули Дидабони Сахтафзори Dell I8K +Comment[tr]=Dell I8K Donanım Monitör Plugini +Comment[uk]=Втулок датчика апаратного забезпечення Dell I8K +Comment[wa]=Tchôke-divins di corwaitaedje di l' éndjolreye pol Dell I8K +Comment[zh_CN]=Dell I8K 硬件邮件监视器插件 +Comment[zh_TW]=Dell I8K 硬體監視器外掛程式 +Icon=hdd_mount +Name=Dell I8K +Name[fr]=Dell l8K +Name[he]=Dell l8k +Name[hi]=डेल I8K +Name[nb]=Dell 18K +Name[ne]=डेल I8K +Name[sr]=Dell-ов I8K +Name[sr@Latn]=Dell-ov I8K +Name[ta]= டெல் I8K +X-KSIM-LIBRARY=i8k diff --git a/ksim/monitors/i8k/ksimi8k.cpp b/ksim/monitors/i8k/ksimi8k.cpp new file mode 100644 index 0000000..ff995b0 --- /dev/null +++ b/ksim/monitors/i8k/ksimi8k.cpp @@ -0,0 +1,257 @@ +/* Dell i8K Hardware Monitor Plug-in for KSim + * + * Copyright (C) 2003 Nadeem Hasan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "ksimi8k.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +KSIM_INIT_PLUGIN(I8KPlugin); + +I8KPlugin::I8KPlugin(const char *name) + : KSim::PluginObject(name) +{ + setConfigFileName(instanceName()); +} + +I8KPlugin::~I8KPlugin() +{ +} + +KSim::PluginView *I8KPlugin::createView(const char *className) +{ + return new I8KView(this, className); +} + +KSim::PluginPage *I8KPlugin::createConfigPage(const char *className) +{ + return new I8KConfig(this, className); +} + +void I8KPlugin::showAbout() +{ + QString version = kapp->aboutData()->version(); + + KAboutData aboutData(instanceName(), + I18N_NOOP("KSim I8K Plugin"), version.latin1(), + I18N_NOOP("Dell I8K Hardware Monitor plugin"), + KAboutData::License_GPL, "(C) 2003 Nadeem Hasan"); + + aboutData.addAuthor("Nadeem Hasan", I18N_NOOP("Author"), + "nhasan@kde.org"); + + KAboutApplication(&aboutData).exec(); +} + +I8KView::I8KView(KSim::PluginObject *parent, const char *name) + : KSim::PluginView(parent, name), + m_timer( 0L ), m_procFile( 0L ), m_procStream( 0L ) +{ + initGUI(); + + m_timer = new QTimer( this ); + + m_reData = new QRegExp( "\\S+\\s+\\S+\\s+\\S+\\s+(\\d+)\\s+\\S+" + "\\s+\\S+\\s+(\\d+)\\s+(\\d+)\\s+\\S+\\s+\\S+" ); + + openStream(); + reparseConfig(); +} + +I8KView::~I8KView() +{ + closeStream(); + + delete m_timer; + delete m_reData; +} + +void I8KView::reparseConfig() +{ + config()->setGroup("I8KPlugin"); + + m_unit = config()->readEntry( "Unit", "C" ); + m_interval = config()->readNumEntry( "Interval", 5 ); + + if ( m_procStream ) + { + m_timer->stop(); + m_timer->start( m_interval*1000 ); + } + + updateView(); +} + +void I8KView::openStream() +{ + kdDebug( 2003 ) << "i8k: Trying /proc/i8k...." << endl; + + m_timer->stop(); + + if ( ( m_procFile = fopen( "/proc/i8k", "r" ) ) ) + { + m_procStream = new QTextIStream( m_procFile ); + disconnect( m_timer, 0, 0, 0 ); + connect( m_timer, SIGNAL( timeout() ), SLOT( updateView() ) ); + m_timer->start( m_interval*1000 ); + + kdDebug( 2003 ) << "i8k: Success" << endl; + } + else + { + // i8k module is not loaded. Try again after 30 secs. + disconnect( m_timer, 0, 0, 0 ); + connect( m_timer, SIGNAL( timeout() ), SLOT( openStream() ) ); + m_timer->start( 30*1000 ); + kdDebug( 2003 ) << "i8k: Failed...retry after 30 secs" << endl; + } +} + +void I8KView::closeStream() +{ + if ( m_procFile ) + fclose( m_procFile ); + + if ( m_procStream ) + delete m_procStream; + + m_procFile = 0L; + m_procStream = 0L; + m_timer->stop(); +} + +void I8KView::initGUI() +{ + QVBoxLayout *layout = new QVBoxLayout( this ); + + m_fan1Label = new KSim::Label( this ); + m_fan2Label = new KSim::Label( this ); + m_tempLabel = new KSim::Label( this ); + + layout->addWidget( m_fan1Label ); + layout->addWidget( m_fan2Label ); + layout->addWidget( m_tempLabel ); +} + +void I8KView::updateView() +{ + kdDebug( 2003 ) << "i8k: Updating..." << endl; + int cputemp=0, rightspeed=0, leftspeed=0; + + if ( m_procStream ) + { + fseek( m_procFile, 0L, SEEK_SET ); + + QString line = m_procStream->read(); + + if ( line.isEmpty() ) + { + // i8k module is no longer available, is it possible? + closeStream(); + openStream(); + return; + } + + if ( m_reData->search( line ) > -1 ) + { + QStringList matches = m_reData->capturedTexts(); + + cputemp = matches[ 1 ].toInt(); + leftspeed = matches[ 2 ].toInt(); + rightspeed = matches[ 3 ].toInt(); + + if ( m_unit == "F" ) + cputemp = ( cputemp*9/5 ) + 32; + } + } + + if ( rightspeed > 0 ) + m_fan1Label->setText( i18n( "Right fan: %1 RPM" ).arg( rightspeed ) ); + else + m_fan1Label->setText( i18n( "Right fan: Off" ) ); + + if ( leftspeed > 0 ) + m_fan2Label->setText( i18n( "Left fan: %1 RPM" ).arg( leftspeed ) ); + else + m_fan2Label->setText( i18n( "Left fan: Off" ) ); + + m_tempLabel->setText( i18n( "CPU temp: %1°%2" ).arg( cputemp ) + .arg( m_unit ) ); +} + +I8KConfig::I8KConfig(KSim::PluginObject *parent, const char *name) + : KSim::PluginPage(parent, name) +{ + m_unit = new QCheckBox( i18n( "Show temperature in Fahrenheit" ), + this ); + QLabel *label = new QLabel( i18n( "Update interval:" ), this ); + m_interval = new KIntNumInput( this ); + m_interval->setRange( 2, 60, 1, true ); + m_interval->setSuffix( i18n( " sec" ) ); + + QGridLayout *layout = new QGridLayout( this, 3, 2, 0, + KDialog::spacingHint() ); + + layout->addMultiCellWidget( m_unit, 0, 0, 0, 1 ); + layout->addWidget( label, 1, 0 ); + layout->addWidget( m_interval, 1, 1 ); + layout->setColStretch( 1, 1 ); + layout->setRowStretch( 2, 1 ); +} + +I8KConfig::~I8KConfig() +{ +} + +void I8KConfig::readConfig() +{ + config()->setGroup("I8KPlugin"); + + QString unit = config()->readEntry( "Unit", "C" ); + int interval = config()->readNumEntry( "Interval", 5 ); + + m_unit->setChecked( unit == "F" ); + m_interval->setValue( interval ); +} + +void I8KConfig::saveConfig() +{ + config()->setGroup("I8KPlugin"); + + config()->writeEntry( "Unit", m_unit->isChecked()? "F" : "C" ); + config()->writeEntry( "Interval", m_interval->value() ); +} + +#include "ksimi8k.moc" + +/* vim: et sw=2 ts=2 +*/ diff --git a/ksim/monitors/i8k/ksimi8k.h b/ksim/monitors/i8k/ksimi8k.h new file mode 100644 index 0000000..4357508 --- /dev/null +++ b/ksim/monitors/i8k/ksimi8k.h @@ -0,0 +1,102 @@ +/* Dell i8K Hardware Monitor Plug-in for KSim + * + * Copyright (C) 2003 Nadeem Hasan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIMI8K_H +#define KSIMI8K_H + +#include + +#include + +class QTimer; +class QTextIStream; +class QRegExp; +class QCheckBox; +class KIntNumInput; + +namespace KSim +{ + class Label; +} + +class I8KPlugin : public KSim::PluginObject +{ + public: + I8KPlugin(const char *name); + ~I8KPlugin(); + + virtual KSim::PluginView *createView(const char *); + virtual KSim::PluginPage *createConfigPage(const char *); + + virtual void showAbout(); +}; + +class I8KView : public KSim::PluginView +{ + Q_OBJECT + public: + I8KView(KSim::PluginObject *parent, const char *name); + ~I8KView(); + + virtual void reparseConfig(); + + protected: + + void initGUI(); + void closeStream(); + + protected slots: + + void openStream(); + void updateView(); + + private: + + QString m_unit; + int m_interval; + + KSim::Label *m_fan1Label, *m_fan2Label, *m_tempLabel; + QTimer *m_timer; + FILE *m_procFile; + QTextIStream *m_procStream; + QRegExp *m_reData; +}; + +class I8KConfig : public KSim::PluginPage +{ + Q_OBJECT + public: + I8KConfig(KSim::PluginObject *parent, const char *name); + ~I8KConfig(); + + virtual void saveConfig(); + virtual void readConfig(); + + private slots: + + private: + + QCheckBox *m_unit; + KIntNumInput *m_interval; +}; + +#endif // KSIMI8K_H + +/* vim: et sw=2 ts=2 +*/ diff --git a/ksim/monitors/lm_sensors/Lm_sensors.desktop b/ksim/monitors/lm_sensors/Lm_sensors.desktop new file mode 100644 index 0000000..d700e0d --- /dev/null +++ b/ksim/monitors/lm_sensors/Lm_sensors.desktop @@ -0,0 +1,84 @@ +[Desktop Entry] +Comment=Lm_sensors Status Monitor +Comment[ar]=مراقب حالة Lm_sensors +Comment[bg]=Мониторинг на Lm_sensors +Comment[bs]=Nadzor statusa lm_sensors +Comment[ca]=Monitor de l'estat de Lm_sensors +Comment[cs]=Monitor stavu lm_sensorů +Comment[cy]=Monitr Statws Lm_sensors +Comment[da]=Statusovervågning af lm_følere +Comment[de]=Statusanzeige für LM-Sensoren +Comment[el]=Επόπτης κατάστασης lm_sensors +Comment[eo]=Rigardilo por la stato de Lm-sentiloj +Comment[es]=Monitor de estado de los sensores Lm +Comment[et]=Lm_sensors olekute monitooring +Comment[eu]=Lm_sentsoreen Egoera Begiralea +Comment[fa]=Lm_نمایشگر وضعیت حسگرهای +Comment[fi]=Lm_sensors tilavalvonta +Comment[fr]=Indicateur d'état lm_sensors +Comment[ga]=Monatóir Stádais Lm_sensors +Comment[he]=צג מצב Lm_sensors +Comment[hi]=एलएम_सेंसर्स स्थिति मॉनीटर +Comment[hu]=Lm_sensors hardvermonitor +Comment[is]=Eftirlit með stöðu Lm_sensors +Comment[it]=Controllo di stato Lm_sensors +Comment[ja]=Lm センサーの状態モニタ +Comment[ka]=Lm_sensors სტატუსის მონიტორი +Comment[kk]=Lm_sensor сенсорларының күйін бақылау +Comment[km]=កម្មវិធី​ត្រួតពិនិត្យ​ស្ថានភាព Lm_sensors +Comment[lt]=Lm_sensors būsenos stebėtojas +Comment[mk]=Монитор за статусот на Lm_sensors +Comment[ms]=Pemerhati Status Lm_sensors +Comment[nb]=Statusovervåkning av Lm_sensorer +Comment[nds]=LM_Sensors-Statuskieker +Comment[ne]=Lm_sensors स्थिति मोनिटर +Comment[nl]=Lm_sensors statusmonitor +Comment[nn]=Lm_sensors-statusovervaking +Comment[pa]=Lm_sensors ਹਾਲਤ ਨਿਗਰਾਨ +Comment[pl]=Stan Lm_sensors +Comment[pt]=Monitor de Estado do Lm_sensors +Comment[pt_BR]=Monitor de estado dos sensores do sistema +Comment[ro]=Monitor stare lm_sensors +Comment[ru]=Монитор состояния датчиков lm_sensors +Comment[sk]=Monitor stavu lm_sensors +Comment[sl]=Nadzornik stanja Lm_senzorji +Comment[sr]=Надгледање статуса lm-сензора +Comment[sr@Latn]=Nadgledanje statusa lm-senzora +Comment[sv]=Lm_sensors statusövervakare +Comment[ta]=Lm_உணர்கருவி நிலை கண்காணி +Comment[tg]=Дидабони Ҳолати Lm_sensors +Comment[th]=Lm_sensors - เครื่องมือสอดส่องสถานะ +Comment[tr]=Lm_sensors Durum İzleyici +Comment[uk]=Монітор стану Lm_sensors +Comment[zh_CN]=Lm_sensors 状态监视器 +Comment[zh_TW]=Lm_sensors 狀態監視器 +Comment[zu]=Umlawuli Wezinga we-Lm_sensors +Icon=memory +Name=Lm_sensors +Name[cs]=Lm_sensory +Name[da]=Lm_følere +Name[de]=LM-Sensoren +Name[eo]=Lm-sentiloj +Name[es]=Sensores Lm +Name[eu]=Lm_sentsoreak +Name[fa]=Lm_حسگرهای +Name[he]=חיישנים +Name[hi]=एलएम_सेंसर्स +Name[ja]=Lm センサー +Name[kk]=Lm_sensor сенсорлары +Name[ko]=Lm 센서 +Name[lv]=Lm_sensori +Name[nb]=Lm_sensorer +Name[nds]=LM-Sensoren +Name[ro]=Senzori LM +Name[ru]=Датчики lm_sensors +Name[sl]=Lm_senzorji +Name[sr]=Lm-сензори +Name[sr@Latn]=Lm-senzori +Name[ta]= Lm_சென்சார்ஸ் +X-KSIM-VERSION=0.1 +X-KSIM-LIBRARY=sensors +X-KSIM-PREFS=Sensors +X-KSIM-AUTHOR=Robbie Ward +X-KSIM-EMAIL=linuxphreak@gmx.co.uk +X-KSIM-COPYRIGHT=(C) 2001 Robbie Ward diff --git a/ksim/monitors/lm_sensors/Makefile.am b/ksim/monitors/lm_sensors/Makefile.am new file mode 100644 index 0000000..182e01c --- /dev/null +++ b/ksim/monitors/lm_sensors/Makefile.am @@ -0,0 +1,26 @@ +kde_module_LTLIBRARIES = ksim_sensors.la + +if include_nv +NVCTRL_LIB= NVCtrl.la +NVCtrl_la_SOURCES = NVCtrl.c +NVCtrl_la_LDFLAGS = -module $(all_libraries) $(KDE_PLUGIN) +endif + +noinst_LTLIBRARIES = $(NVCTRL_LIB) + +ksim_sensors_la_SOURCES = ksimsensors.cpp sensorsconfig.cpp \ + sensorbase.cpp ksimsensorsiface.skel + +ksim_sensors_la_LDFLAGS = $(all_libraries) -module -avoid-version +ksim_sensors_la_LIBADD = ../../library/libksimcore.la $(NVCTRL_LIB) + +EXTRA_DIST = Lm_sensors.desktop + +INCLUDES = -I$(top_srcdir)/ksim/library \ + -I$(top_srcdir)/ksim \ + $(all_includes) + +METASOURCES = AUTO + +mon_DATA = Lm_sensors.desktop +mondir = $(kde_datadir)/ksim/monitors diff --git a/ksim/monitors/lm_sensors/NVCtrl.c b/ksim/monitors/lm_sensors/NVCtrl.c new file mode 100644 index 0000000..6c61b8a --- /dev/null +++ b/ksim/monitors/lm_sensors/NVCtrl.c @@ -0,0 +1,357 @@ +/* + * Copyright (C) 2004 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of Version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 + * of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include +#include +#include +#include +#include "NVCtrlLib.h" +#include "nv_control.h" + + +static XExtensionInfo _nvctrl_ext_info_data; +static XExtensionInfo *nvctrl_ext_info = &_nvctrl_ext_info_data; +static const char *nvctrl_extension_name = NV_CONTROL_NAME; + +#define XNVCTRLCheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, nvctrl_extension_name, val) +#define XNVCTRLSimpleCheckExtension(dpy,i) \ + XextSimpleCheckExtension (dpy, i, nvctrl_extension_name) + +static int close_display(); +static Bool wire_to_event(); +static const XExtensionHooks nvctrl_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + close_display, /* close_display */ + wire_to_event, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (find_display, nvctrl_ext_info, + nvctrl_extension_name, + &nvctrl_extension_hooks, + NV_CONTROL_EVENTS, NULL) + +static XEXT_GENERATE_CLOSE_DISPLAY (close_display, nvctrl_ext_info) + +Bool XNVCTRLQueryExtension ( + Display *dpy, + int *event_basep, + int *error_basep +){ + XExtDisplayInfo *info = find_display (dpy); + + if (XextHasExtension(info)) { + if (event_basep) *event_basep = info->codes->first_event; + if (error_basep) *error_basep = info->codes->first_error; + return True; + } else { + return False; + } +} + + +Bool XNVCTRLQueryVersion ( + Display *dpy, + int *major, + int *minor +){ + XExtDisplayInfo *info = find_display (dpy); + xnvCtrlQueryExtensionReply rep; + xnvCtrlQueryExtensionReq *req; + + if(!XextHasExtension(info)) + return False; + + XNVCTRLCheckExtension (dpy, info, False); + + LockDisplay (dpy); + GetReq (nvCtrlQueryExtension, req); + req->reqType = info->codes->major_opcode; + req->nvReqType = X_nvCtrlQueryExtension; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + if (major) *major = rep.major; + if (minor) *minor = rep.minor; + UnlockDisplay (dpy); + SyncHandle (); + return True; +} + + +Bool XNVCTRLIsNvScreen ( + Display *dpy, + int screen +){ + XExtDisplayInfo *info = find_display (dpy); + xnvCtrlIsNvReply rep; + xnvCtrlIsNvReq *req; + Bool isnv; + + if(!XextHasExtension(info)) + return False; + + XNVCTRLCheckExtension (dpy, info, False); + + LockDisplay (dpy); + GetReq (nvCtrlIsNv, req); + req->reqType = info->codes->major_opcode; + req->nvReqType = X_nvCtrlIsNv; + req->screen = screen; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + isnv = rep.isnv; + UnlockDisplay (dpy); + SyncHandle (); + return isnv; +} + + +void XNVCTRLSetAttribute ( + Display *dpy, + int screen, + unsigned int display_mask, + unsigned int attribute, + int value +){ + XExtDisplayInfo *info = find_display (dpy); + xnvCtrlSetAttributeReq *req; + + XNVCTRLSimpleCheckExtension (dpy, info); + + LockDisplay (dpy); + GetReq (nvCtrlSetAttribute, req); + req->reqType = info->codes->major_opcode; + req->nvReqType = X_nvCtrlSetAttribute; + req->screen = screen; + req->display_mask = display_mask; + req->attribute = attribute; + req->value = value; + UnlockDisplay (dpy); + SyncHandle (); +} + + +Bool XNVCTRLQueryAttribute ( + Display *dpy, + int screen, + unsigned int display_mask, + unsigned int attribute, + int *value +){ + XExtDisplayInfo *info = find_display (dpy); + xnvCtrlQueryAttributeReply rep; + xnvCtrlQueryAttributeReq *req; + Bool exists; + + if(!XextHasExtension(info)) + return False; + + XNVCTRLCheckExtension (dpy, info, False); + + LockDisplay (dpy); + GetReq (nvCtrlQueryAttribute, req); + req->reqType = info->codes->major_opcode; + req->nvReqType = X_nvCtrlQueryAttribute; + req->screen = screen; + req->display_mask = display_mask; + req->attribute = attribute; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + if (value) *value = rep.value; + exists = rep.flags; + UnlockDisplay (dpy); + SyncHandle (); + return exists; +} + + +Bool XNVCTRLQueryStringAttribute ( + Display *dpy, + int screen, + unsigned int display_mask, + unsigned int attribute, + char **ptr +){ + XExtDisplayInfo *info = find_display (dpy); + xnvCtrlQueryStringAttributeReply rep; + xnvCtrlQueryStringAttributeReq *req; + Bool exists; + int length, numbytes, slop; + + if (!ptr) return False; + + if(!XextHasExtension(info)) + return False; + + XNVCTRLCheckExtension (dpy, info, False); + + LockDisplay (dpy); + GetReq (nvCtrlQueryStringAttribute, req); + req->reqType = info->codes->major_opcode; + req->nvReqType = X_nvCtrlQueryStringAttribute; + req->screen = screen; + req->display_mask = display_mask; + req->attribute = attribute; + if (!_XReply (dpy, (xReply *) &rep, 0, False)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + length = rep.length; + numbytes = rep.n; + slop = numbytes & 3; + *ptr = (char *) Xmalloc(numbytes); + if (! *ptr) { + _XEatData(dpy, length); + UnlockDisplay (dpy); + SyncHandle (); + return False; + } else { + _XRead(dpy, (char *) *ptr, numbytes); + if (slop) _XEatData(dpy, 4-slop); + } + exists = rep.flags; + UnlockDisplay (dpy); + SyncHandle (); + return exists; +} + +Bool XNVCTRLQueryValidAttributeValues ( + Display *dpy, + int screen, + unsigned int display_mask, + unsigned int attribute, + NVCTRLAttributeValidValuesRec *values +){ + XExtDisplayInfo *info = find_display (dpy); + xnvCtrlQueryValidAttributeValuesReply rep; + xnvCtrlQueryValidAttributeValuesReq *req; + Bool exists; + + if (!values) return False; + + if(!XextHasExtension(info)) + return False; + + XNVCTRLCheckExtension (dpy, info, False); + + LockDisplay (dpy); + GetReq (nvCtrlQueryValidAttributeValues, req); + req->reqType = info->codes->major_opcode; + req->nvReqType = X_nvCtrlQueryValidAttributeValues; + req->screen = screen; + req->display_mask = display_mask; + req->attribute = attribute; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + exists = rep.flags; + values->type = rep.attr_type; + if (rep.attr_type == ATTRIBUTE_TYPE_RANGE) { + values->u.range.min = rep.min; + values->u.range.max = rep.max; + } + if (rep.attr_type == ATTRIBUTE_TYPE_INT_BITS) { + values->u.bits.ints = rep.bits; + } + values->permissions = rep.perms; + UnlockDisplay (dpy); + SyncHandle (); + return exists; +} + +Bool XNVCtrlSelectNotify ( + Display *dpy, + int screen, + int type, + Bool onoff +){ + XExtDisplayInfo *info = find_display (dpy); + xnvCtrlSelectNotifyReq *req; + + if(!XextHasExtension (info)) + return False; + + XNVCTRLCheckExtension (dpy, info, False); + + LockDisplay (dpy); + GetReq (nvCtrlSelectNotify, req); + req->reqType = info->codes->major_opcode; + req->nvReqType = X_nvCtrlSelectNotify; + req->screen = screen; + req->notifyType = type; + req->onoff = onoff; + UnlockDisplay (dpy); + SyncHandle (); + + return True; +} + +static Bool wire_to_event (Display *dpy, XEvent *host, xEvent *wire) +{ + XExtDisplayInfo *info = find_display (dpy); + XNVCtrlEvent *re = (XNVCtrlEvent *) host; + xnvctrlEvent *event = (xnvctrlEvent *) wire; + + XNVCTRLCheckExtension (dpy, info, False); + + switch ((event->u.u.type & 0x7F) - info->codes->first_event) { + case ATTRIBUTE_CHANGED_EVENT: + re->attribute_changed.type = event->u.u.type & 0x7F; + re->attribute_changed.serial = + _XSetLastRequestRead(dpy, (xGenericReply*) event); + re->attribute_changed.send_event = ((event->u.u.type & 0x80) != 0); + re->attribute_changed.display = dpy; + re->attribute_changed.time = event->u.attribute_changed.time; + re->attribute_changed.screen = event->u.attribute_changed.screen; + re->attribute_changed.display_mask = + event->u.attribute_changed.display_mask; + re->attribute_changed.attribute = event->u.attribute_changed.attribute; + re->attribute_changed.value = event->u.attribute_changed.value; + break; + default: + return False; + } + + return True; +} + diff --git a/ksim/monitors/lm_sensors/NVCtrl.h b/ksim/monitors/lm_sensors/NVCtrl.h new file mode 100644 index 0000000..81c9432 --- /dev/null +++ b/ksim/monitors/lm_sensors/NVCtrl.h @@ -0,0 +1,807 @@ +/* + * Copyright (C) 2004 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of Version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 + * of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + * + */ + +#ifndef __NVCTRL_H +#define __NVCTRL_H + +/**************************************************************************/ +/* + * Integer attributes; these are settable/gettable via + * XNVCTRLSetAttribute() and XNVCTRLQueryAttribute, respectively. + * Some attributes may only be read; some may require a display_mask + * argument. This information is encoded in the "permission" comment + * after each attribute #define, and can be queried at run time with + * XNVCTRLQueryValidAttributeValues(). + * + * Key to Integer Attribute "Permissions": + * + * R: The attribute is readable (in general, all attributes will be + * readable) + * + * W: The attribute is writable (attributes may not be writable for + * various reasons: they represent static system information, they + * can only be changed by changing an XF86Config option, etc). + * + * D: The attribute requires the display mask argument. The + * attributes NV_CTRL_CONNECTED_DISPLAYS and NV_CTRL_ENABLED_DISPLAYS + * will be a bitmask of what display devices are connected and what + * display devices are enabled for use in X, respectively. Each bit + * in the bitmask represents a display device; it is these bits which + * should be used as the display_mask when dealing with attributes + * designated with "D" below. For attributes that do not require the + * display mask, the argument is ignored. + */ + + +/**************************************************************************/ + + +/* + * NV_CTRL_FLATPANEL_SCALING - the current flatpanel scaling state; + * possible values are: + * + * 0: default (the driver will use whatever state is current) + * 1: native (the driver will use the panel's scaler, if possible) + * 2: scaled (the driver will use the GPU's scaler, if possible) + * 3: centered (the driver will center the image) + * 4: aspect scaled (scale with the GPU's scaler, but keep the aspect + * ratio correct) + */ + +#define NV_CTRL_FLATPANEL_SCALING 2 /* RWD */ +#define NV_CTRL_FLATPANEL_SCALING_DEFAULT 0 +#define NV_CTRL_FLATPANEL_SCALING_NATIVE 1 +#define NV_CTRL_FLATPANEL_SCALING_SCALED 2 +#define NV_CTRL_FLATPANEL_SCALING_CENTERED 3 +#define NV_CTRL_FLATPANEL_SCALING_ASPECT_SCALED 4 + + +/* + * NV_CTRL_FLATPANEL_DITHERING - the current flatpanel dithering + * state; possible values are: + * + * 0: default (the driver will decide when to dither) + * 1: enabled (the driver will always dither when possible) + * 2: disabled (the driver will never dither) + */ + +#define NV_CTRL_FLATPANEL_DITHERING 3 /* RWD */ +#define NV_CTRL_FLATPANEL_DITHERING_DEFAULT 0 +#define NV_CTRL_FLATPANEL_DITHERING_ENABLED 1 +#define NV_CTRL_FLATPANEL_DITHERING_DISABLED 2 + + +/* + * NV_CTRL_DIGITAL_VIBRANCE - sets the digital vibrance level for the + * specified display device. + */ + +#define NV_CTRL_DIGITAL_VIBRANCE 4 /* RWD */ + + +/* + * NV_CTRL_BUS_TYPE - returns the Bus type through which the GPU + * driving the specified X screen is connected to the computer. + */ + +#define NV_CTRL_BUS_TYPE 5 /* R-- */ +#define NV_CTRL_BUS_TYPE_AGP 0 +#define NV_CTRL_BUS_TYPE_PCI 1 +#define NV_CTRL_BUS_TYPE_PCI_EXPRESS 2 + + +/* + * NV_CTRL_VIDEO_RAM - returns the amount of video ram on the GPU + * driving the specified X screen. + */ + +#define NV_CTRL_VIDEO_RAM 6 /* R-- */ + + +/* + * NV_CTRL_IRQ - returns the interrupt request line used by the GPU + * driving the specified X screen. + */ + +#define NV_CTRL_IRQ 7 /* R-- */ + + +/* + * NV_CTRL_OPERATING_SYSTEM - returns the operating system on which + * the X server is running. + */ + +#define NV_CTRL_OPERATING_SYSTEM 8 /* R-- */ +#define NV_CTRL_OPERATING_SYSTEM_LINUX 0 +#define NV_CTRL_OPERATING_SYSTEM_FREEBSD 1 + + +/* + * NV_CTRL_SYNC_TO_VBLANK - enables sync to vblank for OpenGL clients. + * This setting is only applied to OpenGL clients that are started + * after this setting is applied. + */ + +#define NV_CTRL_SYNC_TO_VBLANK 9 /* RW- */ +#define NV_CTRL_SYNC_TO_VBLANK_OFF 0 +#define NV_CTRL_SYNC_TO_VBLANK_ON 1 + + +/* + * NV_CTRL_LOG_ANISO - enables anisotropic filtering for OpenGL + * clients; on some NVIDIA hardware, this can only be enabled or + * disabled; on other hardware different levels of anisotropic + * filtering can be specified. This setting is only applied to OpenGL + * clients that are started after this setting is applied. + */ + +#define NV_CTRL_LOG_ANISO 10 /* RW- */ + + +/* + * NV_CTRL_FSAA_MODE - the FSAA setting for OpenGL clients; possible + * FSAA modes: + * + * NV_CTRL_FSAA_MODE_2x "2x Bilinear Multisampling" + * NV_CTRL_FSAA_MODE_2x_5t "2x Quincunx Multisampling" + * NV_CTRL_FSAA_MODE_15x15 "1.5 x 1.5 Supersampling" + * NV_CTRL_FSAA_MODE_2x2 "2 x 2 Supersampling" + * NV_CTRL_FSAA_MODE_4x "4x Bilinear Multisampling" + * NV_CTRL_FSAA_MODE_4x_9t "4x Gaussian Multisampling" + * NV_CTRL_FSAA_MODE_8x "2x Bilinear Multisampling by 4x Supersampling" + * NV_CTRL_FSAA_MODE_16x "4x Bilinear Multisampling by 4x Supersampling" + * + * This setting is only applied to OpenGL clients that are started + * after this setting is applied. + */ + +#define NV_CTRL_FSAA_MODE 11 /* RW- */ +#define NV_CTRL_FSAA_MODE_NONE 0 +#define NV_CTRL_FSAA_MODE_2x 1 +#define NV_CTRL_FSAA_MODE_2x_5t 2 +#define NV_CTRL_FSAA_MODE_15x15 3 +#define NV_CTRL_FSAA_MODE_2x2 4 +#define NV_CTRL_FSAA_MODE_4x 5 +#define NV_CTRL_FSAA_MODE_4x_9t 6 +#define NV_CTRL_FSAA_MODE_8x 7 +#define NV_CTRL_FSAA_MODE_16x 8 + + +/* + * NV_CTRL_TEXTURE_SHARPEN - enables texture sharpening for OpenGL + * clients. This setting is only applied to OpenGL clients that are + * started after this setting is applied. + */ + +#define NV_CTRL_TEXTURE_SHARPEN 12 /* RW- */ +#define NV_CTRL_TEXTURE_SHARPEN_OFF 0 +#define NV_CTRL_TEXTURE_SHARPEN_ON 1 + + +/* + * NV_CTRL_UBB - returns whether UBB is enabled for the specified X + * screen. + */ + +#define NV_CTRL_UBB 13 /* R-- */ +#define NV_CTRL_UBB_OFF 0 +#define NV_CTRL_UBB_ON 1 + + +/* + * NV_CTRL_OVERLAY - returns whether the RGB overlay is enabled for + * the specified X screen. + */ + +#define NV_CTRL_OVERLAY 14 /* R-- */ +#define NV_CTRL_OVERLAY_OFF 0 +#define NV_CTRL_OVERLAY_ON 1 + + +/* + * NV_CTRL_STEREO - returns whether stereo (and what type) is enabled + * for the specified X screen. + */ + +#define NV_CTRL_STEREO 16 /* R-- */ +#define NV_CTRL_STEREO_OFF 0 +#define NV_CTRL_STEREO_DDC 1 +#define NV_CTRL_STEREO_BLUELINE 2 +#define NV_CTRL_STEREO_DIN 3 +#define NV_CTRL_STEREO_TWINVIEW 4 + + +/* + * NV_CTRL_EMULATE - controls OpenGL software emulation of future + * NVIDIA GPUs. + */ + +#define NV_CTRL_EMULATE 17 /* RW- */ +#define NV_CTRL_EMULATE_NONE 0 + + +/* + * NV_CTRL_TWINVIEW - returns whether TwinView is enabled for the + * specified X screen. + */ + +#define NV_CTRL_TWINVIEW 18 /* R-- */ +#define NV_CTRL_TWINVIEW_NOT_ENABLED 0 +#define NV_CTRL_TWINVIEW_ENABLED 1 + + +/* + * NV_CTRL_CONNECTED_DISPLAYS - returns a display mask indicating what + * display devices are connected to the GPU driving the specified X + * screen. + */ + +#define NV_CTRL_CONNECTED_DISPLAYS 19 /* R-- */ + + +/* + * NV_CTRL_ENABLED_DISPLAYS - returns a display mask indicating what + * display devices are enabled for use on the specified X screen. + */ + +#define NV_CTRL_ENABLED_DISPLAYS 20 /* R-- */ + +/**************************************************************************/ +/* + * Integer attributes specific to configuring FrameLock on boards that + * support it. + */ + + +/* + * NV_CTRL_FRAMELOCK - returns whether this X screen supports + * FrameLock. All of the other FrameLock attributes are only + * applicable if NV_CTRL_FRAMELOCK is _SUPPORTED. + */ + +#define NV_CTRL_FRAMELOCK 21 /* R-- */ +#define NV_CTRL_FRAMELOCK_NOT_SUPPORTED 0 +#define NV_CTRL_FRAMELOCK_SUPPORTED 1 + + +/* + * NV_CTRL_FRAMELOCK_MASTER - get/set whether this X screen is the + * FrameLock master for the entire sync group. Note that only one + * node in the sync group should be configured as the master. + */ + +#define NV_CTRL_FRAMELOCK_MASTER 22 /* RW- */ +#define NV_CTRL_FRAMELOCK_MASTER_FALSE 0 +#define NV_CTRL_FRAMELOCK_MASTER_TRUE 1 + + +/* + * NV_CTRL_FRAMELOCK_POLARITY - sync either to the rising edge of the + * framelock pulse, or both the rising and falling edges of the + * framelock pulse. + */ + +#define NV_CTRL_FRAMELOCK_POLARITY 23 /* RW- */ +#define NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE 0x1 +#define NV_CTRL_FRAMELOCK_POLARITY_BOTH_EDGES 0x3 + + +/* + * NV_CTRL_FRAMELOCK_SYNC_DELAY - delay between the framelock pulse + * and the GPU sync. This is an 11 bit value which is multipled by + * 7.81 to determine the sync delay in microseconds. + */ + +#define NV_CTRL_FRAMELOCK_SYNC_DELAY 24 /* RW- */ +#define NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX 2047 +#define NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR 7.81 + +/* + * NV_CTRL_FRAMELOCK_SYNC_INTERVAL - how many house sync pulses + * between the FrameLock sync generation (0 == sync every house sync); + * this only applies to the master when receiving house sync. + */ + +#define NV_CTRL_FRAMELOCK_SYNC_INTERVAL 25 /* RW- */ + + +/* + * NV_CTRL_FRAMELOCK_PORT0_STATUS - status of the rj45 port0. + */ + +#define NV_CTRL_FRAMELOCK_PORT0_STATUS 26 /* R-- */ +#define NV_CTRL_FRAMELOCK_PORT0_STATUS_INPUT 0 +#define NV_CTRL_FRAMELOCK_PORT0_STATUS_OUTPUT 1 + + +/* + * NV_CTRL_FRAMELOCK_PORT1_STATUS - status of the rj45 port1. + */ + +#define NV_CTRL_FRAMELOCK_PORT1_STATUS 27 /* R-- */ +#define NV_CTRL_FRAMELOCK_PORT1_STATUS_INPUT 0 +#define NV_CTRL_FRAMELOCK_PORT1_STATUS_OUTPUT 1 + + +/* + * NV_CTRL_FRAMELOCK_HOUSE_STATUS - status of the house input (the BNC + * connector). + */ + +#define NV_CTRL_FRAMELOCK_HOUSE_STATUS 28 /* R-- */ +#define NV_CTRL_FRAMELOCK_HOUSE_STATUS_NOT_DETECTED 0 +#define NV_CTRL_FRAMELOCK_HOUSE_STATUS_DETECTED 1 + + +/* + * NV_CTRL_FRAMELOCK_SYNC - enable/disable the syncing of the + * specified display devices to the FrameLock pulse. + */ + +#define NV_CTRL_FRAMELOCK_SYNC 29 /* RWD */ +#define NV_CTRL_FRAMELOCK_SYNC_DISABLE 0 +#define NV_CTRL_FRAMELOCK_SYNC_ENABLE 1 + + +/* + * NV_CTRL_FRAMELOCK_SYNC_READY - reports whether a slave FrameLock + * board is receiving sync (regardless of whether or not any display + * devices are using the sync). + */ + +#define NV_CTRL_FRAMELOCK_SYNC_READY 30 /* R-- */ +#define NV_CTRL_FRAMELOCK_SYNC_READY_FALSE 0 +#define NV_CTRL_FRAMELOCK_SYNC_READY_TRUE 1 + + +/* + * NV_CTRL_FRAMELOCK_STEREO_SYNC - this indicates that the GPU stereo + * signal is in sync with the framelock stereo signal. + */ + +#define NV_CTRL_FRAMELOCK_STEREO_SYNC 31 /* R-- */ +#define NV_CTRL_FRAMELOCK_STEREO_SYNC_FALSE 0 +#define NV_CTRL_FRAMELOCK_STEREO_SYNC_TRUE 1 + + +/* + * NV_CTRL_FRAMELOCK_TEST_SIGNAL - to test the connections in the sync + * group, tell the master to enable a test signal, then query port[01] + * status and sync_ready on all slaves. When done, tell the master to + * disable the test signal. Test signal should only be manipulated + * while NV_CTRL_FRAMELOCK_SYNC is enabled. + * + * The TEST_SIGNAL is also used to reset the Universal Frame Count (as + * returned by the glXQueryFrameCountNV() function in the + * GLX_NV_swap_group extension). Note: for best accuracy of the + * Universal Frame Count, it is recommended to toggle the TEST_SIGNAL + * on and off after enabling FrameLock. + */ + +#define NV_CTRL_FRAMELOCK_TEST_SIGNAL 32 /* RW- */ +#define NV_CTRL_FRAMELOCK_TEST_SIGNAL_DISABLE 0 +#define NV_CTRL_FRAMELOCK_TEST_SIGNAL_ENABLE 1 + + +/* + * NV_CTRL_FRAMELOCK_ETHERNET_DETECTED - The FrameLock boards are + * cabled together using regular cat5 cable, connecting to rj45 ports + * on the backplane of the card. There is some concern that users may + * think these are ethernet ports and connect them to a + * router/hub/etc. The hardware can detect this and will shut off to + * prevent damage (either to itself or to the router). + * NV_CTRL_FRAMELOCK_ETHERNET_DETECTED may be called to find out if + * ethernet is connected to one of the rj45 ports. An appropriate + * error message should then be displayed. The _PORT0 and PORT1 + * values may be or'ed together. + */ + +#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED 33 /* R-- */ +#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_NONE 0 +#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_PORT0 0x1 +#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_PORT1 0x2 + + +/* + * NV_CTRL_FRAMELOCK_VIDEO_MODE - get/set the video mode of the house + * input. + */ + +#define NV_CTRL_FRAMELOCK_VIDEO_MODE 34 /* RW- */ +#define NV_CTRL_FRAMELOCK_VIDEO_MODE_NONE 0 +#define NV_CTRL_FRAMELOCK_VIDEO_MODE_TTL 1 +#define NV_CTRL_FRAMELOCK_VIDEO_MODE_NTSCPALSECAM 2 +#define NV_CTRL_FRAMELOCK_VIDEO_MODE_HDTV 3 + +/* + * During FRAMELOCK bring-up, the above values were redefined to + * these: + */ + +#define NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_AUTO 0 +#define NV_CTRL_FRAMELOCK_VIDEO_MODE_TTL 1 +#define NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_BI_LEVEL 2 +#define NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_TRI_LEVEL 3 + + +/* + * NV_CTRL_FRAMELOCK_SYNC_RATE - this is the refresh rate that the + * framelock board is sending to the GPU, in milliHz. + */ + +#define NV_CTRL_FRAMELOCK_SYNC_RATE 35 /* R-- */ + + + +/**************************************************************************/ + +/* + * NV_CTRL_FORCE_GENERIC_CPU - inhibit the use of CPU specific + * features such as MMX, SSE, or 3DNOW! for OpenGL clients; this + * option may result in performance loss, but may be useful in + * conjunction with software such as the Valgrind memory debugger. + * This setting is only applied to OpenGL clients that are started + * after this setting is applied. + */ + +#define NV_CTRL_FORCE_GENERIC_CPU 37 /* RW- */ +#define NV_CTRL_FORCE_GENERIC_CPU_DISABLE 0 +#define NV_CTRL_FORCE_GENERIC_CPU_ENABLE 1 + + +/* + * NV_CTRL_OPENGL_AA_LINE_GAMMA - for OpenGL clients, allow + * Gamma-corrected antialiased lines to consider variances in the + * color display capabilities of output devices when rendering smooth + * lines. Only available on recent Quadro GPUs. This setting is only + * applied to OpenGL clients that are started after this setting is + * applied. + */ + +#define NV_CTRL_OPENGL_AA_LINE_GAMMA 38 /* RW- */ +#define NV_CTRL_OPENGL_AA_LINE_GAMMA_DISABLE 0 +#define NV_CTRL_OPENGL_AA_LINE_GAMMA_ENABLE 1 + + +/* + * NV_CTRL_FRAMELOCK_TIMING - this is TRUE when the framelock board is + * receiving timing input. + */ + +#define NV_CTRL_FRAMELOCK_TIMING 39 /* RW- */ +#define NV_CTRL_FRAMELOCK_TIMING_FALSE 0 +#define NV_CTRL_FRAMELOCK_TIMING_TRUE 1 + +/* + * NV_CTRL_FLIPPING_ALLOWED - when TRUE, OpenGL will swap by flipping + * when possible; when FALSE, OpenGL will alway swap by blitting. XXX + * can this be enabled dynamically? + */ + +#define NV_CTRL_FLIPPING_ALLOWED 40 /* RW- */ +#define NV_CTRL_FLIPPING_ALLOWED_FALSE 0 +#define NV_CTRL_FLIPPING_ALLOWED_TRUE 1 + +/* + * NV_CTRL_ARCHITECTURE - returns the architecture on which the X server is + * running. + */ + +#define NV_CTRL_ARCHITECTURE 41 /* R-- */ +#define NV_CTRL_ARCHITECTURE_X86 0 +#define NV_CTRL_ARCHITECTURE_X86_64 1 +#define NV_CTRL_ARCHITECTURE_IA64 2 + + +/* + * NV_CTRL_TEXTURE_CLAMPING - texture clamping mode in OpenGL. By + * default, NVIDIA's OpenGL implementation uses CLAMP_TO_EDGE, which + * is not strictly conformant, but some applications rely on the + * non-conformant behavior, and not all GPUs support conformant + * texture clamping in hardware. _SPEC forces OpenGL texture clamping + * to be conformant, but may introduce slower performance on older + * GPUS, or incorrect texture clamping in certain applications. + */ + +#define NV_CTRL_TEXTURE_CLAMPING 42 /* RW- */ +#define NV_CTRL_TEXTURE_CLAMPING_EDGE 0 +#define NV_CTRL_TEXTURE_CLAMPING_SPEC 1 + + + +#define NV_CTRL_CURSOR_SHADOW 43 /* RW- */ +#define NV_CTRL_CURSOR_SHADOW_DISABLE 0 +#define NV_CTRL_CURSOR_SHADOW_ENABLE 1 + +#define NV_CTRL_CURSOR_SHADOW_ALPHA 44 /* RW- */ +#define NV_CTRL_CURSOR_SHADOW_RED 45 /* RW- */ +#define NV_CTRL_CURSOR_SHADOW_GREEN 46 /* RW- */ +#define NV_CTRL_CURSOR_SHADOW_BLUE 47 /* RW- */ + +#define NV_CTRL_CURSOR_SHADOW_X_OFFSET 48 /* RW- */ +#define NV_CTRL_CURSOR_SHADOW_Y_OFFSET 49 /* RW- */ + + + +/* + * When Application Control for FSAA is enabled, then what the + * application requests is used, and NV_CTRL_FSAA_MODE is ignored. If + * this is disabled, then any application setting is overridden with + * NV_CTRL_FSAA_MODE + */ + +#define NV_CTRL_FSAA_APPLICATION_CONTROLLED 50 /* RW- */ +#define NV_CTRL_FSAA_APPLICATION_CONTROLLED_ENABLED 1 +#define NV_CTRL_FSAA_APPLICATION_CONTROLLED_DISABLED 0 + + +/* + * When Application Control for LogAniso is enabled, then what the + * application requests is used, and NV_CTRL_LOG_ANISO is ignored. If + * this is disabled, then any application setting is overridden with + * NV_CTRL_LOG_ANISO + */ + +#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED 51 /* RW- */ +#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED_ENABLED 1 +#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED_DISABLED 0 + + +/* + * IMAGE_SHARPENING adjusts the sharpness of the display's image + * quality by amplifying high frequency content. Valid values will + * normally be in the range [0,32). Only available on GeForceFX or + * newer. + */ + +#define NV_CTRL_IMAGE_SHARPENING 52 /* RWD */ + + +/* + * NV_CTRL_TV_OVERSCAN adjusts the amount of overscan on the specified + * display device. + */ + +#define NV_CTRL_TV_OVERSCAN 53 /* RWD */ + + +/* + * NV_CTRL_TV_FLICKER_FILTER adjusts the amount of flicker filter on + * the specified display device. + */ + +#define NV_CTRL_TV_FLICKER_FILTER 54 /* RWD */ + + +/* + * NV_CTRL_TV_BRIGHTNESS adjusts the amount of brightness on the + * specified display device. + */ + +#define NV_CTRL_TV_BRIGHTNESS 55 /* RWD */ + + +/* + * NV_CTRL_TV_HUE adjusts the amount of hue on the specified display + * device. + */ + +#define NV_CTRL_TV_HUE 56 /* RWD */ + + +/* + * NV_CTRL_TV_CONTRAST adjusts the amount of contrast on the specified + * display device. + */ + +#define NV_CTRL_TV_CONTRAST 57 /* RWD */ + + +/* + * NV_CTRL_TV_SATURATION adjusts the amount of saturation on the + * specified display device. + */ + +#define NV_CTRL_TV_SATURATION 58 /* RWD */ + + +/* + * NV_CTRL_TV_RESET_SETTINGS - this write-only attribute can be used + * to request that all TV Settings be reset to their default values; + * typical usage would be that this attribute be sent, and then all + * the TV attributes be queried to retrieve their new values. + */ + +#define NV_CTRL_TV_RESET_SETTINGS 59 /* -WD */ + + +/* + * NV_CTRL_GPU_CORE_TEMPERATURE reports the current core temperature + * of the GPU driving the X screen. + */ + +#define NV_CTRL_GPU_CORE_TEMPERATURE 60 /* R-- */ + + +/* + * NV_CTRL_GPU_CORE_THRESHOLD reports the current GPU core slowdown + * threshold temperature, NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD and + * NV_CTRL_GPU_MAX_CORE_THRESHOLD report the default and MAX core + * slowdown threshold temperatures. + * + * NV_CTRL_GPU_CORE_THRESHOLD reflects the temperature at which the + * GPU is throttled to prevent overheating. + */ + +#define NV_CTRL_GPU_CORE_THRESHOLD 61 /* R-- */ +#define NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD 62 /* R-- */ +#define NV_CTRL_GPU_MAX_CORE_THRESHOLD 63 /* R-- */ + + +/* + * NV_CTRL_AMBIENT_TEMPERATURE reports the current temperature in the + * immediate neighbourhood of the GPU driving the X screen. + */ + +#define NV_CTRL_AMBIENT_TEMPERATURE 64 /* R-- */ + + +/* + * NV_CTRL_PBUFFER_SCANOUT_SUPPORTED - returns whether this X screen + * supports scanout of FP pbuffers; + * + * if this screen does not support PBUFFER_SCANOUT, then all other + * PBUFFER_SCANOUT attributes are unavailable. + */ + +#define NV_CTRL_PBUFFER_SCANOUT_SUPPORTED 65 /* R-- */ +#define NV_CTRL_PBUFFER_SCANOUT_FALSE 0 +#define NV_CTRL_PBUFFER_SCANOUT_TRUE 1 + +/* + * NV_CTRL_PBUFFER_SCANOUT_XID indicates the XID of the pbuffer used for + * scanout. + */ +#define NV_CTRL_PBUFFER_SCANOUT_XID 66 /* RW- */ + +#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_PBUFFER_SCANOUT_XID + +/**************************************************************************/ + +/* + * String Attributes: + */ + + +/* + * NV_CTRL_STRING_PRODUCT_NAME - the GPU product name on which the + * specified X screen is running. + */ + +#define NV_CTRL_STRING_PRODUCT_NAME 0 /* R-- */ + + +/* + * NV_CTRL_STRING_VBIOS_VERSION - the video bios version on the GPU on + * which the specified X screen is running. + */ + +#define NV_CTRL_STRING_VBIOS_VERSION 1 /* R-- */ + + +/* + * NV_CTRL_STRING_NVIDIA_DRIVER_VERSION - string representation of the + * NVIDIA driver version number for the NVIDIA X driver in use. + */ + +#define NV_CTRL_STRING_NVIDIA_DRIVER_VERSION 3 /* R-- */ + + +/* + * NV_CTRL_STRING_DISPLAY_DEVICE_NAME - name of the display device + * specified in the display_mask argument. + */ + +#define NV_CTRL_STRING_DISPLAY_DEVICE_NAME 4 /* R-D */ + + +/* + * NV_CTRL_STRING_TV_ENCODER_NAME - name of the TV encoder used by the + * specified display device; only valid if the display device is a TV. + */ + +#define NV_CTRL_STRING_TV_ENCODER_NAME 5 /* R-D */ + +#define NV_CTRL_STRING_LAST_ATTRIBUTE NV_CTRL_STRING_TV_ENCODER_NAME + + + +/**************************************************************************/ +/* + * CTRLAttributeValidValuesRec - + * + * structure and related defines used by + * XNVCTRLQueryValidAttributeValues() to describe the valid values of + * a particular attribute. The type field will be one of: + * + * ATTRIBUTE_TYPE_INTEGER : the attribute is an integer value; there + * is no fixed range of valid values. + * + * ATTRIBUTE_TYPE_BITMASK : the attribute is an integer value, + * interpretted as a bitmask. + * + * ATTRIBUTE_TYPE_BOOL : the attribute is a boolean, valid values are + * either 1 (on/true) or 0 (off/false). + * + * ATTRIBUTE_TYPE_RANGE : the attribute can have any integer value + * between NVCTRLAttributeValidValues.u.range.min and + * NVCTRLAttributeValidValues.u.range.max (inclusive). + * + * ATTRIBUTE_TYPE_INT_BITS : the attribute can only have certain + * integer values, indicated by which bits in + * NVCTRLAttributeValidValues.u.bits.ints are on (for example: if bit + * 0 is on, then 0 is a valid value; if bit 5 is on, then 5 is a valid + * value, etc). This is useful for attributes like NV_CTRL_FSAA_MODE, + * which can only have certain values, depending on GPU. + * + * + * The permissions field of NVCTRLAttributeValidValuesRec is a bitmask + * that may contain: + * + * ATTRIBUTE_TYPE_READ + * ATTRIBUTE_TYPE_WRITE + * ATTRIBUTE_TYPE_DISPLAY + * + * See 'Key to Integer Attribute "Permissions"' at the top of this + * file for a description of what these three permission bits mean. + */ + +#define ATTRIBUTE_TYPE_UNKNOWN 0 +#define ATTRIBUTE_TYPE_INTEGER 1 +#define ATTRIBUTE_TYPE_BITMASK 2 +#define ATTRIBUTE_TYPE_BOOL 3 +#define ATTRIBUTE_TYPE_RANGE 4 +#define ATTRIBUTE_TYPE_INT_BITS 5 + +#define ATTRIBUTE_TYPE_READ 0x1 +#define ATTRIBUTE_TYPE_WRITE 0x2 +#define ATTRIBUTE_TYPE_DISPLAY 0x4 + +typedef struct _NVCTRLAttributeValidValues { + int type; + union { + struct { + int min; + int max; + } range; + struct { + unsigned int ints; + } bits; + } u; + unsigned int permissions; +} NVCTRLAttributeValidValuesRec; + + + +#define ATTRIBUTE_CHANGED_EVENT 0 + + +#endif /* __NVCTRL_H */ diff --git a/ksim/monitors/lm_sensors/NVCtrlLib.h b/ksim/monitors/lm_sensors/NVCtrlLib.h new file mode 100644 index 0000000..8d9cec4 --- /dev/null +++ b/ksim/monitors/lm_sensors/NVCtrlLib.h @@ -0,0 +1,184 @@ +#ifndef __NVCTRLLIB_H +#define __NVCTRLLIB_H + +#include "NVCtrl.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * XNVCTRLQueryExtension - + * + * Returns True if the extension exists, returns False otherwise. + * event_basep and error_basep are the extension event and error + * bases. Currently, no extension specific errors or events are + * defined. + */ + +Bool XNVCTRLQueryExtension ( + Display *dpy, + int *event_basep, + int *error_basep +); + +/* + * XNVCTRLQueryVersion - + * + * Returns True if the extension exists, returns False otherwise. + * major and minor are the extension's major and minor version + * numbers. + */ + +Bool XNVCTRLQueryVersion ( + Display *dpy, + int *major, + int *minor +); + + +/* + * XNVCTRLIsNvScreen + * + * Returns True is the specified screen is controlled by the NVIDIA + * driver. Returns False otherwise. + */ + +Bool XNVCTRLIsNvScreen ( + Display *dpy, + int screen +); + +/* + * XNVCTRLSetAttribute - + * + * Sets the attribute to the given value. The attributes and their + * possible values are listed in NVCtrl.h. + * + * Not all attributes require the display_mask parameter; see + * NVCtrl.h for details. + * + * Possible errors: + * BadValue - The screen or attribute doesn't exist. + * BadMatch - The NVIDIA driver is not present on that screen. + */ + +void XNVCTRLSetAttribute ( + Display *dpy, + int screen, + unsigned int display_mask, + unsigned int attribute, + int value +); + +/* + * XNVCTRLQueryAttribute - + * + * Returns True if the attribute exists. Returns False otherwise. + * If XNVCTRLQueryAttribute returns True, value will contain the + * value of the specified attribute. + * + * Not all attributes require the display_mask parameter; see + * NVCtrl.h for details. + * + * Possible errors: + * BadValue - The screen doesn't exist. + * BadMatch - The NVIDIA driver is not present on that screen. + */ + + +Bool XNVCTRLQueryAttribute ( + Display *dpy, + int screen, + unsigned int display_mask, + unsigned int attribute, + int *value +); + +/* + * XNVCTRLQueryStringAttribute - + * + * Returns True if the attribute exists. Returns False otherwise. + * If XNVCTRLQueryStringAttribute returns True, *ptr will point to an + * allocated string containing the string attribute requested. It is + * the caller's responsibility to free the string when done. + * + * Possible errors: + * BadValue - The screen doesn't exist. + * BadMatch - The NVIDIA driver is not present on that screen. + * BadAlloc - Insufficient resources to fulfill the request. + */ + +Bool XNVCTRLQueryStringAttribute ( + Display *dpy, + int screen, + unsigned int display_mask, + unsigned int attribute, + char **ptr +); + +/* + * XNVCTRLQueryValidAttributeValues - + * + * Returns True if the attribute exists. Returns False otherwise. If + * XNVCTRLQueryValidAttributeValues returns True, values will indicate + * the valid values for the specified attribute; see the description + * of NVCTRLAttributeValidValues in NVCtrl.h. + */ + +Bool XNVCTRLQueryValidAttributeValues ( + Display *dpy, + int screen, + unsigned int display_mask, + unsigned int attribute, + NVCTRLAttributeValidValuesRec *values +); + +/* + * XNVCtrlSelectNotify - + * + * This enables/disables receiving of NV-CONTROL events. The type + * specifies the type of event to enable (currently, the only type is + * ATTRIBUTE_CHANGED_EVENT); onoff controls whether receiving this + * type of event should be enabled (True) or disabled (False). + * + * Returns True if successful, or False if the screen is not + * controlled by the NVIDIA driver. + */ + +Bool XNVCtrlSelectNotify ( + Display *dpy, + int screen, + int type, + Bool onoff +); + + + +/* + * XNVCtrlEvent structure + */ + +typedef struct { + int type; + unsigned long serial; + Bool send_event; /* always FALSE, we don't allow send_events */ + Display *display; + Time time; + int screen; + unsigned int display_mask; + unsigned int attribute; + int value; +} XNVCtrlAttributeChangedEvent; + +typedef union { + int type; + XNVCtrlAttributeChangedEvent attribute_changed; + long pad[24]; +} XNVCtrlEvent; + +#if defined(__cplusplus) +} +#endif + +#endif /* __NVCTRLLIB_H */ diff --git a/ksim/monitors/lm_sensors/ksimsensors.cpp b/ksim/monitors/lm_sensors/ksimsensors.cpp new file mode 100644 index 0000000..e63f5cf --- /dev/null +++ b/ksim/monitors/lm_sensors/ksimsensors.cpp @@ -0,0 +1,189 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "ksimsensors.h" +#include "ksimsensors.moc" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include "sensorsconfig.h" +#include "sensorbase.h" + +KSIM_INIT_PLUGIN(PluginModule) + +PluginModule::PluginModule(const char *name) + : KSim::PluginObject(name) +{ + setConfigFileName(instanceName()); +} + +PluginModule::~PluginModule() +{ +} + +KSim::PluginView *PluginModule::createView(const char *className) +{ + return new SensorsView(this, className); +} + +KSim::PluginPage *PluginModule::createConfigPage(const char *className) +{ + return new SensorsConfig(this, className); +} + +void PluginModule::showAbout() +{ + QString version = kapp->aboutData()->version(); + + KAboutData aboutData(instanceName(), + I18N_NOOP("KSim Sensors Plugin"), version.latin1(), + I18N_NOOP("An lm_sensors plugin for KSim"), + KAboutData::License_GPL, "(C) 2001 Robbie Ward"); + + aboutData.addAuthor("Robbie Ward", I18N_NOOP("Author"), + "linuxphreak@gmx.co.uk"); + + KAboutApplication(&aboutData).exec(); +} + +SensorsView::SensorsView(KSim::PluginObject *parent, const char *name) + : DCOPObject("sensors"), KSim::PluginView(parent, name) +{ + config()->setGroup("Sensors"); + (new QVBoxLayout(this))->setAutoAdd(true); + + connect(SensorBase::self(), SIGNAL(updateSensors(const SensorList &)), + this, SLOT(updateSensors(const SensorList &))); + + insertSensors(); +} + +SensorsView::~SensorsView() +{ +} + +void SensorsView::reparseConfig() +{ + config()->setGroup("Sensors"); + bool displayFahrenheit = config()->readBoolEntry("displayFahrenheit", false); + int updateVal = config()->readNumEntry("sensorUpdateValue", 5); + SensorBase::self()->setDisplayFahrenheit(displayFahrenheit); + SensorBase::self()->setUpdateSpeed(updateVal * 1000); + + QString label; + QStringList names; + SensorItemList sensorItemList; + const SensorList &list = SensorBase::self()->sensorsList(); + + SensorList::ConstIterator it; + for (it = list.begin(); it != list.end(); ++it) { + config()->setGroup("Sensors"); + label = (*it).sensorType() + "/" + (*it).sensorName(); + names = QStringList::split(':', config()->readEntry(label)); + if (names[0] == "1") + sensorItemList.append(SensorItem((*it).sensorId(), names[1])); + } + + if (sensorItemList == m_sensorItemList) + return; + + m_sensorItemList.clear(); + m_sensorItemList = sensorItemList; + insertSensors(false); +} + +void SensorsView::insertSensors(bool createList) +{ + const SensorList &list = SensorBase::self()->sensorsList(); + + if (createList) { + QString label; + QStringList names; + + config()->setGroup("Sensors"); + bool displayFahrenheit = config()->readBoolEntry("displayFahrenheit", false); + int updateVal = config()->readNumEntry("sensorUpdateValue", 5); + SensorBase::self()->setDisplayFahrenheit(displayFahrenheit); + SensorBase::self()->setUpdateSpeed(updateVal * 1000); + + SensorList::ConstIterator it; + for (it = list.begin(); it != list.end(); ++it) { + label = (*it).sensorType() + "/" + (*it).sensorName(); + names = QStringList::split(':', config()->readEntry(label)); + if (names[0] == "1") + m_sensorItemList.append(SensorItem((*it).sensorId(), names[1])); + } + } + + SensorItemList::Iterator item; + for (item = m_sensorItemList.begin(); item != m_sensorItemList.end(); ++item) + (*item).setLabel(new KSim::Label(KSim::Types::None, this)); + + updateSensors(list); +} + +void SensorsView::updateSensors(const SensorList &sensorList) +{ + if (sensorList.isEmpty() || m_sensorItemList.isEmpty()) + return; + + SensorList::ConstIterator it; + for (it = sensorList.begin(); it != sensorList.end(); ++it) { + SensorItemList::Iterator item; + for (item = m_sensorItemList.begin(); item != m_sensorItemList.end(); ++item) { + if ((*item).id == (*it).sensorId()) { + if (!(*item).label->isVisible()) + (*item).label->show(); + + (*item).label->setText((*item).name + ": " + + (*it).sensorValue() + (*it).sensorUnit()); + } + } + } +} + +QString SensorsView::sensorValue(const QString &sensor, + const QString &label1) +{ + const SensorList &list = SensorBase::self()->sensorsList(); + config()->setGroup("Sensors"); + QStringList names = QStringList::split(':', + config()->readEntry(sensor + "/" + label1)); + + if (names[0] == "0" || list.isEmpty()) + return i18n("Sensor specified not found."); + + SensorList::ConstIterator it; + for (it = list.begin(); it != list.end(); ++it) { + if (sensor == (*it).sensorType() && label1 == (*it).sensorName()) { + return names[1] + QString(": ") + (*it).sensorValue() + (*it).sensorUnit(); + } + } + + return i18n("Sensor specified not found."); +} diff --git a/ksim/monitors/lm_sensors/ksimsensors.h b/ksim/monitors/lm_sensors/ksimsensors.h new file mode 100644 index 0000000..8446931 --- /dev/null +++ b/ksim/monitors/lm_sensors/ksimsensors.h @@ -0,0 +1,91 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SENSORS_H +#define SENSORS_H + +#include +#include +#include "ksimsensorsiface.h" + +class KConfig; +class SensorList; +class KInstance; + +/** + * This class is the lm_sensors monitor plugin + * + * @author Robbie Ward + */ +class PluginModule : public KSim::PluginObject +{ + public: + PluginModule(const char *name); + ~PluginModule(); + + virtual KSim::PluginView *createView(const char *); + virtual KSim::PluginPage *createConfigPage(const char *); + + virtual void showAbout(); +}; + +class SensorsView : public KSim::PluginView, public KSimSensorsIface +{ + Q_OBJECT + public: + SensorsView(KSim::PluginObject *parent, const char *name); + ~SensorsView(); + + virtual void reparseConfig(); + virtual QString sensorValue(const QString &, const QString &); + + private slots: + void updateSensors(const SensorList &); + + private: + void insertSensors(bool createList = true); + + class SensorItem + { + public: + SensorItem() : id(-1), label(0) {} + SensorItem(int i, const QString &na) + : id(i), name(na), label(0) {} + ~SensorItem() { delete label; } + + bool operator==(const SensorItem &rhs) const + { + return (id == rhs.id && name == rhs.name); + } + + void setLabel(KSim::Label *lab) + { + delete label; + label = lab; + } + + int id; + QString name; + KSim::Label *label; + }; + + typedef QValueList SensorItemList; + SensorItemList m_sensorItemList; +}; +#endif diff --git a/ksim/monitors/lm_sensors/ksimsensorsiface.h b/ksim/monitors/lm_sensors/ksimsensorsiface.h new file mode 100644 index 0000000..4bd50ce --- /dev/null +++ b/ksim/monitors/lm_sensors/ksimsensorsiface.h @@ -0,0 +1,33 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 - 2004 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIMSENSORSIFACE_H +#define KSIMSENSORSIFACE_H + +#include + +class KSimSensorsIface : virtual public DCOPObject +{ + K_DCOP + k_dcop: + virtual QString sensorValue(const QString &sensorType, + const QString &sensorName) = 0; +}; + +#endif // KSIMSENSORSIFACE_H diff --git a/ksim/monitors/lm_sensors/nv_control.h b/ksim/monitors/lm_sensors/nv_control.h new file mode 100644 index 0000000..d94ee95 --- /dev/null +++ b/ksim/monitors/lm_sensors/nv_control.h @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2004 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of Version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2 + * of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + * + */ + +#ifndef __NVCONTROL_H +#define __NVCONTROL_H + +#define NV_CONTROL_ERRORS 0 +#define NV_CONTROL_EVENTS 1 +#define NV_CONTROL_NAME "NV-CONTROL" + +#define NV_CONTROL_MAJOR 1 +#define NV_CONTROL_MINOR 6 + +#define X_nvCtrlQueryExtension 0 +#define X_nvCtrlIsNv 1 +#define X_nvCtrlQueryAttribute 2 +#define X_nvCtrlSetAttribute 3 +#define X_nvCtrlQueryStringAttribute 4 +#define X_nvCtrlQueryValidAttributeValues 5 +#define X_nvCtrlSelectNotify 6 +#define X_nvCtrlLastRequest (X_nvCtrlSelectNotify + 1) + +typedef struct { + CARD8 reqType; + CARD8 nvReqType; + CARD16 length B16; +} xnvCtrlQueryExtensionReq; +#define sz_xnvCtrlQueryExtensionReq 4 + +typedef struct { + BYTE type; /* X_Reply */ + CARD8 padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 major B16; + CARD16 minor B16; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xnvCtrlQueryExtensionReply; +#define sz_xnvCtrlQueryExtensionReply 32 + +typedef struct { + CARD8 reqType; + CARD8 nvReqType; + CARD16 length B16; + CARD32 screen B32; +} xnvCtrlIsNvReq; +#define sz_xnvCtrlIsNvReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + CARD8 padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 isnv B32; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xnvCtrlIsNvReply; +#define sz_xnvCtrlIsNvReply 32 + +typedef struct { + CARD8 reqType; + CARD8 nvReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 display_mask B32; + CARD32 attribute B32; +} xnvCtrlQueryAttributeReq; +#define sz_xnvCtrlQueryAttributeReq 16 + +typedef struct { + BYTE type; + BYTE pad0; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 flags B32; + INT32 value B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; +} xnvCtrlQueryAttributeReply; +#define sz_xnvCtrlQueryAttributeReply 32 + +typedef struct { + CARD8 reqType; + CARD8 nvReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 display_mask B32; + CARD32 attribute B32; + INT32 value B32; +} xnvCtrlSetAttributeReq; +#define sz_xnvCtrlSetAttributeReq 20 + +typedef struct { + CARD8 reqType; + CARD8 nvReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 display_mask B32; + CARD32 attribute B32; +} xnvCtrlQueryStringAttributeReq; +#define sz_xnvCtrlQueryStringAttributeReq 16 + +/* + * CtrlQueryStringAttribute reply struct + * n indicates the length of the string. + */ +typedef struct { + BYTE type; + BYTE pad0; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 flags B32; + CARD32 n B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; +} xnvCtrlQueryStringAttributeReply; +#define sz_xnvCtrlQueryStringAttributeReply 32 + +typedef struct { + CARD8 reqType; + CARD8 nvReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 display_mask B32; + CARD32 attribute B32; +} xnvCtrlQueryValidAttributeValuesReq; +#define sz_xnvCtrlQueryValidAttributeValuesReq 16 + +typedef struct { + BYTE type; + BYTE pad0; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 flags B32; + INT32 attr_type B32; + INT32 min B32; + INT32 max B32; + CARD32 bits B32; + CARD32 perms B32; +} xnvCtrlQueryValidAttributeValuesReply; +#define sz_xnvCtrlQueryValidAttributeValuesReply 32 + +typedef struct { + CARD8 reqType; + CARD8 nvReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 notifyType B16; + CARD16 onoff B16; +} xnvCtrlSelectNotifyReq; +#define sz_xnvCtrlSelectNotifyReq 12 + +typedef struct { + union { + struct { + BYTE type; + BYTE detail; + CARD16 sequenceNumber B16; + } u; + struct { + BYTE type; + BYTE detail; + CARD16 sequenceNumber B16; + Time time B32; + CARD32 screen B32; + CARD32 display_mask B32; + CARD32 attribute B32; + CARD32 value B32; + CARD32 pad0 B32; + CARD32 pad1 B32; + } attribute_changed; + } u; +} xnvctrlEvent; + + +#endif /* __NVCONTROL_H */ diff --git a/ksim/monitors/lm_sensors/sensorbase.cpp b/ksim/monitors/lm_sensors/sensorbase.cpp new file mode 100644 index 0000000..9ccb247 --- /dev/null +++ b/ksim/monitors/lm_sensors/sensorbase.cpp @@ -0,0 +1,254 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "sensorbase.h" +#include "sensorbase.moc" +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include "NVCtrl.h" +#include "NVCtrlLib.h" + +SensorBase *SensorBase::m_self = 0; +SensorBase *SensorBase::self() +{ + if (!m_self) { + m_self = new SensorBase; + qAddPostRoutine(cleanup); + } + + return m_self; +} + +SensorBase::SensorBase() : QObject() +{ + KSim::Config::config()->setGroup("Sensors"); + QCString sensorsName("libsensors.so"); + + QStringList sensorLocations = KSim::Config::config()->readListEntry("sensorLocations"); + + QStringList::ConstIterator it; + for (it = sensorLocations.begin(); it != sensorLocations.end(); ++it) { + if (QFile::exists((*it).local8Bit() + sensorsName)) { + m_libLocation = (*it).local8Bit() + sensorsName; + break; + } + } + + m_library = KLibLoader::self()->library(m_libLocation); + kdDebug(2003) << sensorsName << " location = " << m_libLocation << endl; + m_loaded = init(); + + { + int eventBase; + int errorBase; + m_hasNVControl = XNVCTRLQueryExtension(qt_xdisplay(), &eventBase, &errorBase) == True; + } + + m_updateTimer = new QTimer(this); + connect(m_updateTimer, SIGNAL(timeout()), SLOT(update())); +} + +SensorBase::~SensorBase() +{ + if (!m_libLocation.isNull()) { + if (m_cleanup) m_cleanup(); + KLibLoader::self()->unloadLibrary(m_libLocation); + } +} + +void SensorBase::setUpdateSpeed(uint speed) +{ + if (m_updateTimer->isActive()) + m_updateTimer->stop(); + + update(); // just to make sure the display is updated ASAP + + if (speed == 0) + return; + + m_updateTimer->start(speed); +} + +void SensorBase::update() +{ + if (!m_loaded) + return; + + m_sensorList.clear(); + const ChipName *chip; + int currentSensor = 0; + int sensor = 0; + + while ((chip = m_detectedChips(&sensor)) != NULL) { + int first = 0, second = 0; + const FeatureData *sFeature = 0; + while ((sFeature = m_allFeatures(*chip, &first, &second)) != NULL) { + if (sFeature->mapping == NoMapping) { + char *name; + double value; + m_label(*chip, sFeature->number, &name); + m_feature(*chip, sFeature->number, &value); + + float returnValue = formatValue(QString::fromUtf8(name), float(value)); + QString label = formatString(QString::fromUtf8(name), returnValue); + QString chipset = chipsetString(chip); + + m_sensorList.append(SensorInfo(currentSensor++, label, + QString::fromUtf8(name), QString::fromUtf8(chip->prefix), + chipset, sensorType(QString::fromLatin1(name)))); + } + } + } + + if (m_hasNVControl) { + int temp = 0; + if (XNVCTRLQueryAttribute(qt_xdisplay(), qt_xscreen(), 0 /* not used? */, NV_CTRL_GPU_CORE_TEMPERATURE, &temp)) { + QString name = QString::fromLatin1("GPU Temp"); + m_sensorList.append(SensorInfo(currentSensor++, QString::number(temp), + name, QString::null, QString::null, sensorType(name))); + } + + if (XNVCTRLQueryAttribute(qt_xdisplay(), qt_xscreen(), 0 /* not used? */, NV_CTRL_AMBIENT_TEMPERATURE, &temp)) { + QString name = QString::fromLatin1("GPU Ambient Temp"); + m_sensorList.append(SensorInfo(currentSensor++, QString::number(temp), + name, QString::null, QString::null, sensorType(name))); + } + + } + + emit updateSensors(m_sensorList); +} + +void SensorBase::cleanup() +{ + if (!m_self) + return; + + delete m_self; + m_self = 0; +} + +bool SensorBase::init() +{ + if (m_libLocation.isNull()) { + kdError() << "Unable to find libsensors.so" << endl; + return false; + } + + m_init = (Init)m_library->symbol("sensors_init"); + if (!m_init) + return false; + + m_error = (Error)m_library->symbol("sensors_strerror"); + if (!m_error) + return false; + + m_detectedChips = (GetDetectedChips *)m_library->symbol("sensors_get_detected_chips"); + m_allFeatures = (GetAllFeatures *)m_library->symbol("sensors_get_all_features"); + m_label = (Label)m_library->symbol("sensors_get_label"); + m_feature = (Feature)m_library->symbol("sensors_get_feature"); + + if (!m_detectedChips || !m_allFeatures || !m_label || !m_feature) + return false; + + m_cleanup = (Cleanup)m_library->symbol("sensors_cleanup"); + if (!m_cleanup) + return false; + + int res; + FILE *input; + + if ((input = fopen("/etc/sensors.conf", "r")) == 0) + return false; + + if ((res = m_init(input))) { + if (res == ProcError) { + kdError() << "There was an error reading the sensor information\n" + << "Make sure sensors.o and i2c-proc.o are loaded" << endl; + } + else { + kdError() << m_error(res) << endl; + } + + fclose(input); + return false; + } + + fclose(input); + + return true; +} + +QString SensorBase::sensorType(const QString &name) +{ + if (name.findRev("fan", -1, false) != -1) + return i18n("Rounds per minute", " RPM"); + + if (name.findRev("temp", -1, false) != -1) + if (SensorBase::fahrenheit()) + return QString::fromLatin1("F"); + else + return QString::fromLatin1("C"); + + if (name.findRev(QRegExp("[^\\+]?[^\\-]?V$")) != -1) + return i18n("Volt", "V"); + + return QString::null; +} + +QString SensorBase::chipsetString(const ChipName *c) +{ + QString data = QString::fromUtf8(c->prefix); + + if (c->bus == BusISA) + return QString().sprintf("%s-isa-%04x", data.utf8().data(), c->addr); + + return QString().sprintf("%s-i2c-%d-%02x", data.utf8().data(), c->bus, c->addr); +} + +float SensorBase::formatValue(const QString &label, float value) +{ + if (label.findRev("temp", -1, false) != -1) + return toFahrenheit(value); + + return value; +} + +QString SensorBase::formatString(const QString &label, float value) +{ + if (label.findRev("fan", -1, false) != -1) + return QString::number(value); + + return QString::number(value,'f',2); +} diff --git a/ksim/monitors/lm_sensors/sensorbase.h b/ksim/monitors/lm_sensors/sensorbase.h new file mode 100644 index 0000000..c819d48 --- /dev/null +++ b/ksim/monitors/lm_sensors/sensorbase.h @@ -0,0 +1,175 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SENSORBASE_H +#define SENSORBASE_H + +#include +#include +#include + +class QTimer; +class KLibrary; + +class SensorInfo +{ + public: + SensorInfo() {} + SensorInfo(int id, + const QString &sensorValue, + const QString &sensorName, + const QString &sensorType, + const QString &chipsetName, + const QString &sensorUnit) + : m_id(id), m_sensor(sensorValue), + m_sensorName(sensorName), + m_sensorType(sensorType), + m_chipsetName(chipsetName), + m_sensorUnit(sensorUnit) {} + + /** + * @return the sensor Id + */ + int sensorId() const { return m_id; } + /** + * @return the current value, eg: 5000 + */ + const QString &sensorValue() const { return m_sensor; } + /** + * @return the sensor name, eg: temp1, fan2 + */ + const QString &sensorName() const { return m_sensorName; } + /** + * @return the sensor type name, eg: w83782d + */ + const QString &sensorType() const { return m_sensorType; } + /** + * @return the chipset name, eg: w83782d-i2c-0-2d + */ + const QString &chipsetName() const { return m_chipsetName; } + /** + * @return the unit name, eg: RPM, C or F if display fahrenheit is enabled + */ + const QString &sensorUnit() const { return m_sensorUnit; } + + private: + int m_id; + QString m_sensor; + QString m_sensorName; + QString m_sensorType; + QString m_chipsetName; + QString m_sensorUnit; +}; + +class SensorList : public QValueList +{ + public: + SensorList() {} + SensorList(const SensorList &sensorList) + : QValueList(sensorList) {} + SensorList(const QValueList &sensorList) + : QValueList(sensorList) {} + SensorList(const SensorInfo &sensor) { append(sensor); } +}; + +class SensorBase : public QObject +{ + Q_OBJECT + public: + static SensorBase *self(); + + const SensorList &sensorsList() const { return m_sensorList; } + bool fahrenheit() { return m_fahrenheit; } + + signals: + void updateSensors(const SensorList&); + + public slots: + void setUpdateSpeed(uint); + void setDisplayFahrenheit(bool fah) { m_fahrenheit = fah; } + + private slots: + void update(); + + protected: + SensorBase(); + ~SensorBase(); + + private: + SensorBase(const SensorBase &); + SensorBase &operator=(const SensorBase &); + + static void cleanup(); + struct ChipName + { + char *prefix; + int bus; + int addr; + char *busname; + }; + + struct FeatureData + { + int number; + const char *name; + int mapping; + int unused; + int mode; + }; + + enum { ProcError=4, NoMapping=-1, BusISA=-1 }; + typedef void (*Cleanup)(); + typedef int (*Init)(FILE *); + typedef const char *(*Error)(int); + typedef const ChipName *(GetDetectedChips)(int *); + typedef const FeatureData *(GetAllFeatures)(ChipName, int *, int *); + typedef int (*Label)(ChipName, int, char **); + typedef int (*Feature)(ChipName, int, double *); + + bool init(); + float toFahrenheit(float value); + QString sensorType(const QString &name); + QString chipsetString(const ChipName *c); + float formatValue(const QString &label, float value); + QString formatString(const QString &label, float value); + + SensorList m_sensorList; + QTimer *m_updateTimer; + KLibrary *m_library; + QCString m_libLocation; + bool m_loaded; + bool m_fahrenheit; + + bool m_hasNVControl; + + Init m_init; + Error m_error; + GetDetectedChips *m_detectedChips; + GetAllFeatures *m_allFeatures; + Label m_label; + Feature m_feature; + Cleanup m_cleanup; + static SensorBase *m_self; +}; + +inline float SensorBase::toFahrenheit(float value) +{ + return fahrenheit() ? (value * (9.0F / 5.0F) + 32.0F) : value; +} +#endif // SENSORBASE_H diff --git a/ksim/monitors/lm_sensors/sensorsconfig.cpp b/ksim/monitors/lm_sensors/sensorsconfig.cpp new file mode 100644 index 0000000..6e2b4b3 --- /dev/null +++ b/ksim/monitors/lm_sensors/sensorsconfig.cpp @@ -0,0 +1,241 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "sensorsconfig.h" +#include "sensorsconfig.moc" +#include "sensorbase.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class SensorViewItem : public QCheckListItem +{ + public: + SensorViewItem(QListView *parent, const QString &text1, + const QString &text2, const QString &text3, + const QString &text4) + : QCheckListItem(parent, text1, CheckBox) + { + setText(1, text2); + setText(2, text3); + setText(3, text4); + } +}; + +SensorsConfig::SensorsConfig(KSim::PluginObject *parent, const char *name) + : KSim::PluginPage(parent, name) +{ + m_layout = new QGridLayout(this); + m_layout->setSpacing(6); + m_neverShown = true; + + m_sensorView = new KListView(this); + m_sensorView->addColumn(i18n("No.")); + m_sensorView->addColumn(i18n("Label")); + m_sensorView->addColumn(i18n("Sensors")); + m_sensorView->addColumn(i18n("Value")); + m_sensorView->setColumnWidth(0, 40); + m_sensorView->setColumnWidth(1, 60); + m_sensorView->setColumnWidth(2, 80); + m_sensorView->setAllColumnsShowFocus(true); + connect(m_sensorView, SIGNAL(contextMenu(KListView *, + QListViewItem *, const QPoint &)), this, SLOT(menu(KListView *, + QListViewItem *, const QPoint &))); + + connect( m_sensorView, SIGNAL( doubleClicked( QListViewItem * ) ), + SLOT( modify( QListViewItem * ) ) ); + + m_layout->addMultiCellWidget(m_sensorView, 1, 1, 0, 3); + + m_modify = new QPushButton( this ); + m_modify->setText( i18n( "Modify..." ) ); + connect( m_modify, SIGNAL( clicked() ), SLOT( modify() ) ); + m_layout->addMultiCellWidget( m_modify, 2, 2, 3, 3 ); + + m_fahrenBox = new QCheckBox(i18n("Display Fahrenheit"), this); + m_layout->addMultiCellWidget(m_fahrenBox, 3, 3, 0, 3); + + m_updateLabel = new QLabel(this); + m_updateLabel->setText(i18n("Update interval:")); + m_updateLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, + QSizePolicy::Fixed)); + m_layout->addMultiCellWidget(m_updateLabel, 4, 4, 0, 0); + + m_sensorSlider = new KIntSpinBox(this); + m_layout->addMultiCellWidget(m_sensorSlider, 4, 4, 1, 1); + + QLabel *intervalLabel = new QLabel(this); + intervalLabel->setText(i18n("seconds")); + intervalLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, + QSizePolicy::Fixed)); + m_layout->addMultiCellWidget(intervalLabel, 4, 4, 2, 2); +} + +SensorsConfig::~SensorsConfig() +{ +} + +void SensorsConfig::saveConfig() +{ + config()->setGroup("Sensors"); + config()->writeEntry("sensorUpdateValue", m_sensorSlider->value()); + config()->writeEntry("displayFahrenheit", m_fahrenBox->isChecked()); + + for (QListViewItemIterator it(m_sensorView); it.current(); ++it) { + config()->setGroup("Sensors"); + config()->writeEntry(it.current()->text(2), + QString::number(static_cast(it.current())->isOn()) + + ":" + it.current()->text(1)); + } +} + +void SensorsConfig::readConfig() +{ + config()->setGroup("Sensors"); + m_fahrenBox->setChecked(config()->readBoolEntry("displayFahrenheit", false)); + m_sensorSlider->setValue(config()->readNumEntry("sensorUpdateValue", 15)); + + QStringList names; + for (QListViewItemIterator it(m_sensorView); it.current(); ++it) { + config()->setGroup("Sensors"); + names = QStringList::split(":", config()->readEntry(it.current()->text(2), "0:")); + if (!names[1].isNull()) + it.current()->setText(1, names[1]); + static_cast(it.current())->setOn(names[0].toInt()); + } +} + +void SensorsConfig::menu(KListView *, QListViewItem *, const QPoint &) +{ + m_popupMenu = new QPopupMenu(this); + + m_popupMenu->insertItem(i18n("Select All"), 1); + m_popupMenu->insertItem(i18n("Unselect All"), 2); + m_popupMenu->insertItem(i18n("Invert Selection"), 3); + + switch (m_popupMenu->exec(QCursor::pos())) { + case 1: + selectAll(); + break; + case 2: + unSelectAll(); + break; + case 3: + invertSelect(); + break; + } + + delete m_popupMenu; +} + +void SensorsConfig::selectAll() +{ + for (QListViewItemIterator it(m_sensorView); it.current(); ++it) + static_cast(it.current())->setOn(true); +} + +void SensorsConfig::unSelectAll() +{ + for (QListViewItemIterator it(m_sensorView); it.current(); ++it) + static_cast(it.current())->setOn(false); +} + +void SensorsConfig::invertSelect() +{ + for (QListViewItemIterator it(m_sensorView); it.current(); ++it) { + QCheckListItem *item = static_cast(it.current()); + if (item->isOn()) + item->setOn(false); + else + item->setOn(true); + } +} + +void SensorsConfig::initSensors() +{ + const SensorList &sensorList = SensorBase::self()->sensorsList(); + + int i = 0; + QString label; + QStringList sensorInfo; + SensorList::ConstIterator it; + for (it = sensorList.begin(); it != sensorList.end(); ++it) { + label.sprintf("%02i", ++i); + (void) new SensorViewItem(m_sensorView, label, + (*it).sensorName(), (*it).sensorType() + "/" + (*it).sensorName(), + (*it).sensorValue() + (*it).sensorUnit()); + } + + QStringList names; + for (QListViewItemIterator it(m_sensorView); it.current(); ++it) { + config()->setGroup("Sensors"); + names = QStringList::split(":", config()->readEntry(it.current()->text(2), "0:")); + if (!names[1].isNull()) + it.current()->setText(1, names[1]); + static_cast(it.current())->setOn(names[0].toInt()); + } +} + +void SensorsConfig::modify( QListViewItem * item ) +{ + if ( !item ) + return; + + bool ok = false; + QString text = KInputDialog::getText( i18n( "Modify Sensor Label" ), i18n( "Sensor label:" ), + item->text( 1 ), &ok, this ); + + if ( ok ) + item->setText( 1, text ); +} + +void SensorsConfig::modify() +{ + modify( m_sensorView->selectedItem() ); +} + +void SensorsConfig::showEvent(QShowEvent *) +{ + if (m_neverShown) { + initSensors(); + m_neverShown = false; + } + else { + const SensorList &list = SensorBase::self()->sensorsList(); + SensorList::ConstIterator it; + for (it = list.begin(); it != list.end(); ++it) { + QListViewItem *item = m_sensorView->findItem((*it).sensorName(), 1); + if (item) + item->setText(3, (*it).sensorValue() + (*it).sensorUnit()); + } + } +} diff --git a/ksim/monitors/lm_sensors/sensorsconfig.h b/ksim/monitors/lm_sensors/sensorsconfig.h new file mode 100644 index 0000000..28d656e --- /dev/null +++ b/ksim/monitors/lm_sensors/sensorsconfig.h @@ -0,0 +1,69 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SENSORSIMPL_H +#define SENSORSIMPL_H + +#include + +class QPushButton; +class QCheckListItem; +class QGridLayout; +class QLabel; +class KListView; +class QListViewItem; +class QPopupMenu; +class KIntSpinBox; +class QCheckBox; +class QTimer; + +class SensorsConfig : public KSim::PluginPage +{ + Q_OBJECT + public: + SensorsConfig(KSim::PluginObject *parent, const char *name); + ~SensorsConfig(); + + void saveConfig(); + void readConfig(); + + private slots: + void menu(KListView *, QListViewItem *, const QPoint &); + void initSensors(); + void selectAll(); + void unSelectAll(); + void invertSelect(); + + void modify( QListViewItem * ); + void modify(); + + protected: + void showEvent(QShowEvent *); + + private: + bool m_neverShown; + QLabel *m_updateLabel; + KIntSpinBox *m_sensorSlider; + KListView *m_sensorView; + QCheckBox *m_fahrenBox; + QGridLayout *m_layout; + QPopupMenu *m_popupMenu; + QPushButton * m_modify; +}; +#endif diff --git a/ksim/monitors/mail/Makefile.am b/ksim/monitors/mail/Makefile.am new file mode 100644 index 0000000..bf89a1d --- /dev/null +++ b/ksim/monitors/mail/Makefile.am @@ -0,0 +1,15 @@ +kde_module_LTLIBRARIES = ksim_mail.la +ksim_mail_la_SOURCES = ksimmail.cpp + +ksim_mail_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +ksim_mail_la_LIBADD = $(LIB_KIO) ../../library/libksimcore.la + +EXTRA_DIST = mail.desktop + +INCLUDES= -I$(top_srcdir)/ksim/library \ + $(all_includes) + +METASOURCES = AUTO + +mon_DATA = mail.desktop +mondir = $(kde_datadir)/ksim/monitors diff --git a/ksim/monitors/mail/ksimmail.cpp b/ksim/monitors/mail/ksimmail.cpp new file mode 100644 index 0000000..6ca1142 --- /dev/null +++ b/ksim/monitors/mail/ksimmail.cpp @@ -0,0 +1,160 @@ +/* + Copyright (c) 2002 Malte Starostik + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// $Id$ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "ksimmail.moc" + +KSIM_INIT_PLUGIN( MailPlugin ); + +MailPlugin::MailPlugin( const char* name ) + : KSim::PluginObject( name ) +{ + setConfigFileName(instanceName()); +} + +MailPlugin::~MailPlugin() +{ +} + +KSim::PluginView* MailPlugin::createView( const char* name ) +{ + return new MailView( this, name ); +} + +KSim::PluginPage* MailPlugin::createConfigPage( const char* name ) +{ + return new MailConfig( this, name ); +} + +void MailPlugin::showAbout() +{ + KAboutData about( instanceName(), + I18N_NOOP( "KSim Mail Plugin" ), "0.1", + I18N_NOOP( "A mail monitor plugin for KSim" ), + KAboutData::License_GPL, "(c) 2002 Malte Starostik" ); + about.addAuthor( "Malte Starostik", I18N_NOOP( "Author" ), "malte@kde.org" ); + + KAboutApplication( &about ).exec(); +} + +MailView::MailView( KSim::PluginObject* parent, const char* name ) + : KSim::PluginView( parent, name ) +{ + QVBoxLayout* layout = new QVBoxLayout( this ); + + MailLabel* label = new MailLabel( this ); + layout->addWidget( label, 0, AlignHCenter ); +} + +MailView::~MailView() +{ +} + +void MailView::reparseConfig() +{ +} + +void MailView::updateDisplay() +{ +} + +MailLabel::MailLabel( QWidget* parent ) + : KSim::Label( KSim::Types::Mail, parent ) +{ +// label->setPixmap( KSim::ThemeLoader::self().current().krellMail() ); + configureObject( false ); + QTimer* timer = new QTimer( this ); + connect( timer, SIGNAL( timeout() ), SLOT( animation() ) ); + timer->start( 100 ); +} + +MailLabel::~MailLabel() +{ +} + +void MailLabel::configureObject( bool repaint ) +{ + m_envelope.load( themeLoader().current().mailPixmap() ); + m_frames = themeLoader().current().mailFrames(); + m_delay = themeLoader().current().mailDelay(); + + if ( !m_frames ) m_frames = 18; + if ( !m_delay ) m_delay = 1; + + setPixmap( frame( m_envelope, 1 ) ); + + KSim::Label::configureObject( repaint ); +} + +void MailLabel::paintEvent( QPaintEvent* e ) +{ + KSim::Label::paintEvent( e ); +} + +void MailLabel::animation() +{ + static int f = 1; + setPixmap( frame( m_envelope, f ) ); + if ( f++ >= m_frames ) f = 1; +} + +QPixmap MailLabel::frame( const QPixmap& source, int number ) const +{ + QPixmap result( source.width(), source.height() / m_frames ); + bitBlt( &result, 0, 0, &source, 0, number * source.height() / m_frames ); + if ( source.mask() ) + { + QBitmap mask( result.size() ); + bitBlt( &mask, 0, 0, source.mask(), 0, number * source.height() / m_frames ); + result.setMask( mask ); + } + return result; +} + +MailConfig::MailConfig( KSim::PluginObject* parent, const char* name ) + : KSim::PluginPage( parent, name ) +{ +} + +MailConfig::~MailConfig() +{ +} + +void MailConfig::saveConfig() +{ +} + +void MailConfig::readConfig() +{ +} + +// vim: ts=4 sw=4 noet diff --git a/ksim/monitors/mail/ksimmail.h b/ksim/monitors/mail/ksimmail.h new file mode 100644 index 0000000..fd8790a --- /dev/null +++ b/ksim/monitors/mail/ksimmail.h @@ -0,0 +1,90 @@ +/* + Copyright (c) 2002 Malte Starostik + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// $Id$ + +#ifndef __ksimmail_h__ +#define __ksimmail_h__ + +#include + +class MailPlugin : public KSim::PluginObject +{ +public: + MailPlugin( const char* name ); + ~MailPlugin(); + + virtual KSim::PluginView* createView( const char* ); + virtual KSim::PluginPage* createConfigPage( const char* ); + + virtual void showAbout(); +}; + +class MailView : public KSim::PluginView +{ + Q_OBJECT +public: + MailView( KSim::PluginObject* parent, const char* name ); + ~MailView(); + + virtual void reparseConfig(); + +private slots: + void updateDisplay(); +}; + +class MailLabel : public KSim::Label +{ + Q_OBJECT +public: + MailLabel( QWidget* parent ); + virtual ~MailLabel(); + + virtual void configureObject( bool ); + +protected: + virtual void paintEvent( QPaintEvent* ); + +private slots: + void animation(); + +private: + QPixmap frame( const QPixmap& source, int number ) const; + +private: + QPixmap m_envelope; + QPixmap m_penguin; + int m_frames; + int m_delay; +}; + +class MailConfig : public KSim::PluginPage +{ + Q_OBJECT +public: + MailConfig( KSim::PluginObject* parent, const char* name ); + ~MailConfig(); + + virtual void saveConfig(); + virtual void readConfig(); +}; + +#endif + +// vim: ts=4 sw=4 noet diff --git a/ksim/monitors/mail/mail.desktop b/ksim/monitors/mail/mail.desktop new file mode 100644 index 0000000..f65ed27 --- /dev/null +++ b/ksim/monitors/mail/mail.desktop @@ -0,0 +1,119 @@ +[Desktop Entry] +Comment=Mail Monitor Plugin +Comment[af]=Pos Monitor Inplak +Comment[ar]=ملحق مراقبة البريد +Comment[bg]=Мониторинг на електронната поща +Comment[bs]=Dodatak za praćenje pošte +Comment[ca]=Monitor de correu +Comment[cs]=Modul pro monitorování pošty +Comment[cy]=Atodyn Monitro Post +Comment[da]=Postovervågnings-plugin +Comment[de]=Hilfsprogramm zur Mailüberwachung +Comment[el]=Πρόσθετο εποπτείας αλληλογραφίας +Comment[eo]=Disk-observa kromaĵo +Comment[es]=Extensión de monitorización de correo +Comment[et]=E-posti monitooring +Comment[eu]=Postaren Plugin Begiralea +Comment[fa]=وصلۀ نمایشگر نامه +Comment[fi]=Sähköpostin monitorointisovelma +Comment[fr]=Module de surveillance de boîtes aux lettres +Comment[ga]=Breiseán Monatóireachta Ríomhphoist +Comment[he]=תוסף צג דואר +Comment[hi]=डाक मॉनीटर प्लगइन +Comment[hu]=E-mail-figyelő bővítőmodul +Comment[is]=Pósteftirlitsforrit +Comment[it]=Plugin di controllo posta +Comment[ja]=メールモニタプラグイン +Comment[ka]= ფოსტის მონიტორის მოდული +Comment[kk]=Поштаны бақылау модулі +Comment[km]=កម្មវិធី​ជំនួយ​របស់​កម្មវិធី​ត្រួតពិនិត្យ​សំបុត្រ +Comment[lt]=Pašto stebėtojo priedas +Comment[mk]=Приклучок за следење на е-поштата +Comment[ms]=Plug masuk Pemerhati Mel +Comment[nb]=Programtillegg for E-postovervåking +Comment[nds]=Nettpost-Kiekmoduul +Comment[ne]=मेल मोनिटर प्लगइन +Comment[nl]=Mail monitor-plugin +Comment[nn]=Programtillegg for e-postovervaking +Comment[pa]=ਪੱਤਰ ਨਿਗਰਾਨ ਪਲੱਗਿੰਨ +Comment[pl]=Stan skrzynki pocztowej +Comment[pt]='Plugin' de Monitorização do Correio +Comment[pt_BR]=Plug-in de monitoramento de e-mail +Comment[ro]=Modul monitorizare e-mail +Comment[ru]=Монитор почты +Comment[sk]=Modul pre monitorovanie pošty +Comment[sl]=Vstavek za opazovanje pošte +Comment[sr]=Прикључак за надгледање поште +Comment[sr@Latn]=Priključak za nadgledanje pošte +Comment[sv]=Insticksprogram för e-postövervakning +Comment[ta]= அஞ்சல் கண்காணி சொருகுப்பொருள் +Comment[tg]=Модули Дидабони Пост +Comment[th]=ปลั๊กอินตรวจสอบจดหมาย +Comment[tr]=Posta İzleyici Eklentisi +Comment[uk]=Втулок датчика пошти +Comment[uz]=Xat-xabarni nazorat qilish plagini +Comment[uz@cyrillic]=Хат-хабарни назорат қилиш плагини +Comment[wa]=Tchôke-divins di corwaitaedje di l' emilaedje +Comment[xh]=Iplagi efakiweyo Monitor Yeposi +Comment[zh_CN]=邮件监视器插件 +Comment[zh_TW]=電子郵件監視器外掛程式 +Comment[zu]=I-plugin Yomlawuli Weposi +Icon=kmail +Name=Mail +Name[af]=Pos +Name[ar]=البريد +Name[bg]=Поща +Name[br]=Lizher +Name[ca]=Correu +Name[cs]=Pošta +Name[cy]=Post +Name[da]=Post +Name[el]=Αλληλογραφία +Name[eo]=Retpoŝto +Name[es]=Correo +Name[et]=Kirjad +Name[eu]=Posta +Name[fa]=نامه +Name[fi]=Sähköposti +Name[fr]=Courrier +Name[ga]=Ríomhphost +Name[he]=דואר +Name[hi]=डाक +Name[hr]=Pošta +Name[is]=Póstur +Name[it]=Posta +Name[ja]=メール +Name[ka]=ფოსტა +Name[kk]=Пошта +Name[km]=សំបុត្រ +Name[lt]=Paštas +Name[lv]=Pasts +Name[mk]=Е-пошта +Name[mt]=Imejl +Name[nb]=E-Post +Name[nds]=Nettpost +Name[ne]=मेल +Name[nn]=E-post +Name[pa]=ਪੱਤਰ +Name[pl]=Poczta +Name[pt]=E-mail +Name[pt_BR]=E-mail +Name[ru]=Почта +Name[sk]=Pošta +Name[sl]=Pošta +Name[sr]=Пошта +Name[sr@Latn]=Pošta +Name[sv]=E-post +Name[ta]= அஞ்சல் +Name[tg]=Пост +Name[th]=จดหมาย +Name[tr]=E-posta +Name[uk]=Пошта +Name[uz]=Xat-xabar +Name[uz@cyrillic]=Хат-хабар +Name[wa]=Emilaedje +Name[xh]=Iposi +Name[zh_CN]=邮件 +Name[zh_TW]=電子郵件 +Name[zu]=Iposi +X-KSIM-LIBRARY=mail diff --git a/ksim/monitors/net/Makefile.am b/ksim/monitors/net/Makefile.am new file mode 100644 index 0000000..291eb71 --- /dev/null +++ b/ksim/monitors/net/Makefile.am @@ -0,0 +1,14 @@ +kde_module_LTLIBRARIES = ksim_net.la +ksim_net_la_SOURCES = ksimnet.cpp netdialog.cpp netconfig.cpp + +ksim_net_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +ksim_net_la_LIBADD = ../../library/libksimcore.la $(LIB_KIO) + +EXTRA_DIST = Net.desktop + +INCLUDES= -I$(top_srcdir)/ksim/library $(all_includes) + +METASOURCES = AUTO + +mon_DATA = Net.desktop +mondir = $(kde_datadir)/ksim/monitors diff --git a/ksim/monitors/net/Net.desktop b/ksim/monitors/net/Net.desktop new file mode 100644 index 0000000..2fa6b87 --- /dev/null +++ b/ksim/monitors/net/Net.desktop @@ -0,0 +1,112 @@ +[Desktop Entry] +Comment=Net Status Monitor +Comment[ar]=مراقب حالة الشبكة +Comment[bg]=Мониторинг на мрежата +Comment[bs]=Nadzor statusa mreže +Comment[ca]=Monitor de l'estat de xarxa +Comment[cs]=Monitor stavu sítě +Comment[cy]=Monitr Statws Rhwyd +Comment[da]=Overvågning af netstatus +Comment[de]=Statusanzeige fürs Netzwerk +Comment[el]=Επόπτης κατάστασης δικτύου +Comment[eo]=Rigardilo por la retstato +Comment[es]=Monitor de estado de la red +Comment[et]=Võrgu oleku monitooring +Comment[eu]=Sarearen Egoera Begiralea +Comment[fa]=Net نمایشگر وضعیت +Comment[fi]=Verkon tilavalvonta +Comment[fr]=Indicateur d'état réseau +Comment[ga]=Monatóir Stádais an Ghréasáin +Comment[he]=צג מצב רשת +Comment[hi]=नेट स्थिति मॉनीटर +Comment[hu]=Hálózati állapotfigyelő +Comment[is]=Eftirlit með stöðu netsins +Comment[it]=Controllo dello stato della rete +Comment[ja]=ネットワーク状態モニタ +Comment[ka]=ქსელის სტატუსის სტატუსი +Comment[kk]=Желінің күйін бақылау +Comment[km]=កម្មវិធី​ត្រួតពិនិត្យ​ស្ថានភាព​បណ្តាញ +Comment[lt]=Net būsenos stebėtojas +Comment[mk]=Монитор за статусот на мрежата +Comment[ms]=Pemerhati Status Net +Comment[nb]=Overvåkning av nettstatus +Comment[nds]=Statuskieker för't Nettwark +Comment[ne]=सञ्जाल स्थिति मोनिटर +Comment[nl]=Netstatus-monitor +Comment[nn]=Overvaking av nettstatus +Comment[pa]=ਨੈੱਟ ਹਾਲਤ ਨਿਗਰਾਨ +Comment[pl]=Ruch w sieci +Comment[pt]=Monitor de Estado da Rede +Comment[pt_BR]=Monitor de estado da rede +Comment[ro]=Monitor stare reţea +Comment[ru]=Монитор сети +Comment[sk]=Monitor stavu siete +Comment[sl]=Nadzornik stanja mreže +Comment[sr]=Надгледање статуса мреже +Comment[sr@Latn]=Nadgledanje statusa mreže +Comment[sv]=Övervakar nätverkets status +Comment[ta]=வலை நிலை கண்காணி +Comment[tg]=Дидабони Ҳолати Шабака +Comment[th]=เครื่องมือสอดส่องสถานะของเน็ต +Comment[tr]=Ağ İçin Durum İzleyici +Comment[uk]=Монітор стану мережі +Comment[uz]=Tarmoqni nazorat qilish plagini +Comment[uz@cyrillic]=Тармоқни назорат қилиш плагини +Comment[wa]=Corwaitoe di l' estat del rantoele +Comment[zh_CN]=网络状态监视器 +Comment[zh_TW]=網路狀態監視器 +Comment[zu]=Umlawuli Wezinga Lenethi +Icon=network +Name=Net +Name[ar]=الشبكة +Name[bg]=Мрежа +Name[br]=Rouedad +Name[ca]=Xarxa +Name[cs]=Síť +Name[cy]=Rhwyd +Name[el]=Δίκτυο +Name[eo]=Reto +Name[es]=Red +Name[ga]=Gréasán +Name[he]=רשת +Name[hi]=नेट +Name[is]=Netið +Name[it]=Rete +Name[ja]=ネット +Name[kk]=Желі +Name[km]=បណ្តាញ +Name[lv]=Tīkls +Name[mk]=Мрежа +Name[nb]=Nett +Name[nds]=Nett +Name[ne]=सञ्जाल +Name[nn]=Nett +Name[pa]=ਨੈੱਟ +Name[pl]=Sieć +Name[pt]=Rede +Name[pt_BR]=Rede +Name[ro]=Reţea +Name[ru]=Сеть +Name[sk]=Sieť +Name[sl]=Mreža +Name[sr]=Мрежа +Name[sr@Latn]=Mreža +Name[sv]=Nätverk +Name[ta]= வலை +Name[tg]=Шабака +Name[th]=เน็ต +Name[tr]=ağ +Name[uk]=Мережа +Name[uz]=Tarmoq +Name[uz@cyrillic]=Тармоқ +Name[wa]=Rantoele +Name[xh]=Umnatha +Name[zh_CN]=网络 +Name[zh_TW]=網路 +Name[zu]=Inethi +X-KSIM-VERSION=0.1 +X-KSIM-LIBRARY=net +X-KSIM-COPYRIGHT=(C) 2001 Robbie Ward +X-KSIM-EMAIL=linuxphreak@gmx.co.uk +X-KSIM-PREFS=Network +X-KSIM-AUTHOR=Robbie Ward diff --git a/ksim/monitors/net/ksimnet.cpp b/ksim/monitors/net/ksimnet.cpp new file mode 100644 index 0000000..45f86c2 --- /dev/null +++ b/ksim/monitors/net/ksimnet.cpp @@ -0,0 +1,672 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#ifdef __FreeBSD__ +#include +#include +#include +#include +#include +#include + +static int mib[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ksimnet.h" +#include "netconfig.h" +#include + +#define NET_UPDATE 1000 +#define LED_UPDATE 125 + +KSIM_INIT_PLUGIN(NetPlugin) + +NetPlugin::NetPlugin(const char *name) + : KSim::PluginObject(name) +{ + setConfigFileName(instanceName()); +} + +NetPlugin::~NetPlugin() +{ +} + +KSim::PluginView *NetPlugin::createView(const char *className) +{ + return new NetView(this, className); +} + +KSim::PluginPage *NetPlugin::createConfigPage(const char *className) +{ + return new NetConfig(this, className); +} + +void NetPlugin::showAbout() +{ + QString version = kapp->aboutData()->version(); + + KAboutData aboutData(instanceName(), + I18N_NOOP("KSim Net Plugin"), version.latin1(), + I18N_NOOP("A net plugin for KSim"), + KAboutData::License_GPL, "(C) 2001 Robbie Ward"); + + aboutData.addAuthor("Robbie Ward", I18N_NOOP("Author"), + "linuxphreak@gmx.co.uk"); + aboutData.addAuthor("Heitham Omar", I18N_NOOP("FreeBSD ports"), + "super_ice@ntlworld.com"); + + KAboutApplication(&aboutData).exec(); +} + +NetView::NetView(KSim::PluginObject *parent, const char *name) + : KSim::PluginView(parent, name) +{ +#ifdef __linux__ + m_procStream = 0L; + if ((m_procFile = fopen("/proc/net/dev", "r"))) + m_procStream = new QTextStream(m_procFile, IO_ReadOnly); +#endif +#ifdef __FreeBSD__ + m_buf = 0; + m_allocSize = 0; +#endif + + m_firstTime = true; + m_netLayout = new QVBoxLayout(this); + + m_networkList = createList(); + addDisplay(); + + m_netTimer = new QTimer(this); + connect(m_netTimer, SIGNAL(timeout()), SLOT(updateGraph())); + m_netTimer->start(NET_UPDATE); + + m_lightTimer = new QTimer(this); + connect(m_lightTimer, SIGNAL(timeout()), SLOT(updateLights())); + m_lightTimer->start(LED_UPDATE); + + updateGraph(); +} + +NetView::~NetView() +{ +#ifdef __linux__ + delete m_procStream; + + if (m_procFile) + fclose(m_procFile); +#endif + + cleanup(); +} + +void NetView::reparseConfig() +{ + Network::List networkList = createList(); + if ( networkList == m_networkList ) + return; + + m_netTimer->stop(); + m_lightTimer->stop(); + m_firstTime = true; + + cleanup(); + + m_networkList = networkList; + addDisplay(); + + m_netTimer->start(NET_UPDATE); + m_lightTimer->start(LED_UPDATE); +} + +void NetView::cleanup() +{ + Network::List::Iterator it; + for ( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + ( *it ).cleanup(); + } + + m_networkList.clear(); +} + +void NetView::addDisplay() +{ + int i = 0; + + Network::List::Iterator it; + for ( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + KSim::LedLabel *led = addLedLabel( ( *it ).name() ); + KSim::Label *label = ( ( *it ).showTimer() ? addLabel() : 0L ); + QPopupMenu * popup = ( ( *it ).commandsEnabled() ? + addPopupMenu( ( *it ).name(), i ) : 0L ); + KSim::Chart *chart = addChart(); + //KSim::LedLabel *led = addLedLabel( ( *it ).name() ); + //KSim::Label *label = ( ( *it ).showTimer() ? addLabel() : 0L ); + //QPopupMenu * popup = ( ( *it ).commandsEnabled() ? + //addPopupMenu( ( *it ).name(), i ) : 0L ); + + if ( ( *it ).commandsEnabled() ) + { + if ( chart ) + { + chart->installEventFilter( this ); + } + + if ( led ) + { + led->installEventFilter( this ); + } + + if ( label ) + { + label->installEventFilter( this ); + } + } + + ( *it ).setDisplay( chart, led, label, popup ); + ++i; + } +} + +// Run the connect command +void NetView::runConnectCommand( int value ) +{ + int i = 0; + Network::List::ConstIterator it; + for ( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + if ( value == i ) + { + // I use KRun here as it provides startup notification + if ( !( *it ).connectCommand().isNull() ) + { + KRun::runCommand( ( *it ).connectCommand() ); + } + + break; + } + ++i; + } +} + +// Run the disconnect command +void NetView::runDisconnectCommand( int value ) +{ + int i = 0; + Network::List::ConstIterator it; + for ( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + if ( value == i ) + { + // I use KRun here as it provides startup notification + if ( !( *it ).disconnectCommand().isNull() ) + { + KRun::runCommand( ( *it ).disconnectCommand() ); + } + + break; + } + + ++i; + } +} + +Network::List NetView::createList() const +{ + config()->setGroup( "Net" ); + int amount = config()->readNumEntry( "deviceAmount", 0 ); + + Network::List list; + for ( int i = 0; i < amount; ++i ) + { + if ( !config()->hasGroup( "device-" + QString::number( i ) ) ) + { + continue; + } + + config()->setGroup( "device-" + QString::number( i ) ); + + list.append( Network( config()->readEntry( "deviceName" ), + config()->readEntry( "deviceFormat" ), + config()->readBoolEntry( "showTimer" ), + config()->readBoolEntry( "commands" ), + config()->readEntry( "cCommand" ), + config()->readEntry("dCommand") ) ); + } + + qHeapSort( list ); + return list; +} + +void NetView::updateLights() +{ + Network::List::Iterator it; + for ( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + if ( isOnline( ( *it ).name() ) ) + { + unsigned long receiveDiff = ( *it ).data().in - ( *it ).oldData().in; + unsigned long sendDiff = ( *it ).data().out - ( *it ).oldData().out; + unsigned long halfMax = ( *it ).maxValue() / 2; + + ( *it ).led()->setMaxValue( ( *it ).maxValue() / 1024 ); + ( *it ).led()->setValue( receiveDiff / 1024 ); + + if ( receiveDiff == 0 ) + { + ( *it ).led()->setOff( KSim::Led::First ); + } + else if ( ( receiveDiff / 1024 ) >= halfMax ) + { + ( *it ).led()->setOn( KSim::Led::First ); + } + else + { + ( *it ).led()->toggle( KSim::Led::First ); + } + + if ( sendDiff == 0 ) + { + ( *it ).led()->setOff( KSim::Led::Second ); + } + else if ( ( sendDiff / 1024 ) >= halfMax ) + { + ( *it ).led()->setOn( KSim::Led::Second ); + } + else + { + ( *it ).led()->toggle( KSim::Led::Second ); + } + } + else + { + ( *it ).led()->setMaxValue( 0 ); + ( *it ).led()->setValue( 0 ); + ( *it ).led()->setOff( KSim::Led::First ); + ( *it ).led()->setOff( KSim::Led::Second ); + } + } +} + +void NetView::updateGraph() +{ + int timer = 0; + int hours = 0; + int minutes = 0; + int seconds = 0; + + time_t start = 0; + struct stat st; + + QTime netTime; + QString timeDisplay; + QString pid( "/var/run/%1.pid" ); + QString newPid; + + Network::List::Iterator it; + for ( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + if ( isOnline( ( *it ).name() ) ) + { + NetData data; + + if ( ( *it ).label() ) + { + timeDisplay = ( *it ).format(); + newPid = pid.arg( ( *it ).name() ); + + if ( QFile::exists( newPid ) && stat( QFile::encodeName( newPid ).data(), &st ) == 0 ) + { + start = st.st_mtime; + + timer = static_cast( difftime( time( 0 ), start ) ); + hours = timer / 3600; + minutes = (timer - hours * 3600) / 60; + seconds = timer % 60; + if ( netTime.isValid( hours, minutes, seconds ) ) + netTime.setHMS( hours, minutes, seconds ); + } + + // Keep backwards compat for now + if ( timeDisplay.contains( '%' ) > 0 ) + timeDisplay.replace( '%', "" ); + + ( *it ).label()->setText( netTime.toString( timeDisplay ) ); + } + + netStatistics( ( *it ).name(), data ); + ( *it ).setData( data ); + + unsigned long receiveDiff = data.in - ( *it ).oldData().in; + unsigned long sendDiff = data.out - ( *it ).oldData().out; + + if ( m_firstTime ) + { + receiveDiff = sendDiff = 0; + } + + ( *it ).chart()->setValue( receiveDiff, sendDiff ); + ( *it ).setMaxValue( ( *it ).chart()->maxValue() ); + + QString receiveString = KGlobal::locale()->formatNumber( ( float ) receiveDiff / 1024.0, 1 ); + QString sendString = KGlobal::locale()->formatNumber( ( float ) sendDiff / 1024.0, 1 ); + + ( *it ).chart()->setText( i18n( "in: %1k" ).arg( receiveString ), + i18n( "out: %1k" ).arg( sendString ) ); + } + else + { + ( *it ).setData( NetData() ); + ( *it ).chart()->setValue( 0, 0 ); + + ( *it ).chart()->setText( i18n( "in: %1k" ).arg( KGlobal::locale()->formatNumber( 0.0, 1 ) ), + i18n( "out: %1k" ).arg( KGlobal::locale()->formatNumber( 0.0, 1 ) ) ); + + if ( ( *it ).label() ) + ( *it ).label()->setText( i18n( "offline" ) ); + } + } + + if ( m_firstTime ) + m_firstTime = false; +} + +KSim::Chart *NetView::addChart() +{ + KSim::Chart *chart = new KSim::Chart(false, 0, this); + m_netLayout->addWidget(chart); + chart->show(); + return chart; +} + +KSim::LedLabel *NetView::addLedLabel(const QString &device) +{ + KSim::LedLabel *ledLabel = new KSim::LedLabel(0, KSim::Types::Net, + device, this); + + ledLabel->show(); + m_netLayout->addWidget(ledLabel); + return ledLabel; +} + +KSim::Label *NetView::addLabel() +{ + KSim::Label *label = new KSim::Label(KSim::Types::None, this); + label->show(); + m_netLayout->addWidget(label); + return label; +} + +QPopupMenu *NetView::addPopupMenu(const QString &device, int value) +{ + QPopupMenu *popup = new QPopupMenu(this); + popup->insertItem(SmallIcon("network"), i18n("Connect"), this, + SLOT(runConnectCommand(int)), 0, 1); + popup->setItemParameter(1, value); + popup->insertItem(SmallIcon("network"), i18n("Disconnect"), this, + SLOT(runDisconnectCommand(int)), 0, 2); + popup->setItemParameter(2, value); + menu()->insertItem(device, popup, 100 + value); + return popup; +} + +void NetView::netStatistics(const QString &device, NetData &data) +{ +#ifdef __linux__ + if (m_procFile == 0) { + data.in = 0; + data.out = 0; + return; + } + + QString output; + QString parser; + // Parse the proc file + while (!m_procStream->atEnd()) { + parser = m_procStream->readLine(); + // remove all the entries apart from the line containing 'device' + if (parser.find(device) != -1) + output = parser; + } + + if (output.isEmpty()) { + data.in = 0; + data.out = 0; + return; + } + + // make sure our output doesn't contain "eth0:11210107" so we dont + // end up with netList[1] actually being netList[2] + output.replace(QRegExp(":"), " "); + QStringList netList = QStringList::split(' ', output); + + data.in = netList[1].toULong(); + data.out = netList[9].toULong(); + + fseek(m_procFile, 0L, SEEK_SET); +#endif + +#ifdef __FreeBSD__ + struct if_msghdr *ifm, *nextifm; + struct sockaddr_dl *sdl; + char *lim, *next; + size_t needed; + char s[32]; + + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + return; + + if (m_allocSize < needed) { + if (m_buf != NULL) + delete[] m_buf; + + m_buf = new char[needed]; + + if (m_buf == NULL) + return; + + m_allocSize = needed; + } + + if (sysctl(mib, 6, m_buf, &needed, NULL, 0) < 0) + return; + + lim = m_buf + needed; + + next = m_buf; + while (next < lim) { + ifm = (struct if_msghdr *)next; + if (ifm->ifm_type != RTM_IFINFO) + return; + + next += ifm->ifm_msglen; + + // get an interface with a network address + while (next < lim) { + nextifm = (struct if_msghdr *)next; + if (nextifm->ifm_type != RTM_NEWADDR) + break; + + next += nextifm->ifm_msglen; + } + + // if the interface is up + if (ifm->ifm_flags & IFF_UP) { + sdl = (struct sockaddr_dl *)(ifm + 1); + if (sdl->sdl_family != AF_LINK) + continue; + + strncpy(s, sdl->sdl_data, sdl->sdl_nlen); + s[sdl->sdl_nlen] = '\0'; + + if (strcmp(device.local8Bit().data(), s) == 0) { + data.in = ifm->ifm_data.ifi_ibytes; + data.out = ifm->ifm_data.ifi_obytes; + return; + } + } + } +#endif +} + +bool NetView::isOnline(const QString &device) +{ +#ifdef __linux__ + QFile file("/proc/net/route"); + if (!file.open(IO_ReadOnly)) + return -1; + + return (QTextStream(&file).read().find(device) != -1 ? true : false); +#endif + +#ifdef __FreeBSD__ + struct if_msghdr *ifm, *nextifm; + struct sockaddr_dl *sdl; + char *lim, *next; + size_t needed; + char s[32]; + + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + return false; + + if (m_allocSize < needed) { + if (m_buf != NULL) + delete[] m_buf; + + m_buf = new char[needed]; + + if (m_buf == NULL) + return false; + + m_allocSize = needed; + } + + if (sysctl(mib, 6, m_buf, &needed, NULL, 0) < 0) + return false; + + lim = m_buf + needed; + + next = m_buf; + while (next < lim) { + ifm = (struct if_msghdr *)next; + if (ifm->ifm_type != RTM_IFINFO) + return false; + + next += ifm->ifm_msglen; + + // get an interface with a network address + while (next < lim) { + nextifm = (struct if_msghdr *)next; + if (nextifm->ifm_type != RTM_NEWADDR) + break; + + next += nextifm->ifm_msglen; + } + + // if the interface is up + if (ifm->ifm_flags & IFF_UP) { + sdl = (struct sockaddr_dl *)(ifm + 1); + if (sdl->sdl_family != AF_LINK) + continue; + + strncpy(s, sdl->sdl_data, sdl->sdl_nlen); + s[sdl->sdl_nlen] = '\0'; + + if (strcmp(s, device.local8Bit().data()) == 0) + return true; + } + } + + return false; +#endif +} + +// EventFilter +bool NetView::eventFilter( QObject * o, QEvent * e ) +{ + // find out which interface we are + int i = 0; + Network::List::Iterator it; + for ( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + if ( o == ( *it ).chart() || o == ( *it ).label() || o == ( *it ).led() ) + { + break; + } + + ++i; + } + + if ( e->type() == QEvent::MouseButtonPress ) + { + if ( static_cast( e )->button() == QMouseEvent::RightButton ) + { + showMenu(i); + } + + return true; + } + + return false; +} + +void NetView::showMenu(int i) { + + QPopupMenu menu; + menu.insertItem( SmallIcon("network"), i18n("Connect"), 1); + menu.insertItem( SmallIcon("network"), i18n("Disconnect"), 2); + switch (menu.exec(QCursor::pos())) { + case 1: + runConnectCommand(i); + break; + case 2: + runDisconnectCommand(i); + break; + } +} + + +#include "ksimnet.moc" diff --git a/ksim/monitors/net/ksimnet.h b/ksim/monitors/net/ksimnet.h new file mode 100644 index 0000000..bdb76e6 --- /dev/null +++ b/ksim/monitors/net/ksimnet.h @@ -0,0 +1,90 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KSIMNET_H +#define KSIMNET_H + +#include +#include "netdevices.h" +#include + +class QTimer; +class QVBoxLayout; +class QTextStream; + +class NetPlugin : public KSim::PluginObject +{ + public: + NetPlugin(const char *name); + ~NetPlugin(); + + virtual KSim::PluginView *createView(const char *); + virtual KSim::PluginPage *createConfigPage(const char *); + + virtual void showAbout(); +}; + +class NetView : public KSim::PluginView +{ + Q_OBJECT + public: + NetView(KSim::PluginObject *parent, const char *name); + ~NetView(); + + virtual void reparseConfig(); + + private slots: + void cleanup(); + void updateLights(); + void updateGraph(); + void addDisplay(); + void runConnectCommand(int); + void runDisconnectCommand(int); + + protected: + bool eventFilter(QObject *, QEvent *); + + private: + Network::List createList() const; + + KSim::Chart *addChart(); + KSim::LedLabel *addLedLabel(const QString &device); + KSim::Label *addLabel(); + QPopupMenu *addPopupMenu(const QString &device, int value); + + void netStatistics(const QString &device, NetData &data); + bool isOnline(const QString &device); + + void showMenu(int i); + + bool m_firstTime; + Network::List m_networkList; + QTimer *m_netTimer; + QTimer *m_lightTimer; + QVBoxLayout *m_netLayout; +#ifdef __linux__ + FILE *m_procFile; + QTextStream *m_procStream; +#endif +#ifdef __FreeBSD__ + char *m_buf; + int m_allocSize; +#endif +}; +#endif diff --git a/ksim/monitors/net/netconfig.cpp b/ksim/monitors/net/netconfig.cpp new file mode 100644 index 0000000..ca424b3 --- /dev/null +++ b/ksim/monitors/net/netconfig.cpp @@ -0,0 +1,296 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netconfig.h" +#include "netconfig.moc" +#include "netdialog.h" + +NetConfig::NetConfig(KSim::PluginObject *parent, const char *name) + : KSim::PluginPage(parent, name) +{ + m_yes = i18n("yes"); + m_no = i18n("no"); + + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->setSpacing(6); + + usingBox = new KListView(this); + usingBox ->addColumn(i18n("Interface")); + usingBox ->addColumn(i18n("Timer")); + usingBox ->addColumn(i18n("Commands")); + usingBox->setAllColumnsShowFocus(true); + + connect(usingBox, SIGNAL(contextMenu(KListView *, + QListViewItem *, const QPoint &)), + SLOT(menu(KListView *, QListViewItem *, const QPoint &))); + connect(usingBox, SIGNAL(doubleClicked(QListViewItem *)), + SLOT(modifyItem(QListViewItem *))); + mainLayout->addWidget(usingBox); + + layout = new QHBoxLayout; + layout->setSpacing(6); + + QSpacerItem *spacer = new QSpacerItem(20, 20, + QSizePolicy::Expanding, QSizePolicy::Minimum); + layout->addItem(spacer); + + insertButton = new QPushButton(this); + insertButton->setText(i18n("Add...")); + connect(insertButton, SIGNAL(clicked()), SLOT(showNetDialog())); + layout->addWidget(insertButton); + + modifyButton = new QPushButton(this); + modifyButton->setText(i18n("Modify...")); + connect(modifyButton, SIGNAL(clicked()), SLOT(modifyCurrent())); + layout->addWidget(modifyButton); + + removeButton = new QPushButton(this); + removeButton->setText(i18n("Remove")); + connect(removeButton, SIGNAL(clicked()), SLOT(removeCurrent())); + layout->addWidget(removeButton); + + mainLayout->addLayout(layout); +} + +NetConfig::~NetConfig() +{ +} + +void NetConfig::saveConfig() +{ + qHeapSort( m_networkList); + + int i = 0; + Network::List::Iterator it; + for( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + config()->setGroup( "device-" + QString::number( i ) ); + config()->writeEntry( "deviceName", ( *it ).name() ); + config()->writeEntry( "showTimer", ( *it ).showTimer() ); + config()->writeEntry( "deviceFormat", ( *it ).format() ); + config()->writeEntry( "commands", ( *it ).commandsEnabled() ); + config()->writeEntry( "cCommand", ( *it ).connectCommand() ); + config()->writeEntry( "dCommand", ( *it ).disconnectCommand() ); + i++; + } + + config()->setGroup( "Net" ); + config()->writeEntry( "deviceAmount", m_networkList.count() ); +} + +void NetConfig::readConfig() +{ + usingBox->clear(); + m_networkList.clear(); + + config()->setGroup( "Net" ); + int deviceAmount = config()->readNumEntry( "deviceAmount" ); + + for ( int i = 0; i < deviceAmount; ++i ) + { + if ( !config()->hasGroup( "device-" + QString::number( i ) ) ) + { + continue; + } + + config()->setGroup("device-" + QString::number(i)); + + m_networkList.append( Network( config()->readEntry( "deviceName" ), + config()->readEntry( "deviceFormat" ), + config()->readBoolEntry( "showTimer" ), + config()->readBoolEntry( "commands" ), + config()->readEntry( "cCommand" ), + config()->readEntry( "dCommand" ) ) ); + + (void) new QListViewItem( usingBox, + config()->readEntry( "deviceName" ), + boolToString( config()->readBoolEntry( "showTimer" ) ), + boolToString( config()->readBoolEntry( "commands" ) ) ); + } +} + +void NetConfig::menu(KListView *, QListViewItem *item, const QPoint &) +{ + aboutMenu = new QPopupMenu(this); + + if (item) { + aboutMenu->insertItem(i18n("&Add Net Device"), 3); + aboutMenu->insertItem(i18n("&Modify '%1'").arg(item->text(0)), 2); + aboutMenu->insertItem(i18n("&Remove '%1'").arg(item->text(0)), 1); + } + else { + aboutMenu->insertItem(i18n("&Add Net Device"), 3); + aboutMenu->insertItem(i18n("&Modify..."), 2); + aboutMenu->insertItem(i18n("&Remove..."), 1); + aboutMenu->setItemEnabled(1, false); + aboutMenu->setItemEnabled(2, false); + } + + switch (aboutMenu->exec(QCursor::pos())) { + case 1: + removeItem(item); + break; + case 2: + modifyItem(item); + break; + case 3: + showNetDialog(); + break; + } + + delete aboutMenu; +} + +void NetConfig::modifyItem(QListViewItem *item) +{ + if (!item) + return; + + netDialog = new NetDialog(this); + Network::List::Iterator it, netDevice; + for ( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + if ( ( *it ).name() == item->text( 0 ) ) + { + netDevice = it; + netDialog->setDeviceName( ( *it ).name() ); + netDialog->setShowTimer( ( *it ).showTimer() ); + netDialog->setFormat( ( *it ).format() ); + netDialog->setShowCommands( ( *it ).commandsEnabled() ); + netDialog->setCCommand( ( *it ).connectCommand() ); + netDialog->setDCommand( ( *it ).disconnectCommand() ); + break; + } + } + + netDialog->exec(); + if ( netDialog->okClicked() ) + { + m_networkList.remove( netDevice ); + m_networkList.append( Network( netDialog->deviceName(), + netDialog->format(), + netDialog->timer(), + netDialog->commands(), + netDialog->cCommand(), + netDialog->dCommand() ) ); + + item->setText( 0, netDialog->deviceName() ); + item->setText( 1, boolToString( netDialog->timer() ) ); + item->setText( 2, boolToString( netDialog->commands() ) ); + } + + delete netDialog; +} + +void NetConfig::removeItem(QListViewItem *item) +{ + if (!item) + return; + + int result = KMessageBox::warningContinueCancel(0, i18n("Are you sure you " + "want to remove the net interface '%1'?").arg(item->text(0)), QString::null, KStdGuiItem::del()); + + if (result == KMessageBox::Cancel) + return; + + int i = 0; + Network::List::Iterator it; + for ( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + if ( item->text( 0 ) == ( *it ).name() ) + { + m_networkList.remove( it ); + if ( config()->deleteGroup( "device-" + QString::number( i ) ) ) + kdDebug(2003) << "device-" << i << " was deleted" << endl; + + break; + } + i++; + } + + delete item; +} + +void NetConfig::removeCurrent() +{ + removeItem(usingBox->currentItem()); +} + +void NetConfig::modifyCurrent() +{ + modifyItem(usingBox->currentItem()); +} + +void NetConfig::showNetDialog() +{ + netDialog = new NetDialog(this, "netDialog"); + netDialog->exec(); + if (netDialog->okClicked()) + getStats(); + + delete netDialog; +} + +void NetConfig::getStats() +{ + Network::List::ConstIterator it; + for ( it = m_networkList.begin(); it != m_networkList.end(); ++it ) + { + if ( ( *it ).name() == netDialog->deviceName() ) + { + KMessageBox::sorry(0, i18n("You already have a network " + "interface by this name. Please select a different interface")); + + return; + } + } + + m_networkList.append( Network( netDialog->deviceName(), + netDialog->format(), + netDialog->timer(), + netDialog->commands(), + netDialog->cCommand(), + netDialog->dCommand() ) ); + + (void) new QListViewItem( usingBox, + netDialog->deviceName(), + boolToString( netDialog->timer() ), + boolToString( netDialog->commands() ) ); +} + +const QString &NetConfig::boolToString(bool value) const +{ + if (value) + return m_yes; + + return m_no; +} diff --git a/ksim/monitors/net/netconfig.h b/ksim/monitors/net/netconfig.h new file mode 100644 index 0000000..9ec5c8d --- /dev/null +++ b/ksim/monitors/net/netconfig.h @@ -0,0 +1,67 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef NETCONFIG_H +#define NETCONFIG_H + +#include +#include "netdevices.h" + +class NetDialog; +class QPopupMenu; +class QPushButton; +class KListView; +class QHBoxLayout; +class QListViewItem; + +class NetConfig : public KSim::PluginPage +{ + Q_OBJECT + public: + NetConfig(KSim::PluginObject *parent, const char *name); + virtual ~NetConfig(); + + virtual void saveConfig(); + virtual void readConfig(); + + private slots: + void menu(KListView *, QListViewItem *, const QPoint &); + void modifyItem(QListViewItem *); + void removeItem(QListViewItem *); + void removeCurrent(); + void modifyCurrent(); + void showNetDialog(); + void getStats(); + + private: + // Couldnt think of a better name for this :) + const QString &boolToString(bool) const; + + QHBoxLayout *layout; + QPushButton *insertButton; + QPushButton *removeButton; + QPushButton *modifyButton; + KListView *usingBox; + NetDialog *netDialog; + Network::List m_networkList; + QString m_yes; + QString m_no; + QPopupMenu *aboutMenu; +}; +#endif diff --git a/ksim/monitors/net/netdevices.h b/ksim/monitors/net/netdevices.h new file mode 100644 index 0000000..2a5a680 --- /dev/null +++ b/ksim/monitors/net/netdevices.h @@ -0,0 +1,218 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef NETDEVICES_H +#define NETDEVICES_H + +#include +#include + +class NetData +{ + public: + NetData() : in(0), out(0) {} + NetData &operator=( const NetData & rhs ) + { + in = rhs.in; + out = rhs.out; + + return *this; + } + + unsigned long in; + unsigned long out; +}; + +class Network +{ + public: + typedef QValueList List; + + Network() + { + m_chart = 0; + m_led = 0; + m_label = 0; + m_popup = 0; + + m_max = 0; + } + + Network( const QString & name, + const QString & format, + bool timer, + bool commands, + const QString & cCommand, + const QString & dCommand ) + : m_name( name ), + m_format( format ), + m_timer( timer ), + m_commands( commands ), + m_cCommand( cCommand ), + m_dCommand( dCommand ) + { + m_chart = 0; + m_led = 0; + m_label = 0; + m_popup = 0; + + m_max = 0; + } + + bool operator==( const Network & rhs ) const + { + return m_name == rhs.m_name && + m_format == rhs.m_format && + m_timer == rhs.m_timer && + m_commands == rhs.m_commands && + m_cCommand == rhs.m_cCommand && + m_dCommand == rhs.m_dCommand; + } + + bool operator!=( const Network & rhs ) const + { + return !operator==(rhs); + } + + bool operator<( const Network & rhs ) const + { + return m_name < rhs.m_name; + } + + bool operator>( const Network & rhs ) const + { + return m_name > rhs.m_name; + } + + bool operator<=( const Network & rhs ) const + { + return !( *this > rhs ); + } + + void cleanup() + { + delete m_chart; + delete m_label; + delete m_led; + delete m_popup; + + m_chart = 0; + m_label = 0; + m_led = 0; + m_popup = 0; + } + + void setData( const NetData & data ) + { + m_old = m_data; + m_data = data; + } + + const NetData & data() const + { + return m_data; + } + + const NetData & oldData() const + { + return m_old; + } + + void setMaxValue( int max ) + { + m_max = max; + } + + int maxValue() const + { + return m_max; + } + + const QString & name() const + { + return m_name; + } + + bool showTimer() const + { + return m_timer; + } + + const QString & format() const + { + return m_format; + } + + bool commandsEnabled() const + { + return m_commands; + } + + const QString & connectCommand() const + { + return m_cCommand; + } + + const QString & disconnectCommand() const + { + return m_dCommand; + } + + void setDisplay( KSim::Chart * chart, KSim::LedLabel * led, + KSim::Label * label, QPopupMenu * popup ) + { + m_chart = chart; + m_led = led; + m_label = label; + m_popup = popup; + } + + KSim::Chart * chart() + { + return m_chart; + } + + KSim::LedLabel * led() + { + return m_led; + } + + KSim::Label * label() + { + return m_label; + } + + private: + NetData m_data; + NetData m_old; + QString m_name; + QString m_format; + bool m_timer; + bool m_commands; + QString m_cCommand; + QString m_dCommand; + + KSim::Chart * m_chart; + KSim::LedLabel * m_led; + KSim::Label * m_label; + QPopupMenu * m_popup; + + int m_max; +}; +#endif diff --git a/ksim/monitors/net/netdialog.cpp b/ksim/monitors/net/netdialog.cpp new file mode 100644 index 0000000..fe655d4 --- /dev/null +++ b/ksim/monitors/net/netdialog.cpp @@ -0,0 +1,328 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "netdialog.h" +#include "netdialog.moc" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __FreeBSD__ +#include +#include +#include +#include +#include +#include +#endif + +#include + +NetDialog::NetDialog(QWidget *parent, const char *name) + : QTabDialog(parent, name, true) +{ + m_clicked = false; + setCaption(kapp->makeStdCaption(i18n("Network Interface"))); + + m_generalTab = new QWidget(this); + m_generalLayout = new QGridLayout(m_generalTab); + m_generalLayout->setSpacing(6); + m_generalLayout->setMargin(11); + + m_deviceLabel = new QLabel(m_generalTab); + m_deviceLabel->setText(i18n("Interface:")); + m_generalLayout->addMultiCellWidget(m_deviceLabel, 0, 0, 0, 0); + + m_deviceCombo = new KComboBox(true, m_generalTab); + m_deviceCombo->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, + QSizePolicy::Fixed)); + m_deviceCombo->setFocus(); + m_deviceCombo->setDuplicatesEnabled(false); + m_generalLayout->addMultiCellWidget(m_deviceCombo, 0, 0, 1, 1); + + QStringList output(createList()); + if (output.isEmpty()) { + m_deviceCombo->insertItem("ppp0"); + m_deviceCombo->insertItem("eth0"); + } + else + m_deviceCombo->insertStringList(output); + + QSpacerItem *deviceSpacer = new QSpacerItem(20, 20, + QSizePolicy::Expanding, QSizePolicy::Fixed); + m_generalLayout->addMultiCell(deviceSpacer, 0, 0, 2, 2); + + m_timerBox = new QGroupBox(m_generalTab); + m_timerBox->setTitle(i18n("Timer")); + m_timerBox->setColumnLayout(0, Qt::Vertical); + m_timerBox->layout()->setSpacing(0); + m_timerBox->layout()->setMargin(0); + m_timerBoxLayout = new QVBoxLayout(m_timerBox->layout()); + m_timerBoxLayout->setAlignment(Qt::AlignTop); + m_timerBoxLayout->setSpacing(6); + m_timerBoxLayout->setMargin(11); + + m_timerEdit = new KLineEdit(m_timerBox); + m_timerEdit->setText("hh:mm:ss"); + m_timerEdit->setEnabled(false); + + m_showTimer = new QCheckBox(m_timerBox); + m_showTimer->setText(i18n("Show timer")); + connect(m_showTimer, SIGNAL(toggled(bool)), + m_timerEdit, SLOT(setEnabled(bool))); + m_timerBoxLayout->addWidget(m_showTimer); + m_timerBoxLayout->addWidget(m_timerEdit); + + m_hFormat = new QLabel(m_timerBox); + m_hFormat->setText(i18n("hh - Total hours online")); + m_timerBoxLayout->addWidget(m_hFormat); + + m_mFormat = new QLabel(m_timerBox); + m_mFormat->setText(i18n("mm - Total minutes online")); + m_timerBoxLayout->addWidget(m_mFormat); + + m_sFormat = new QLabel(m_timerBox); + m_sFormat->setText(i18n("ss - Total seconds online")); + m_timerBoxLayout->addWidget(m_sFormat); + m_generalLayout->addMultiCellWidget(m_timerBox, 1, 1, 0, 2); + + QSpacerItem *spacer = new QSpacerItem(20, 20, + QSizePolicy::Minimum, QSizePolicy::Expanding); + m_generalLayout->addMultiCell(spacer, 2, 2, 0, 0); + addTab(m_generalTab, i18n("General")); + + m_commandTab = new QWidget(this); + m_commandLayout = new QGridLayout(m_commandTab); + m_commandLayout->setSpacing(6); + m_commandLayout->setMargin(11); + + m_enableCommands = new QCheckBox(m_commandTab); + m_enableCommands->setText(i18n("Enable connect/disconnect")); + m_commandLayout->addMultiCellWidget(m_enableCommands, 0, 0, 0, 2); + + m_cCommand = new QLabel(m_commandTab); + m_cCommand->setText(i18n("Connect command:")); + m_commandLayout->addMultiCellWidget(m_cCommand, 1, 1, 0, 0); + + m_connectRequester = new KURLRequester(m_commandTab); + m_connectRequester->setMinimumSize(145, 0); + m_connectRequester->setEnabled(false); + connect(m_enableCommands, SIGNAL(toggled(bool)), + m_connectRequester, SLOT(setEnabled(bool))); + m_commandLayout->addMultiCellWidget(m_connectRequester, 1, 1, 1, 2); + + m_dCommand = new QLabel(m_commandTab); + m_dCommand->setText(i18n("Disconnect command:")); + m_commandLayout->addMultiCellWidget(m_dCommand, 2, 2, 0, 0); + + m_disconnectRequester = new KURLRequester(m_commandTab); + m_disconnectRequester->setMinimumSize(145, 0); + m_disconnectRequester->setEnabled(false); + connect(m_enableCommands, SIGNAL(toggled(bool)), + m_disconnectRequester, SLOT(setEnabled(bool))); + m_commandLayout->addMultiCellWidget(m_disconnectRequester, 2, 2, 1, 2); + + QSpacerItem *commandSpacer = new QSpacerItem(20, 20, + QSizePolicy::Minimum, QSizePolicy::Expanding); + m_commandLayout->addItem(commandSpacer); + addTab(m_commandTab, i18n("Commands")); + + setOkButton(KStdGuiItem::ok().text()); + setCancelButton(KStdGuiItem::cancel().text()); + connect(this, SIGNAL(applyButtonPressed()), SLOT(sendClicked())); +} + +NetDialog::~NetDialog() +{ +} + +const QString NetDialog::deviceName() const +{ + return m_deviceCombo->currentText(); +} + +bool NetDialog::timer() +{ + return m_showTimer->isChecked(); +} + +const QString NetDialog::format() const +{ + return m_timerEdit->text(); +} + +bool NetDialog::commands() +{ + return m_enableCommands->isChecked(); +} + +const QString NetDialog::cCommand() const +{ + return m_connectRequester->url(); +} + +const QString NetDialog::dCommand() const +{ + return m_disconnectRequester->url(); +} + +void NetDialog::setDeviceName(const QString &text) +{ + m_deviceCombo->setCurrentItem(text, true); +} + +void NetDialog::setShowTimer(bool value) +{ + m_showTimer->setChecked(value); +} + +void NetDialog::setFormat(const QString &format) +{ + m_timerEdit->setText(format); +} + +void NetDialog::setShowCommands(bool value) +{ + m_enableCommands->setChecked(value); +} + +void NetDialog::setCCommand(const QString &text) +{ + m_connectRequester->setURL(text); +} + +void NetDialog::setDCommand(const QString &text) +{ + m_disconnectRequester->setURL(text); +} + +void NetDialog::sendClicked() +{ + m_clicked = true; + kdDebug(2003) << "ok was clicked" << endl; +} + +QStringList NetDialog::createList() const +{ +#ifdef __linux__ + QFile file("/proc/net/dev"); + if (!file.open(IO_ReadOnly)) + return QStringList(); + + QStringList output; + QTextStream textStream(&file); + while (!textStream.atEnd()) + output.append(textStream.readLine()); + + if (output.isEmpty()) + return QStringList(); + + output.pop_front(); + output.pop_front(); + + QStringList::Iterator it; + QStringList list; + for (it = output.begin(); it != output.end(); ++it) { + list = QStringList::split(' ', (*it)); + (*it) = list[0].stripWhiteSpace(); + (*it).truncate((*it).find(':')); + } + + return output; +#endif + +#ifdef __FreeBSD__ + QStringList output; + int mib[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; + char *buf = 0; + int alloc = 0; + struct if_msghdr *ifm, *nextifm; + struct sockaddr_dl *sdl; + char *lim, *next; + size_t needed; + char s[32]; + + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + return QStringList(); + + if (alloc < needed) { + buf = new char[needed]; + + if (buf == NULL) + return QStringList(); + + alloc = needed; + } + + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + return QStringList(); + + lim = buf + needed; + + next = buf; + while (next < lim) { + ifm = (struct if_msghdr *)next; + if (ifm->ifm_type != RTM_IFINFO) + return QStringList(); + + next += ifm->ifm_msglen; + + // get an interface with a network address + while (next < lim) { + nextifm = (struct if_msghdr *)next; + if (nextifm->ifm_type != RTM_NEWADDR) + break; + + next += nextifm->ifm_msglen; + } + + // if the interface is up + if (ifm->ifm_flags & IFF_UP) { + sdl = (struct sockaddr_dl *)(ifm + 1); + if (sdl->sdl_family != AF_LINK) + continue; + + strncpy(s, sdl->sdl_data, sdl->sdl_nlen); + s[sdl->sdl_nlen] = '\0'; + + output.append(s); + } + } + + if (buf) + delete[] buf; + + return output; +#endif +} diff --git a/ksim/monitors/net/netdialog.h b/ksim/monitors/net/netdialog.h new file mode 100644 index 0000000..b6d7801 --- /dev/null +++ b/ksim/monitors/net/netdialog.h @@ -0,0 +1,85 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef NETDIALOG_H +#define NETDIALOG_H + +#include + +class QVBoxLayout; +class QGridLayout; +class QCheckBox; +class QGroupBox; +class QLabel; +class QWidget; +class KComboBox; +class KLineEdit; +class KURLRequester; + +class NetDialog : public QTabDialog +{ + Q_OBJECT + public: + NetDialog(QWidget *parent, const char *name = 0); + ~NetDialog(); + + const QString deviceName() const; + bool timer(); + const QString format() const; + bool commands(); + const QString cCommand() const; + const QString dCommand() const; + bool okClicked() { return m_clicked; } + + public slots: + void setDeviceName(const QString &); + void setShowTimer(bool); + void setFormat(const QString &); + void setShowCommands(bool); + void setCCommand(const QString &); + void setDCommand(const QString &); + + private slots: + void sendClicked(); + + private: + QStringList createList() const; + + bool m_clicked; + QWidget *m_generalTab; + QLabel *m_deviceLabel; + KComboBox *m_deviceCombo; + QGroupBox *m_timerBox; + QCheckBox *m_showTimer; + KLineEdit *m_timerEdit; + QLabel *m_hFormat; + QLabel *m_mFormat; + QLabel *m_sFormat; + QWidget *m_commandTab; + QCheckBox *m_enableCommands; + QLabel *m_cCommand; + KURLRequester *m_connectRequester; + QLabel *m_dCommand; + KURLRequester *m_disconnectRequester; + + QGridLayout *m_generalLayout; + QVBoxLayout *m_timerBoxLayout; + QGridLayout *m_commandLayout; +}; +#endif // NETDIALOG_H diff --git a/ksim/monitors/snmp/Makefile.am b/ksim/monitors/snmp/Makefile.am new file mode 100644 index 0000000..0c922c9 --- /dev/null +++ b/ksim/monitors/snmp/Makefile.am @@ -0,0 +1,16 @@ +kde_module_LTLIBRARIES = ksim_snmp.la +ksim_snmp_la_SOURCES = plugin.cpp view.cpp configpage.cpp configwidget.ui snmp.cpp hostdialogbase.ui hostdialog.cpp value.cpp monitor.cpp \ + monitordialogbase.ui monitordialog.cpp labelmonitor.cpp chartmonitor.cpp \ + identifier.cpp monitorconfig.cpp hostconfig.cpp session.cpp probedialog.cpp snmplib.cpp \ + pdu.cpp proberesultdialogbase.ui proberesultdialog.cpp browsedialogbase.ui browsedialog.cpp \ + walker.cpp + +ksim_snmp_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +ksim_snmp_la_LIBADD = ../../library/libksimcore.la $(LIB_KIO) $(LIBSNMP) + +INCLUDES= -I$(top_srcdir)/ksim/library $(all_includes) + +METASOURCES = AUTO + +mon_DATA = Snmp.desktop +mondir = $(kde_datadir)/ksim/monitors diff --git a/ksim/monitors/snmp/Snmp.desktop b/ksim/monitors/snmp/Snmp.desktop new file mode 100644 index 0000000..b6ceb4c --- /dev/null +++ b/ksim/monitors/snmp/Snmp.desktop @@ -0,0 +1,70 @@ +[Desktop Entry] +Comment=Snmp Status Monitor +Comment[ar]=مراقب حالة Snmp +Comment[bg]=Мониторинг на Snmp +Comment[bs]=Nadzor SNMP statusa +Comment[ca]=Monitor d'estat snmp +Comment[cs]=Monitor stavu SNMP +Comment[cy]=Monitr Cyflwr Snmp +Comment[da]=Snmp statusovervågning +Comment[de]=Statusanzeige für SNMP +Comment[el]=Επόπτης κατάστασης snmp +Comment[eo]=Monitoro por la Snmp-stato +Comment[es]=Monitor de estado de Snmp +Comment[et]=Snmp oleku monitooring +Comment[eu]=Snmp Egoera Begiralea +Comment[fa]=نمایشگر وضعیت Snmp +Comment[fi]=SNPP-tilavalvoja +Comment[fr]=Indicateur d'état snmp +Comment[ga]=Monatóir Stádais SNMP +Comment[hi]=एसएनएमपी स्थिति मॉनीटर +Comment[hu]=Snmp állapotmonitor +Comment[is]=Snmp eftirlitstól +Comment[it]=Controllo di stato SNMP +Comment[ja]=Snmp ステータスモニタ +Comment[ka]=Snmp სტატუსის მონიტორი +Comment[kk]=SNMP күйін бақылау +Comment[km]=កម្មវិធី​ត្រួតពិនិត្យ​ស្ថានភាព Snmp +Comment[lt]=Snmp būsenos stebėtojas +Comment[mk]=Монитор за статусот на Snmp +Comment[nb]=Overvåkning av status via SNMP +Comment[nds]=SNMP-Statuskieker +Comment[ne]=Snmp स्थिति मोनिटर +Comment[nl]=Snmp Statusbewaking +Comment[nn]=Overvaking av status via SNMP +Comment[pa]=Snmp ਹਾਲਤ ਨਿਗਰਾਨ +Comment[pl]=Monitor statusu Snmp +Comment[pt]=Monitor de Estado do SNMP +Comment[pt_BR]=Monitor de estado do SNMP +Comment[ro]=Monitor stare SNMP +Comment[ru]=Монитор состояния SNMP +Comment[sk]=Monitor stavu SNMP +Comment[sl]=Nadzornik stanja Snmp +Comment[sr]=Надгледање статуса Snmp-а +Comment[sr@Latn]=Nadgledanje statusa Snmp-a +Comment[sv]=Övervakar SNMP-status +Comment[ta]=Snmp நிலை கண்காணி +Comment[tg]=Дидабони Ҳолати Snmp +Comment[tr]=Snmp Durum Monitörü +Comment[uk]=Монітор стану мережі (snmp протокол) +Comment[wa]=Corwaitoe di l' estat snmp +Comment[zh_CN]=Snmp 状态监视器 +Comment[zh_TW]=Snmp 狀態監視器 +Icon=network +Name=Snmp +Name[cs]=SNMP +Name[de]=SNMP +Name[ga]=SNMP +Name[hi]=एसएनएमपी +Name[it]=SNMP +Name[kk]=SNMP +Name[nds]=SNMP +Name[ro]=SNMP +Name[sk]=SNMP +Name[sv]=SNMP +X-KSIM-VERSION=0.1 +X-KSIM-LIBRARY=snmp +X-KSIM-COPYRIGHT=(C) 2003 Simon Hausmann +X-KSIM-EMAIL=hausmann@kde.org +X-KSIM-PREFS=Snmp +X-KSIM-AUTHOR=Simon Hausmann diff --git a/ksim/monitors/snmp/browsedialog.cpp b/ksim/monitors/snmp/browsedialog.cpp new file mode 100644 index 0000000..d196ec8 --- /dev/null +++ b/ksim/monitors/snmp/browsedialog.cpp @@ -0,0 +1,147 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "browsedialog.h" + +#include + +#include +#include +#include +#include +#include + +using namespace KSim::Snmp; + +BrowseDialog::BrowseDialog( const HostConfig &hostConfig, const QString ¤tOid, QWidget *parent, const char *name ) + : BrowseDialogBase( parent, name ), m_host( hostConfig ) +{ + stop->setGuiItem( KGuiItem( i18n( "&Stop" ), "stop" ) ); + + browserContents->setSorting( -1 ); + + selectedObject->setText( currentOid ); + + m_walker = 0; + + baseOids << "1.3.6.1.2" << "1.3.6.1.4"; + nextWalk(); +} + +QString BrowseDialog::selectedObjectIdentifier() const +{ + return selectedObject->text(); +} + +void BrowseDialog::stopAllWalks() +{ + baseOids.clear(); + stopWalker(); +} + +void BrowseDialog::insertBrowseItem( const Walker::Result &result ) +{ + if ( !result.success || + result.data.type() == Value::EndOfMIBView || + result.data.type() == Value::NoSuchInstance || + result.data.type() == Value::NoSuchObject ) { + + nextWalk(); + return; + } + + QListViewItem *i = new QListViewItem( browserContents, browserContents->lastItem(), result.identifierString, result.dataString ); + applyFilter( i ); +} + +void BrowseDialog::applyFilter() +{ + for ( QListViewItem *i = browserContents->firstChild(); + i; i = i->nextSibling() ) + applyFilter( i ); +} + +void BrowseDialog::nextWalk() +{ + stopWalker(); + + if ( baseOids.isEmpty() ) + return; + + QString baseOidString = baseOids.pop(); + Identifier id = Identifier::fromString( baseOidString ); + if ( id.isNull() ) + return; + startWalk( id ); +} + +void BrowseDialog::startWalk( const Identifier &startOid ) +{ + stopWalker(); + + m_walker = new Walker( m_host, startOid, this ); + connect( m_walker, SIGNAL( resultReady( const Walker::Result & ) ), + this, SLOT( insertBrowseItem( const Walker::Result & ) ) ); + connect( m_walker, SIGNAL( finished() ), + this, SLOT( nextWalk() ) ); + + stop->setEnabled( true ); +} + +void BrowseDialog::stopWalker() +{ + if ( !m_walker ) + return; + + disconnect( m_walker, SIGNAL( resultReady( const Walker::Result & ) ), + this, SLOT( insertBrowseItem( const Walker::Result & ) ) ); + disconnect( m_walker, SIGNAL( finished() ), + this, SLOT( nextWalk() ) ); + + m_walker->deleteLater(); + m_walker = 0; + + stop->setEnabled( false ); +} + +void BrowseDialog::objectSelected( QListViewItem *item ) +{ + selectedObject->setText( item->text( 0 ) ); +} + +void BrowseDialog::applyFilter( QListViewItem *item ) +{ + QString filterText = filter->text(); + + if ( filterText.isEmpty() ) { + item->setVisible( true ); + return; + } + + if ( item->text( 0 ).find( filterText, 0 /*index*/, false /*case sensitive*/ ) == -1 ) { + item->setVisible( false ); + return; + } + + item->setVisible( true ); +} + +#include "browsedialog.moc" +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/browsedialog.h b/ksim/monitors/snmp/browsedialog.h new file mode 100644 index 0000000..cb6466a --- /dev/null +++ b/ksim/monitors/snmp/browsedialog.h @@ -0,0 +1,71 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef BROWSEDIALOG_H +#define BROWSEDIALOG_H + +#include "browsedialogbase.h" + +#include "hostconfig.h" +#include "identifier.h" +#include "value.h" +#include "snmp.h" +#include "walker.h" + +#include + +namespace KSim +{ + +namespace Snmp +{ + +class BrowseDialog : public BrowseDialogBase +{ + Q_OBJECT +public: + BrowseDialog( const HostConfig &hostConfig, const QString ¤tOid, QWidget *parent, const char *name = 0 ); + + QString selectedObjectIdentifier() const; + +protected: + virtual void stopAllWalks(); + virtual void applyFilter(); + virtual void objectSelected( QListViewItem *item ); + +private slots: + void insertBrowseItem( const Walker::Result &browseResult ); + void nextWalk(); + +private: + void applyFilter( QListViewItem *item ); + void startWalk( const Identifier &startOid ); + void stopWalker(); + + HostConfig m_host; + Walker *m_walker; + QValueStack baseOids; +}; + +} +} + +#endif // BROWSEDIALOG_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/browsedialogbase.ui b/ksim/monitors/snmp/browsedialogbase.ui new file mode 100644 index 0000000..17459f8 --- /dev/null +++ b/ksim/monitors/snmp/browsedialogbase.ui @@ -0,0 +1,262 @@ + +KSim::Snmp::BrowseDialogBase + + + MyDialog + + + + 0 + 0 + 650 + 532 + + + + Browse + + + true + + + + unnamed + + + + layout2 + + + + unnamed + + + + textLabel1 + + + Filter: + + + + + filter + + + + + line1 + + + VLine + + + Sunken + + + Vertical + + + + + stop + + + Stop + + + + + + + + Object + + + true + + + true + + + + + Value + + + true + + + true + + + + browserContents + + + true + + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + true + + + true + + + + + buttonCancel + + + &Cancel + + + true + + + + + + + layout4 + + + + unnamed + + + + blah + + + + 1 + 5 + 0 + 0 + + + + Selected object: + + + + + selectedObject + + + + 5 + 5 + 0 + 0 + + + + textLabel1 + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 71 + 20 + + + + + + + + + + buttonOk + clicked() + MyDialog + accept() + + + buttonCancel + clicked() + MyDialog + reject() + + + stop + clicked() + MyDialog + stopAllWalks() + + + filter + textChanged(const QString&) + MyDialog + applyFilter() + + + browserContents + executed(QListViewItem*) + MyDialog + objectSelected(QListViewItem*) + + + + stopAllWalks() + applyFilter() + objectSelected(QListViewItem *) + + + + kdialog.h + kpushbutton.h + klistview.h + + diff --git a/ksim/monitors/snmp/chartmonitor.cpp b/ksim/monitors/snmp/chartmonitor.cpp new file mode 100644 index 0000000..1a32086 --- /dev/null +++ b/ksim/monitors/snmp/chartmonitor.cpp @@ -0,0 +1,83 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include "chartmonitor.h" + +#include + +using namespace KSim::Snmp; + +ChartMonitor::ChartMonitor( const MonitorConfig &config, QWidget *parent, const char *name ) + : KSim::Chart( true /* displayMeter */, 0, QString::null, parent, name ), + m_lastValue( 0 ), m_config( config ), m_firstSampleReceived( false ) +{ + setTitle( m_config.name ); + disableAutomaticUpdates(); +} + +void ChartMonitor::setData( const Value &data ) +{ + Q_UINT64 currentValue = convertToInt( data ); + + if ( data.isCounterType() ) { + int diff = currentValue - m_lastValue; + + if ( !m_firstSampleReceived ) { + diff = 0; + m_firstSampleReceived = true; + } + + m_lastValue = currentValue; + currentValue = diff; + } + + // move the graph and add the new sample then + updateDisplay(); + setValue( currentValue ); + if ( m_config.displayCurrentValueInline ) { + Q_UINT64 bytesPerSec = currentValue / ( m_config.refreshInterval.seconds + m_config.refreshInterval.minutes * 60 ); + setText( KIO::convertSize( bytesPerSec ), 0 ); + } +} + +Q_UINT64 ChartMonitor::convertToInt( const Value &data ) +{ + switch ( data.type() ) { + case Value::TimeTicks: + case Value::Int: return data.toInt(); + case Value::Gauge: + case Value::Counter: + case Value::UInt: return data.toUInt(); + case Value::Counter64: return data.toCounter64(); + case Value::Double: // ### not sure what to do here... + case Value::ByteArray: + case Value::Oid: // ### could treat this as a sort of hyperlink... hmm + case Value::IpAddress: + case Value::NoSuchObject: + case Value::NoSuchInstance: + case Value::EndOfMIBView: + case Value::Invalid: + case Value::Null: return 0; + } + return 0; +} + +#include "chartmonitor.moc" + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/chartmonitor.h b/ksim/monitors/snmp/chartmonitor.h new file mode 100644 index 0000000..30a58ad --- /dev/null +++ b/ksim/monitors/snmp/chartmonitor.h @@ -0,0 +1,54 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef CHARTMONITOR_H +#define CHARTMONITOR_H + +#include "chart.h" +#include "monitor.h" + +namespace KSim +{ + +namespace Snmp +{ + +class ChartMonitor : public KSim::Chart +{ + Q_OBJECT +public: + ChartMonitor( const MonitorConfig &config, QWidget *parent, const char *name = 0 ); + +public slots: + void setData( const Value &data ); + +private: + Q_UINT64 m_lastValue; + MonitorConfig m_config; + bool m_firstSampleReceived; + + static Q_UINT64 convertToInt( const Value &data ); +}; + +} + +} + +#endif // CHARTMONITOR_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/configpage.cpp b/ksim/monitors/snmp/configpage.cpp new file mode 100644 index 0000000..d15d606 --- /dev/null +++ b/ksim/monitors/snmp/configpage.cpp @@ -0,0 +1,313 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "configpage.h" +#include "plugin.h" + +#include "configwidget.h" +#include "hostdialog.h" +#include "monitordialog.h" + +#include +#include +#include + +#include +#include +#include +#include + +using namespace KSim::Snmp; + +static bool listViewHasSelection( QListView *lv ) +{ + for ( QListViewItem *i = lv->firstChild(); i; i = i->itemBelow() ) + if ( i->isSelected() ) + return true; + return false; +} + +ConfigPage::ConfigPage( Plugin *parent, const char *name ) + : KSim::PluginPage( parent, name ) +{ + ( new QVBoxLayout( this ) )->setAutoAdd( true ); + + m_page = new ConfigWidget( this ); + + connect( m_page->addHost, SIGNAL( clicked() ), + this, SLOT( addNewHost() ) ); + connect( m_page->modifyHost, SIGNAL( clicked() ), + this, SLOT( modifyHost() ) ); + connect( m_page->removeHost, SIGNAL( clicked() ), + this, SLOT( removeHost() ) ); + + connect( m_page->addMonitor, SIGNAL( clicked() ), + this, SLOT( addNewMonitor() ) ); + connect( m_page->modifyMonitor, SIGNAL( clicked() ), + this, SLOT( modifyMonitor() ) ); + connect( m_page->removeMonitor, SIGNAL( clicked() ), + this, SLOT( removeMonitor() ) ); + + connect( m_page->hosts, SIGNAL( selectionChanged() ), + this, SLOT( disableOrEnableSomeWidgets() ) ); + connect( m_page->monitors, SIGNAL( selectionChanged() ), + this, SLOT( disableOrEnableSomeWidgets() ) ); +} + +ConfigPage::~ConfigPage() +{ +} + +void ConfigPage::saveConfig() +{ + KConfig &cfg = *config(); + + // collect garbage + removeAllHostGroups(); + removeAllMonitorGroups(); + + QStringList hosts = m_hosts.save( cfg ); + QStringList monitors = m_monitors.save( cfg ); + + cfg.setGroup( "General" ); + cfg.writeEntry( "Hosts", hosts ); + cfg.writeEntry( "Monitors", monitors ); +} + +void ConfigPage::readConfig() +{ + KConfig &cfg = *config(); + + cfg.setGroup( "General" ); + QStringList hosts = cfg.readListEntry( "Hosts" ); + QStringList monitors = cfg.readListEntry( "Monitors" ); + + m_hosts.load( cfg, hosts ); + m_monitors.load( cfg, monitors, m_hosts ); + + fillGui(); +} + +void ConfigPage::addNewHost() +{ + HostDialog dlg( this ); + if ( dlg.exec() ) { + HostConfig src = dlg.settings(); + m_hosts.insert( src.name, src ); + + ( void )new HostItem( m_page->hosts, src ); + } + + disableOrEnableSomeWidgets(); +} + +void ConfigPage::modifyHost() +{ + HostItem *currentItem = dynamic_cast( m_page->hosts->currentItem() ); + if ( !currentItem ) + return; + + HostConfigMap::Iterator hostIt = m_hosts.find( currentItem->text( 0 ) ); + if ( hostIt == m_hosts.end() ) + return; + + HostDialog dlg( *hostIt, this ); + if ( dlg.exec() ) { + HostConfig newHost = dlg.settings(); + + if ( newHost.name != hostIt.key() ) { + m_hosts.remove( hostIt ); + hostIt = m_hosts.insert( newHost.name, newHost ); + } else + *hostIt = newHost; + + currentItem->setFromHostConfig( newHost ); + } +} + +void ConfigPage::removeHost() +{ + HostItem *currentItem = dynamic_cast( m_page->hosts->currentItem() ); + if ( !currentItem ) + return; + + HostConfigMap::Iterator hostIt = m_hosts.find( currentItem->text( 0 ) ); + if ( hostIt == m_hosts.end() ) + return; + + QStringList monitors = monitorsForHost( *hostIt ); + if ( !monitors.isEmpty() ) { + int answer = KMessageBox::warningContinueCancelList( + this, + i18n( "This host has the following monitor associated. Do you really want to delete this host entry?", + "This host has the following %n monitors associated. Do you really want to delete this host entry?", + monitors.count() ), + monitors, + i18n( "Delete Host Entry" ), + i18n( "Delete" ) ); + + if ( answer != KMessageBox::Continue ) + return; + + removeMonitors( monitors ); + } + + m_hosts.remove( hostIt ); + delete currentItem; + + disableOrEnableSomeWidgets(); +} + +void ConfigPage::addNewMonitor() +{ + MonitorDialog dlg( m_hosts, this ); + if ( dlg.exec() ) { + MonitorConfig monitor = dlg.monitorConfig(); + m_monitors.insert( monitor.name, monitor ); + + ( void )new MonitorItem( m_page->monitors, monitor ); + } +} + +void ConfigPage::modifyMonitor() +{ + MonitorItem *currentItem = dynamic_cast( m_page->monitors->currentItem() ); + if ( !currentItem ) + return; + + MonitorConfigMap::Iterator monitorIt = m_monitors.find( currentItem->text( 0 ) ); + if ( monitorIt == m_monitors.end() ) + return; + + MonitorDialog dlg( *monitorIt, m_hosts, this ); + if ( dlg.exec() ) { + MonitorConfig newMonitor = dlg.monitorConfig(); + + if ( newMonitor.name != monitorIt.key() ) { + m_monitors.remove( monitorIt ); + monitorIt = m_monitors.insert( newMonitor.name, newMonitor ); + } else + *monitorIt = newMonitor; + + currentItem->setFromMonitor( newMonitor ); + } +} + +void ConfigPage::removeMonitor() +{ + MonitorItem *currentItem = dynamic_cast( m_page->monitors->currentItem() ); + if ( !currentItem ) + return; + + MonitorConfigMap::Iterator monitorIt = m_monitors.find( currentItem->text( 0 ) ); + if ( monitorIt == m_monitors.end() ) + return; + + m_monitors.remove( monitorIt ); + delete currentItem; +} + +void ConfigPage::disableOrEnableSomeWidgets() +{ + bool hostSelected = listViewHasSelection( m_page->hosts ); + bool monitorSelected = listViewHasSelection( m_page->monitors ); + + m_page->modifyHost->setEnabled( hostSelected ); + m_page->removeHost->setEnabled( hostSelected ); + + m_page->modifyMonitor->setEnabled( monitorSelected ); + m_page->removeMonitor->setEnabled( monitorSelected ); + + m_page->monitorGroup->setEnabled( !m_hosts.isEmpty() ); +} + +void ConfigPage::removeMonitors( QStringList monitors ) +{ + for ( QStringList::ConstIterator it = monitors.begin(); + it != monitors.end(); ++it ) + m_monitors.remove( *it ); + + QListViewItem *item = m_page->monitors->firstChild(); + while ( item ) { + QListViewItem *nextItem = item->itemBelow(); + + for ( QStringList::Iterator it = monitors.begin(); + it != monitors.end(); ++it ) + if ( item->text( 0 ) == *it ) { + + monitors.remove( it ); + + delete item; + + break; + } + + item = nextItem; + } +} + +void ConfigPage::removeAllHostGroups() +{ + removeConfigGroups( "Host " ); +} + +void ConfigPage::removeAllMonitorGroups() +{ + removeConfigGroups( "Monitor " ); +} + +void ConfigPage::removeConfigGroups( const QString &prefix ) +{ + KConfig &cfg = *config(); + + QStringList groups = cfg.groupList(); + for ( QStringList::ConstIterator it = groups.begin(); it != groups.end(); ++it ) + if ( ( *it ).startsWith( prefix ) ) + cfg.deleteGroup( *it, true /* deep */ ); +} + +void ConfigPage::fillGui() +{ + m_page->hosts->clear(); + m_page->monitors->clear(); + + for ( HostConfigMap::ConstIterator it = m_hosts.begin(); it != m_hosts.end(); ++it ) + ( void )new HostItem( m_page->hosts, *it ); + + for ( MonitorConfigMap::ConstIterator it = m_monitors.begin(); it != m_monitors.end(); ++it ) + ( void )new MonitorItem( m_page->monitors, *it ); + + disableOrEnableSomeWidgets(); +} + +QStringList ConfigPage::monitorsForHost( const HostConfig &host ) const +{ + QStringList monitors; + + for ( MonitorConfigMap::ConstIterator it = m_monitors.begin(); + it != m_monitors.end(); ++it ) + if ( ( *it ).host == host ) + monitors << ( *it ).name; + + return monitors; +} + +#include "configpage.moc" +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/configpage.h b/ksim/monitors/snmp/configpage.h new file mode 100644 index 0000000..42c7579 --- /dev/null +++ b/ksim/monitors/snmp/configpage.h @@ -0,0 +1,120 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef CONFIGPAGE_H +#define CONFIGPAGE_H + +#include +#include + +#include "monitorconfig.h" +#include "hostconfig.h" + +namespace KSim +{ + +namespace Snmp +{ + +class HostItem : public QListViewItem +{ +public: + HostItem( QListView *parent, const KSim::Snmp::HostConfig &src ) + : QListViewItem( parent, QString::null, QString::null, QString::null ) + { + setFromHostConfig( src ); + } + + HostItem( QListView *parent ) + : QListViewItem( parent, QString::null, QString::null, QString::null ) + {} + + void setFromHostConfig( const KSim::Snmp::HostConfig &src ) + { + setText( 0, src.name ); + setText( 1, QString::number( src.port ) ); + setText( 2, snmpVersionToString( src.version ) ); + } +}; + +class MonitorItem : public QListViewItem +{ +public: + MonitorItem( QListView *parent, const KSim::Snmp::MonitorConfig &monitor ) + : QListViewItem( parent, QString::null, QString::null, QString::null ) + { + setFromMonitor( monitor ); + } + + MonitorItem( QListView *parent ) + : QListViewItem( parent, QString::null, QString::null, QString::null ) + {} + + void setFromMonitor( const KSim::Snmp::MonitorConfig &monitor ) + { + setText( 0, monitor.name ); + setText( 1, monitorDisplayTypeToString( monitor.display ) ); + } +}; + +class ConfigWidget; +class Plugin; + +class ConfigPage : public KSim::PluginPage +{ + Q_OBJECT +public: + ConfigPage( Plugin *parent, const char *name ); + ~ConfigPage(); + + virtual void saveConfig(); + virtual void readConfig(); + +private slots: + void addNewHost(); + void modifyHost(); + void removeHost(); + void addNewMonitor(); + void modifyMonitor(); + void removeMonitor(); + + void disableOrEnableSomeWidgets(); + +private: + void removeMonitors( QStringList monitors ); + + void removeAllHostGroups(); + void removeAllMonitorGroups(); + void removeConfigGroups( const QString &prefix ); + void fillGui(); + + QStringList monitorsForHost( const HostConfig &host ) const; + + ConfigWidget *m_page; + KSim::Snmp::HostConfigMap m_hosts; + KSim::Snmp::MonitorConfigMap m_monitors; +}; + +} + +} + +#endif // CONFIGPAGE_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/configure.in.in b/ksim/monitors/snmp/configure.in.in new file mode 100644 index 0000000..2d266d7 --- /dev/null +++ b/ksim/monitors/snmp/configure.in.in @@ -0,0 +1,40 @@ +AC_ARG_WITH(snmp, + [AC_HELP_STRING(--with-snmp, + [enable support for SNMP @<:@default=check@:>@])], + [], with_snmp=check) + +enable_snmp=no +if test "x$with_snmp" != xno; then + KDE_CHECK_HEADER( net-snmp/library/snmp_api.h, + [ have_netsnmp_h=yes ], [ have_netsnmp_h=no ], + [ #include + #include + ] + ) + + if test "$have_netsnmp_h" = yes; then + KDE_CHECK_LIB( netsnmp, snmp_sess_init, [ + AC_SUBST( LIBSNMP, "-lnetsnmp" ) + enable_snmp=yes + ], [], [] ) + fi + + if test "$enable_snmp" != yes; then + AC_MSG_CHECKING([if libnetsnmp needs -lcrypto]) + + dnl use a different symbol to prevent autoconf from caching + KDE_CHECK_LIB( netsnmp, snmp_open, [ + AC_SUBST( LIBSNMP, "-lnetsnmp -lcrypto" ) + enable_snmp=yes + AC_MSG_RESULT(yes) + ], [ + AC_MSG_RESULT(no) + ], [-lcrypto] ) + fi + + if test "x$with_snmp" != xcheck && test "x$enable_snmp" != xyes; then + AC_MSG_ERROR([--with-snmp was given, but test for net-snmp failed]) + fi +fi + +AM_CONDITIONAL(include_ksim_monitors_snmp, test "x$enable_snmp" = xyes) diff --git a/ksim/monitors/snmp/configwidget.ui b/ksim/monitors/snmp/configwidget.ui new file mode 100644 index 0000000..c121184 --- /dev/null +++ b/ksim/monitors/snmp/configwidget.ui @@ -0,0 +1,215 @@ + +KSim::Snmp::ConfigWidget + + + ConfigWidget + + + + 0 + 0 + 740 + 597 + + + + + unnamed + + + + hostGroup + + + SNMP Hosts + + + + unnamed + + + + removeHost + + + Remove + + + + + modifyHost + + + Modify... + + + + + addHost + + + Add... + + + + + + Host + + + true + + + true + + + + + Port + + + true + + + true + + + + + Version + + + true + + + true + + + + hosts + + + true + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 141 + 20 + + + + + + + + monitorGroup + + + SNMP Monitors + + + + unnamed + + + + addMonitor + + + Add... + + + + + modifyMonitor + + + Modify... + + + + + removeMonitor + + + Remove + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 121 + 20 + + + + + + + Name + + + true + + + true + + + + + Type + + + true + + + true + + + + monitors + + + true + + + + + + + + hosts + addHost + modifyHost + removeHost + monitors + addMonitor + modifyMonitor + removeMonitor + + + + klistview.h + klistview.h + + diff --git a/ksim/monitors/snmp/hostconfig.cpp b/ksim/monitors/snmp/hostconfig.cpp new file mode 100644 index 0000000..1b96541 --- /dev/null +++ b/ksim/monitors/snmp/hostconfig.cpp @@ -0,0 +1,152 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "hostconfig.h" + +#include + +#include + +using namespace KSim::Snmp; + +static int defaultSnmpPort() +{ + servent *ent = getservbyname( "snmp", 0 ); + if ( !ent ) + return 161; + return ent->s_port; +} + +bool HostConfig::load( KConfigBase &config ) +{ + name = config.readEntry( "Host" ); + if ( name.isEmpty() ) + return false; + + port = config.readNumEntry( "Port", defaultSnmpPort() ); + + bool ok = false; + version = stringToSnmpVersion( config.readEntry( "Version" ), &ok ); + if ( !ok ) + return false; + + if ( version != SnmpVersion3 ) { + community = config.readEntry( "Community" ); + return true; + } + + securityName = config.readEntry( "SecurityName" ); + + securityLevel = stringToSecurityLevel( config.readEntry( "SecurityLevel" ), &ok ); + if ( !ok ) + return false; + + if ( securityLevel == NoAuthPriv ) + return true; + + authentication.protocol = stringToAuthenticationProtocol( config.readEntry( "AuthType" ), &ok ); + if ( !ok ) + return false; + authentication.key = KStringHandler::obscure( config.readEntry( "AuthPassphrase" ) ); + + if ( securityLevel == AuthNoPriv ) + return true; + + privacy.protocol = stringToPrivacyProtocol( config.readEntry( "PrivType" ), &ok ); + if ( !ok ) + return false; + privacy.key = KStringHandler::obscure( config.readEntry( "PrivPassphrase" ) ); + + return true; +} + +void HostConfig::save( KConfigBase &config ) const +{ + if ( isNull() ) + return; + + config.writeEntry( "Host", name ); + if ( port != 0 ) + config.writeEntry( "Port", port ); + + config.writeEntry( "Version", snmpVersionToString( version ) ); + + if ( version != SnmpVersion3 ) { + writeIfNotEmpty( config, "Community", community ); + return; + } + + writeIfNotEmpty( config, "SecurityName", securityName ); + + config.writeEntry( "SecurityLevel", securityLevelToString( securityLevel ) ); + + if ( securityLevel == NoAuthPriv ) + return; + + writeIfNotEmpty( config, "AuthType", authenticationProtocolToString( authentication.protocol ) ); + writeIfNotEmpty( config, "AuthPassphrase", KStringHandler::obscure( authentication.key ) ); + + if ( securityLevel == AuthNoPriv ) + return; + + writeIfNotEmpty( config, "PrivType", privacyProtocolToString( privacy.protocol ) ); + writeIfNotEmpty( config, "PrivPassphrase", KStringHandler::obscure( privacy.key ) ); +} + +void HostConfig::writeIfNotEmpty( KConfigBase &config, const QString &name, const QString &value ) +{ + if ( value.isEmpty() ) + return; + + config.writeEntry( name, value ); +} + +void HostConfigMap::load( KConfigBase &config, const QStringList &hosts ) +{ + clear(); + + for ( QStringList::ConstIterator it = hosts.begin(); it != hosts.end(); ++it ) { + config.setGroup( "Host " + *it ); + + HostConfig src; + if ( !src.load( config ) ) + continue; + + insert( *it, src ); + } +} + +QStringList HostConfigMap::save( KConfigBase &config ) const +{ + QStringList hostList; + + for ( ConstIterator it = begin(); it != end(); ++it ) { + QString host = it.key(); + + hostList << host; + + config.setGroup( "Host " + host ); + ( *it ).save( config ); + } + + return hostList; +} + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/hostconfig.h b/ksim/monitors/snmp/hostconfig.h new file mode 100644 index 0000000..d19de9b --- /dev/null +++ b/ksim/monitors/snmp/hostconfig.h @@ -0,0 +1,86 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef HOSTCONFIG_H +#define HOSTCONFIG_H + +#include "snmp.h" + +namespace KSim +{ + +namespace Snmp +{ + +struct HostConfig +{ + HostConfig() {} + HostConfig( KConfigBase &config ) + { load( config ); } + + QString name; // hostname + ushort port; + + SnmpVersion version; + + QString community; + + QString securityName; + + SecurityLevel securityLevel; + + struct + { + AuthenticationProtocol protocol; + QString key; + } authentication; + struct + { + PrivacyProtocol protocol; + QString key; + } privacy; + + bool load( KConfigBase &config ); + void save( KConfigBase &config ) const; + + bool isNull() const { return name.isEmpty(); } + + bool operator==( const HostConfig &rhs ) const + { return name == rhs.name; } + +private: + static void writeIfNotEmpty( KConfigBase &config, const QString &name, const QString &value ); +}; + +struct HostConfigMap : public QMap< QString, HostConfig > +{ + HostConfigMap() {} + HostConfigMap( const QMap< QString, HostConfig > &rhs ) + : QMap< QString, HostConfig >( rhs ) {} + + void load( KConfigBase &config, const QStringList &hosts ); + QStringList save( KConfigBase &config ) const; +}; + +} +} + +#endif // HOSTCONFIG_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/hostdialog.cpp b/ksim/monitors/snmp/hostdialog.cpp new file mode 100644 index 0000000..a1ccdc3 --- /dev/null +++ b/ksim/monitors/snmp/hostdialog.cpp @@ -0,0 +1,193 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "hostdialog.h" +#include "probedialog.h" +#include "proberesultdialog.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace KSim::Snmp; + +HostDialog::HostDialog( QWidget *parent, const char *name ) + : HostDialogBase( parent, name ) +{ + init(); + port->setValue( 161 ); +} + +HostDialog::HostDialog( const HostConfig &src, QWidget *parent, const char *name ) + : HostDialogBase( parent, name ) +{ + init( src ); +} + +HostConfig HostDialog::settings() const +{ + HostConfig result; + + result.name = hostName->text(); + result.port = port->value(); + + result.version = stringToSnmpVersion( snmpVersion->currentText() ); + if ( result.version != SnmpVersion3 ) { + result.community = communityString->text(); + } + + result.securityName = securityName->text(); + + result.securityLevel = stringToSecurityLevel( securityLevel->currentText() ); + + if ( result.securityLevel == NoAuthPriv ) + return result; + + result.authentication.protocol = stringToAuthenticationProtocol( authenticationType->currentText() ); + result.authentication.key = authenticationPassphrase->text(); + + if ( result.securityLevel == AuthNoPriv ) + return result; + + result.privacy.protocol = stringToPrivacyProtocol( privacyType->currentText() ); + result.privacy.key = privacyPassphrase->text(); + + return result; +} + +void HostDialog::showSnmpAuthenticationDetailsForVersion( const QString &versionStr ) +{ + bool ok = false; + SnmpVersion version = stringToSnmpVersion( versionStr, &ok ); + assert( ok ); + + authenticationDetails->raiseWidget( version == SnmpVersion3 ? snmpV3Page : snmpV1Page ); +} + +void HostDialog::enableDisabledAuthenticationAndPrivacyElementsForSecurityLevel( const QString &levelStr ) +{ + bool ok = false; + SecurityLevel level = stringToSecurityLevel( levelStr, &ok ); + assert( ok ); + + bool enableAuthentication = level != NoAuthPriv; + bool enablePrivacy = level == AuthPriv; + + authenticationTypeLabel->setEnabled( enableAuthentication ); + authenticationType->setEnabled( enableAuthentication ); + authenticationPassphraseLabel->setEnabled( enableAuthentication ); + authenticationPassphrase->setEnabled( enableAuthentication ); + + privacyTypeLabel->setEnabled( enablePrivacy ); + privacyType->setEnabled( enablePrivacy ); + privacyPassphraseLabel->setEnabled( enablePrivacy ); + privacyPassphrase->setEnabled( enablePrivacy ); +} + +void HostDialog::checkValidity() +{ + bool enableOk = true; + bool ok = false; + SnmpVersion version = stringToSnmpVersion( snmpVersion->currentText(), &ok ); + assert( ok ); + + enableOk &= !hostName->text().isEmpty(); + + if ( version == SnmpVersion3 ) + enableOk &= !securityName->text().isEmpty(); + else + enableOk &= !communityString->text().isEmpty(); + + buttonOk->setEnabled( enableOk ); + testHostButton->setEnabled( enableOk ); +} + +void HostDialog::testHost() +{ + ProbeDialog dlg( settings(), this ); + if ( dlg.exec() ) { + ProbeDialog::ProbeResultList results = dlg.probeResults(); + + ProbeResultDialog resultDlg( settings(), results, this ); + resultDlg.exec(); + } +} + +void HostDialog::init( const HostConfig &src ) +{ + // hide these, there's nothing to choose right now. might be that + // net-snmp will support different privacy types in the future, but + // apparently not now. + privacyTypeLabel->hide(); + privacyType->hide(); + + snmpVersion->insertStringList( allSnmpVersions() ); + securityLevel->insertStringList( allSecurityLevels() ); + authenticationType->insertStringList( allAuthenticationProtocols() ); + privacyType->insertStringList( allPrivacyProtocols() ); + + if ( !src.isNull() ) + loadSettingsFromHostConfig( src ); + + showSnmpAuthenticationDetailsForVersion( snmpVersion->currentText() ); + enableDisabledAuthenticationAndPrivacyElementsForSecurityLevel( securityLevel->currentText() ); + checkValidity(); +} + +void HostDialog::loadSettingsFromHostConfig( const HostConfig &src ) +{ + hostName->setText( src.name ); + port->setValue( src.port ); + + snmpVersion->setCurrentItem( allSnmpVersions().findIndex( snmpVersionToString( src.version ) ) ); + + if ( src.version != SnmpVersion3 ) { + communityString->setText( src.community ); + return; + } + + securityName->setText( src.securityName ); + + securityLevel->setCurrentItem( allSecurityLevels().findIndex( securityLevelToString( src.securityLevel ) ) ); + + if ( src.securityLevel == NoAuthPriv ) + return; + + authenticationType->setCurrentItem( allAuthenticationProtocols().findIndex( authenticationProtocolToString( src.authentication.protocol ) ) ); + authenticationPassphrase->setText( src.authentication.key ); + + if ( src.securityLevel == AuthNoPriv ) + return; + + privacyType->setCurrentItem( allPrivacyProtocols().findIndex( privacyProtocolToString( src.privacy.protocol ) ) ); + privacyPassphrase->setText( src.privacy.key ); +} + +#include "hostdialog.moc" + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/hostdialog.h b/ksim/monitors/snmp/hostdialog.h new file mode 100644 index 0000000..e296b7b --- /dev/null +++ b/ksim/monitors/snmp/hostdialog.h @@ -0,0 +1,59 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef HOSTDIALOG_H +#define HOSTDIALOG_H + +#include "hostdialogbase.h" +#include "hostconfig.h" +#include "probedialog.h" + +namespace KSim +{ + +namespace Snmp +{ + +class HostDialog : public HostDialogBase +{ + Q_OBJECT +public: + HostDialog( QWidget *parent, const char *name = 0 ); + HostDialog( const HostConfig &src, QWidget *parent, const char *name = 0 ); + + HostConfig settings() const; + +private slots: + void showSnmpAuthenticationDetailsForVersion( const QString &versionStr ); + void enableDisabledAuthenticationAndPrivacyElementsForSecurityLevel( const QString &levelStr ); + void checkValidity(); + void testHost(); + +private: + void init( const HostConfig &src = HostConfig() ); + void loadSettingsFromHostConfig( const HostConfig &src ); +}; + +} + +} + +#endif // HOSTDIALOG_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/hostdialogbase.ui b/ksim/monitors/snmp/hostdialogbase.ui new file mode 100644 index 0000000..1ee9ee4 --- /dev/null +++ b/ksim/monitors/snmp/hostdialogbase.ui @@ -0,0 +1,526 @@ + +KSim::Snmp::HostDialogBase +Much thanks to Frerich for hints/advice on the GUI design +Simon Hausmann + + + HostDialogBase + + + + 0 + 0 + 559 + 454 + + + + Configure Host + + + true + + + + unnamed + + + + textLabel2 + + + NoFrame + + + Plain + + + &Hostname: + + + hostName + + + + + hostName + + + + + textLabel3 + + + &Port: + + + port + + + + + port + + + 65535 + + + 1 + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 91 + 20 + + + + + + buttonGroup2 + + + Authentication Details + + + + unnamed + + + + authenticationDetails + + + + snmpV1Page + + + 0 + + + + unnamed + + + + textLabel5 + + + &Community String: + + + communityString + + + + + spacer4 + + + Vertical + + + Expanding + + + + 20 + 41 + + + + + + spacer3 + + + Horizontal + + + Expanding + + + + 160 + 20 + + + + + + communityString + + + Password + + + + + + + snmpV3Page + + + 1 + + + + unnamed + + + + textLabel6 + + + S&ecurity name: + + + securityName + + + + + textLabel7 + + + Security &level: + + + securityLevel + + + + + authenticationTypeLabel + + + &Authentication type: + + + authenticationType + + + + + privacyTypeLabel + + + P&rivacy type: + + + privacyType + + + + + privacyPassphraseLabel + + + Priva&cy passphrase: + + + privacyPassphrase + + + + + authenticationPassphraseLabel + + + Authentication &passphrase: + + + authenticationPassphrase + + + + + spacer5 + + + Horizontal + + + Expanding + + + + 71 + 20 + + + + + + securityName + + + + + privacyType + + + true + + + + + privacyPassphrase + + + Password + + + + + securityLevel + + + + + authenticationType + + + + + authenticationPassphrase + + + Password + + + + + spacer7 + + + Vertical + + + Expanding + + + + 20 + 20 + + + + + + + + + line3 + + + HLine + + + Sunken + + + Horizontal + + + + + textLabel2_2 + + + &SNMP version: + + + snmpVersion + + + + + snmpVersion + + + + + spacer8 + + + Horizontal + + + Expanding + + + + 351 + 20 + + + + + + + + line2 + + + HLine + + + Sunken + + + Horizontal + + + + + layout2 + + + + unnamed + + + + testHostButton + + + Test Host... + + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 220 + 20 + + + + + + buttonOk + + + &OK + + + true + + + true + + + + + buttonCancel + + + &Cancel + + + true + + + + + + + + + buttonOk + clicked() + HostDialogBase + accept() + + + buttonCancel + clicked() + HostDialogBase + reject() + + + snmpVersion + activated(const QString&) + HostDialogBase + showSnmpAuthenticationDetailsForVersion(const QString&) + + + securityLevel + activated(const QString&) + HostDialogBase + enableDisabledAuthenticationAndPrivacyElementsForSecurityLevel(const QString&) + + + hostName + textChanged(const QString&) + HostDialogBase + checkValidity() + + + securityName + textChanged(const QString&) + HostDialogBase + checkValidity() + + + communityString + textChanged(const QString&) + HostDialogBase + checkValidity() + + + testHostButton + clicked() + HostDialogBase + testHost() + + + + hostName + port + snmpVersion + securityName + securityLevel + authenticationType + authenticationPassphrase + privacyType + privacyPassphrase + buttonOk + buttonCancel + communityString + + + showSnmpAuthenticationDetailsForVersion(const QString &) + enableDisabledAuthenticationAndPrivacyElementsForSecurityLevel(const QString &) + checkValidity() + testHost() + + + + kdialog.h + klineedit.h + klineedit.h + klineedit.h + klineedit.h + klineedit.h + + diff --git a/ksim/monitors/snmp/identifier.cpp b/ksim/monitors/snmp/identifier.cpp new file mode 100644 index 0000000..25c188e --- /dev/null +++ b/ksim/monitors/snmp/identifier.cpp @@ -0,0 +1,129 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "identifier.h" +#include "snmp_p.h" +#include "snmplib.h" + +#include + +using namespace KSim::Snmp; + +Identifier::Data::Data( const oid *d, size_t length ) +{ + memcpy( data, d, length * sizeof( oid ) ); + this->length = length; +} + +Identifier::Identifier() + : d( new Data ) +{ +} + +Identifier::Identifier( Data *data ) + : d( data ) +{ + assert( d ); +} + +Identifier::Identifier( const Identifier &rhs ) + : d( new Data( *rhs.d ) ) +{ +} + +Identifier &Identifier::operator=( const Identifier &rhs ) +{ + if ( d == rhs.d ) + return *this; + + *d = *rhs.d; + + return *this; +} + +Identifier::~Identifier() +{ + delete d; +} + +Identifier Identifier::fromString( const QString &name, bool *ok ) +{ + Identifier res; + res.d->length = MAX_OID_LEN; + // if ( !get_node( name.ascii(), res.d->data, &res.d->length ) ) { + if ( name.isEmpty() || !SnmpLib::self()->snmp_parse_oid( name.ascii(), res.d->data, &res.d->length ) ) { + if ( ok ) + *ok = false; + return Identifier(); + } + + if ( ok ) + *ok = true; + + return res; +} + +QString Identifier::toString( PrintFlags flags ) const +{ + size_t buflen = 256; + size_t outlen = 0; + int overflow = 0; + + u_char *buf = ( u_char* )calloc( buflen, 1 ); + if ( !buf ) + return QString::null; + + int oldOutpuFormat = SnmpLib::self()->netsnmp_ds_get_int( NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT ); + SnmpLib::self()->netsnmp_ds_set_int( NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, + flags == PrintAscii ? NETSNMP_OID_OUTPUT_MODULE : NETSNMP_OID_OUTPUT_NUMERIC ); + + SnmpLib::self()->netsnmp_sprint_realloc_objid_tree( &buf, &buflen, &outlen, 1 /* alloc realloc */, + &overflow, d->data, d->length ); + + SnmpLib::self()->netsnmp_ds_set_int( NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, oldOutpuFormat ); + + if ( overflow ) { + free( buf ); + return QString::null; + } + + QString result = QString::fromAscii( ( char* )buf ); + + free( buf ); + + return result; +} + +bool Identifier::operator==( const Identifier &rhs ) const +{ + return SnmpLib::self()->netsnmp_oid_equals( d->data, d->length, rhs.d->data, rhs.d->length ) == 0; +} + +bool Identifier::operator<( const Identifier &rhs ) const +{ + return SnmpLib::self()->snmp_oid_compare( d->data, d->length, rhs.d->data, rhs.d->length ) < 0; +} + +bool Identifier::isNull() const +{ + return d->length == 0; +} + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/identifier.h b/ksim/monitors/snmp/identifier.h new file mode 100644 index 0000000..7da54dd --- /dev/null +++ b/ksim/monitors/snmp/identifier.h @@ -0,0 +1,72 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef IDENTIFIER_H +#define IDENTIFIER_H + +#include +#include +#include + +#include "value.h" + +namespace KSim +{ + +namespace Snmp +{ + +class Identifier +{ +public: + friend class PDU; + struct Data; + + enum PrintFlags { PrintAscii, PrintNumeric }; + + Identifier(); + Identifier( Data *data ); + Identifier( const Identifier &rhs ); + Identifier &operator=( const Identifier &rhs ); + ~Identifier(); + + static Identifier fromString( const QString &name, bool *ok = 0 ); + + QString toString( PrintFlags flags = PrintAscii ) const; + + bool isNull() const; + + bool operator==( const Identifier &rhs ) const; + bool operator!=( const Identifier &rhs ) const + { return !operator==( rhs ); } + bool operator<( const Identifier &rhs ) const; + +private: + Data *d; +}; + +typedef QValueList IdentifierList; +typedef QMap ValueMap; + +} +} + +#endif // IDENTIFIER_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/labelmonitor.cpp b/ksim/monitors/snmp/labelmonitor.cpp new file mode 100644 index 0000000..24e48c7 --- /dev/null +++ b/ksim/monitors/snmp/labelmonitor.cpp @@ -0,0 +1,45 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "labelmonitor.h" + +using namespace KSim::Snmp; + +LabelMonitor::LabelMonitor( const MonitorConfig &config, QWidget *parent, const char *name ) + : KSim::Label( parent, name ), m_config( config ) +{ +} + +void LabelMonitor::setData( const Value &data ) +{ + QString dataString = data.toString( m_config.refreshInterval.minutes == 0 ? Value::TimeTicksWithSeconds : 0 ); + + if ( m_config.useCustomFormatString ) { + QString text = m_config.customFormatString; + text.replace( "%n", m_config.name ); + text.replace( "%s", dataString ); + setText( text ); + } else + setText( m_config.name + ": " + dataString ); +} + +#include "labelmonitor.moc" + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/labelmonitor.h b/ksim/monitors/snmp/labelmonitor.h new file mode 100644 index 0000000..3e92c69 --- /dev/null +++ b/ksim/monitors/snmp/labelmonitor.h @@ -0,0 +1,52 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef LABELMONITOR_H +#define LABELMONITOR_H + +#include "label.h" +#include "value.h" +#include "monitorconfig.h" + +namespace KSim +{ + +namespace Snmp +{ + +class LabelMonitor : public KSim::Label +{ + Q_OBJECT +public: + LabelMonitor( const MonitorConfig &config, QWidget *parent, const char *name = 0 ); + +public slots: + void setData( const Value &data ); + +private: + MonitorConfig m_config; +}; + +} + +} + +#endif // LABELMONITOR_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/monitor.cpp b/ksim/monitors/snmp/monitor.cpp new file mode 100644 index 0000000..7a97825 --- /dev/null +++ b/ksim/monitors/snmp/monitor.cpp @@ -0,0 +1,96 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "monitor.h" + +#include +#include + +using namespace KSim::Snmp; + +Monitor::Monitor( const HostConfig &host, const Identifier &oid, int refresh, QObject *parent, const char *name ) + : QObject( parent, name ), m_oid( oid ), m_session( host ) +{ + if ( refresh > 0 ) + m_timerId = startTimer( refresh ); + else + m_timerId = -1; + + QTimer::singleShot( 0, this, SLOT( performSnmpRequest() ) ); +} + +Monitor::~Monitor() +{ + if ( QThread::running() ) + QThread::wait(); +} + +void Monitor::run() +{ + AsyncSnmpQueryResult *result = new AsyncSnmpQueryResult; + + result->oid = m_oid; + result->success = performSyncSnmpRequest( result->data, &result->error ); + + QCustomEvent *ev = new QCustomEvent( QEvent::User, result ); + QApplication::postEvent( this, ev ); +} + +void Monitor::customEvent( QCustomEvent *ev ) +{ + if ( ev->type() != QEvent::User ) + return; + + AsyncSnmpQueryResult *result = reinterpret_cast( ev->data() ); + if ( result->success ) { + emit newData( result->data ); + emit newData( result->oid, result->data ); + } else { + emit error( result->error ); + emit error( result->oid, result->error ); + } + + delete result; +} + +void Monitor::timerEvent( QTimerEvent *ev ) +{ + if ( ev->timerId() != m_timerId ) + return; + + performSnmpRequest(); +} + +void Monitor::performSnmpRequest() +{ + if ( QThread::running() ) + return; + + start(); +} + +bool Monitor::performSyncSnmpRequest( Value &data, ErrorInfo *errorInfo ) +{ + return m_session.snmpGet( m_oid, data, errorInfo ); +} + +#include "monitor.moc" + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/monitor.h b/ksim/monitors/snmp/monitor.h new file mode 100644 index 0000000..cd3dedc --- /dev/null +++ b/ksim/monitors/snmp/monitor.h @@ -0,0 +1,77 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MONITOR_H +#define MONITOR_H + +#include "monitorconfig.h" +#include "session.h" + +#include + +namespace KSim +{ + +namespace Snmp +{ + +class Monitor : public QObject, public QThread +{ + Q_OBJECT +public: + Monitor( const HostConfig &host, const Identifier &oid, int refresh, QObject *parent = 0, const char *name = 0 ); + virtual ~Monitor(); + +signals: + void newData( const Value &data ); + void newData( const Identifier &oid, const Value &data ); + void error( const ErrorInfo &errorInfo ); + void error( const Identifier &oid, const ErrorInfo &errorInfo ); + +protected: + virtual void run(); + virtual void customEvent( QCustomEvent *ev ); + virtual void timerEvent( QTimerEvent *ev ); + +private slots: + void performSnmpRequest(); + bool performSyncSnmpRequest( Value &data, ErrorInfo *errorInfo = 0 ); + +private: + struct AsyncSnmpQueryResult + { + AsyncSnmpQueryResult() : success( false ) {} + Identifier oid; + Value data; + ErrorInfo error; + bool success; + }; + + const Identifier m_oid; + int m_timerId; + Session m_session; +}; + +} + +} + +#endif // MONITOR_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/monitorconfig.cpp b/ksim/monitors/snmp/monitorconfig.cpp new file mode 100644 index 0000000..6b3b27e --- /dev/null +++ b/ksim/monitors/snmp/monitorconfig.cpp @@ -0,0 +1,183 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "monitorconfig.h" +#include "labelmonitor.h" +#include "chartmonitor.h" + +#include + +using namespace KSim::Snmp; + +MonitorConfig::MonitorConfig() +{ + display = Label; + refreshInterval.minutes = refreshInterval.seconds = 0; + useCustomFormatString = false; + displayCurrentValueInline = false; +} + +bool MonitorConfig::load( KConfigBase &config, const HostConfigMap &hosts ) +{ + QString hostName = config.readEntry( "Host" ); + if ( hostName.isEmpty() ) + return false; + + HostConfigMap::ConstIterator hostIt = hosts.find( hostName ); + if ( hostIt == hosts.end() ) + return false; + + host = *hostIt; + + name = config.readEntry( "MonitorName" ); + if ( name.isEmpty() ) + return false; + + oid = config.readEntry( "ObjectIdentifier" ); + if ( Identifier::fromString( oid ).isNull() ) + return false; + + bool ok = false; + display = stringToMonitorDisplayType( config.readEntry( "DisplayType" ), &ok ); + if ( !ok ) + return false; + + refreshInterval.minutes = config.readUnsignedNumEntry( "RefreshIntervalMinutes" ); + refreshInterval.seconds = config.readUnsignedNumEntry( "RefreshIntervalSeconds" ); + + if ( refreshInterval.minutes == 0 && refreshInterval.seconds == 0 ) + return false; + + if ( display == Label ) { + useCustomFormatString = config.readBoolEntry( "UseCustomFormatString", useCustomFormatString ); + if ( useCustomFormatString ) + customFormatString = config.readEntry( "CustomFormatString" ); + } else + displayCurrentValueInline = config.readBoolEntry( "DisplayCurrentValueInline", displayCurrentValueInline ); + + return true; +} + +void MonitorConfig::save( KConfigBase &config ) const +{ + if ( isNull() ) + return; + + config.writeEntry( "Host", host.name ); + config.writeEntry( "MonitorName", name ); + config.writeEntry( "ObjectIdentifier", oid ); + config.writeEntry( "DisplayType", monitorDisplayTypeToString( display ) ); + config.writeEntry( "RefreshIntervalMinutes", refreshInterval.minutes ); + config.writeEntry( "RefreshIntervalSeconds", refreshInterval.seconds ); + if ( display == Label ) { + config.writeEntry( "UseCustomFormatString", useCustomFormatString ); + if ( useCustomFormatString ) + config.writeEntry( "CustomFormatString", customFormatString ); + } else + config.writeEntry( "DisplayCurrentValueInline", displayCurrentValueInline ); +} + +QWidget *MonitorConfig::createMonitorWidget( QWidget *parent, const char *name ) +{ + QWidget *w; + + int refresh = refreshInterval.seconds * 1000 + refreshInterval.minutes * 60 * 1000; + Identifier id = Identifier::fromString( oid ); + if ( id.isNull() ) + return 0; + + if ( display == Label ) + w = new LabelMonitor( *this, parent, name ); + else + w = new ChartMonitor( *this, parent, name ); + + Monitor *monitor = new Monitor( host, id, refresh, w ); + QObject::connect( monitor, SIGNAL( newData( const Value & ) ), + w, SLOT( setData( const Value & ) ) ); + return w; +} + +QString KSim::Snmp::monitorDisplayTypeToString( MonitorConfig::DisplayType type ) +{ + switch ( type ) + { + case MonitorConfig::Label: return QString::fromLatin1( "Label" ); + case MonitorConfig::Chart: return QString::fromLatin1( "Chart" ); + default: assert( false ); + }; + return QString::null; +} + +MonitorConfig::DisplayType KSim::Snmp::stringToMonitorDisplayType( QString string, bool *ok ) +{ + string = string.lower(); + if ( string == "chart" ) { + if ( ok ) + *ok = true; + return MonitorConfig::Chart; + } + if ( string == "label" ) { + if ( ok ) + *ok = true; + return MonitorConfig::Label; + } + if ( ok ) + *ok = false; + return MonitorConfig::Chart; +} + +QStringList KSim::Snmp::allDisplayTypes() +{ + // !!! keep order with enum + return QStringList() << "Label" << "Chart"; +} + +void MonitorConfigMap::load( KConfigBase &config, const QStringList &names, const HostConfigMap &hosts ) +{ + clear(); + + for ( QStringList::ConstIterator it = names.begin(); it != names.end(); ++it ) { + config.setGroup( "Monitor " + *it ); + + MonitorConfig monitor; + if ( !monitor.load( config, hosts ) ) + continue; + + insert( *it, monitor ); + } +} + +QStringList MonitorConfigMap::save( KConfigBase &config ) const +{ + QStringList names; + + for ( ConstIterator it = begin(); it != end(); ++it ) { + QString name = it.key(); + + names << name; + + config.setGroup( "Monitor " + name ); + ( *it ).save( config ); + } + + return names; +} + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/monitorconfig.h b/ksim/monitors/snmp/monitorconfig.h new file mode 100644 index 0000000..bbc8674 --- /dev/null +++ b/ksim/monitors/snmp/monitorconfig.h @@ -0,0 +1,84 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MONITORCONFIG_H +#define MONITORCONFIG_H + +#include "hostconfig.h" + +namespace KSim +{ + +namespace Snmp +{ + +struct MonitorConfig +{ + enum DisplayType { Label = 0, Chart }; + + MonitorConfig(); + MonitorConfig( KConfigBase &config, const HostConfigMap &hosts ) + { load( config, hosts ); } + + bool load( KConfigBase &config, const HostConfigMap &hosts ); + void save( KConfigBase &config ) const; + + bool isNull() const { return name.isEmpty() || host.isNull(); } + + QWidget *createMonitorWidget( QWidget *parent, const char *name = 0 ); + + HostConfig host; + QString name; + QString oid; + struct + { + uint minutes; + uint seconds; + } refreshInterval; + DisplayType display; + + bool useCustomFormatString; + QString customFormatString; + + bool displayCurrentValueInline; +}; + +struct MonitorConfigMap : public QMap< QString, MonitorConfig > +{ + MonitorConfigMap() {} + MonitorConfigMap( const QMap< QString, MonitorConfig > &rhs ) + : QMap< QString, MonitorConfig >( rhs ) {} + + void load( KConfigBase &config, const QStringList &names, const HostConfigMap &hosts ); + QStringList save( KConfigBase &config ) const; +}; + +typedef QValueList MonitorConfigList; + +QString monitorDisplayTypeToString( MonitorConfig::DisplayType type ); +MonitorConfig::DisplayType stringToMonitorDisplayType( QString string, bool *ok = 0 ); +QStringList allDisplayTypes(); + +} + +} + +#endif // MONITORCONFIG_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/monitordialog.cpp b/ksim/monitors/snmp/monitordialog.cpp new file mode 100644 index 0000000..615a1aa --- /dev/null +++ b/ksim/monitors/snmp/monitordialog.cpp @@ -0,0 +1,178 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "monitordialog.h" +#include "identifier.h" +#include "browsedialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace KSim::Snmp; + +MonitorDialog::MonitorDialog( const HostConfigMap &hosts, QWidget *parent, const char *name ) + : MonitorDialogBase( parent, name ), m_hosts( hosts ) +{ + init(); +} + +MonitorDialog::MonitorDialog( const MonitorConfig &monitor, const HostConfigMap &hosts, QWidget *parent, const char *name ) + : MonitorDialogBase( parent, name ), m_hosts( hosts ) +{ + init( monitor ); +} + +MonitorConfig MonitorDialog::monitorConfig() const +{ + MonitorConfig result; + + result.host = currentHost(); + if ( result.host.isNull() ) + return MonitorConfig(); + + result.name = monitorName->text(); + if ( result.name.isEmpty() ) + return MonitorConfig(); + + result.oid = oid->text(); + if ( Identifier::fromString( result.oid ).isNull() ) + return MonitorConfig(); + + result.refreshInterval.minutes = updateIntervalMinutes->value(); + result.refreshInterval.seconds = updateIntervalSeconds->value(); + + result.display = stringToMonitorDisplayType( displayType->currentText() ); + + if ( result.display == MonitorConfig::Label ) { + result.useCustomFormatString = customFormatStringCheckBox->isChecked(); + if ( result.useCustomFormatString ) + result.customFormatString = customFormatString->text(); + } else + result.displayCurrentValueInline = displayCurrentValueInline->isChecked(); + + return result; +} + +void MonitorDialog::checkValues() +{ + bool currentDisplayTypeIsLabel = stringToMonitorDisplayType( displayType->currentText() ) == MonitorConfig::Label; + labelOptions->setEnabled( currentDisplayTypeIsLabel ); + chartOptions->setEnabled( !currentDisplayTypeIsLabel ); + + QString statusText; + + if ( monitorName->text().isEmpty() ) + statusText = i18n( "Please enter a name for this monitor" ); + + if ( statusText.isEmpty() && Identifier::fromString( oid->text() ).isNull() ) + statusText = i18n( "Please enter a valid name for the object identifier" ); + + if ( statusText.isEmpty() ) + statusText = " "; // a space to keep the height + + status->setText( statusText ); + + buttonOk->setEnabled( !monitorConfig().isNull() ); +} + +void MonitorDialog::testObject() +{ + // ### FIXME +} + +void MonitorDialog::browse() +{ + HostConfig host = currentHost(); + if ( host.isNull() ) + return; + + BrowseDialog dlg( host, oid->text(), this ); + if ( dlg.exec() ) + oid->setText( dlg.selectedObjectIdentifier() ); +} + +void MonitorDialog::init( const MonitorConfig &monitor ) +{ + customFormatString->setText( "%s" ); + + status->setText( " " ); + + host->clear(); + + QStringList allHosts; + for ( HostConfigMap::ConstIterator it = m_hosts.begin(); it != m_hosts.end(); ++it ) + allHosts << it.key(); + + host->insertStringList( allHosts ); + + displayType->clear(); + displayType->insertStringList( allDisplayTypes() ); + + if ( monitor.isNull() ) { + checkValues(); + return; + } + + monitorName->setText( monitor.name ); + + assert( allHosts.findIndex( monitor.host.name ) != -1 ); + + host->setCurrentItem( allHosts.findIndex( monitor.host.name ) ); + + oid->setText( monitor.oid ); + + updateIntervalMinutes->setValue( monitor.refreshInterval.minutes ); + updateIntervalSeconds->setValue( monitor.refreshInterval.seconds ); + + displayType->setCurrentItem( allDisplayTypes().findIndex( monitorDisplayTypeToString( monitor.display ) ) ); + + customFormatStringCheckBox->setChecked( monitor.useCustomFormatString ); + customFormatString->setEnabled( monitor.useCustomFormatString ); + + if ( monitor.useCustomFormatString ) + customFormatString->setText( monitor.customFormatString ); + + displayCurrentValueInline->setChecked( monitor.displayCurrentValueInline ); + + checkValues(); +} + +HostConfig MonitorDialog::currentHost() const +{ + HostConfigMap::ConstIterator hostIt = m_hosts.find( host->currentText() ); + if ( hostIt == m_hosts.end() ) + return HostConfig(); + + return *hostIt; +} + +#include "monitordialog.moc" +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/monitordialog.h b/ksim/monitors/snmp/monitordialog.h new file mode 100644 index 0000000..0f22d33 --- /dev/null +++ b/ksim/monitors/snmp/monitordialog.h @@ -0,0 +1,60 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MONITORDIALOG_H +#define MONITORDIALOG_H + +#include "monitordialogbase.h" +#include "monitorconfig.h" + +namespace KSim +{ + +namespace Snmp +{ + +class MonitorDialog : public MonitorDialogBase +{ + Q_OBJECT +public: + MonitorDialog( const HostConfigMap &hosts, QWidget *parent, const char *name = 0 ); + MonitorDialog( const MonitorConfig &monitor, const HostConfigMap &hosts, QWidget *parent, const char *name = 0 ); + + MonitorConfig monitorConfig() const; + +protected: + virtual void checkValues(); + virtual void testObject(); + virtual void browse(); + +private: + void init( const MonitorConfig &monitor = MonitorConfig() ); + + HostConfig currentHost() const; + + HostConfigMap m_hosts; +}; + +} + +} + +#endif // MONITORDIALOG_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/monitordialogbase.ui b/ksim/monitors/snmp/monitordialogbase.ui new file mode 100644 index 0000000..13d6b06 --- /dev/null +++ b/ksim/monitors/snmp/monitordialogbase.ui @@ -0,0 +1,440 @@ + +KSim::Snmp::MonitorDialogBase + + + MonitorDialogBase + + + + 0 + 0 + 725 + 597 + + + + Configure Monitor + + + true + + + + unnamed + + + + textLabel5 + + + Display type: + + + + + textLabel2 + + + Update interval: + + + + + textLabel1 + + + Object identifier: + + + + + textLabel1_2 + + + Name: + + + + + textLabel1_3 + + + Host: + + + + + labelOptions + + + Options for Label + + + + unnamed + + + + customFormatStringCheckBox + + + Use custom format string: + + + + + customFormatString + + + false + + + + + textLabel1_4 + + + + 7 + 7 + 0 + 0 + + + + The text in the edit box is what is displayed except that any occurrence of <b>%s</b> will be replaced with the snmp object value and any occurrence of <b>%n</b> will be replaced with the name of this monitor (see Name input field) . + + + WordBreak|AlignVCenter + + + + + + + layout2 + + + + unnamed + + + + updateIntervalMinutes + + + 60 + + + + + textLabel4 + + + minutes + + + + + updateIntervalSeconds + + + 59 + + + 1 + + + + + textLabel3 + + + seconds + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 141 + 20 + + + + + + + + layout3 + + + + unnamed + + + + + Chart + + + + + Text Label + + + + displayType + + + + + spacer3 + + + Horizontal + + + Expanding + + + + 271 + 20 + + + + + + + + spacer4 + + + Horizontal + + + Expanding + + + + 244 + 20 + + + + + + monitorName + + + + + spacer5 + + + Horizontal + + + Expanding + + + + 210 + 20 + + + + + + host + + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + true + + + true + + + + + buttonCancel + + + &Cancel + + + true + + + + + + + line1 + + + HLine + + + Sunken + + + Horizontal + + + + + status + + + blehStatus + + + + + chartOptions + + + Options for Chart + + + + unnamed + + + + displayCurrentValueInline + + + Treat data as byte transfer rate and display the current value inline + + + + + + + browseButton + + + Browse... + + + + + oid + + + + + + + buttonOk + clicked() + MonitorDialogBase + accept() + + + buttonCancel + clicked() + MonitorDialogBase + reject() + + + monitorName + textChanged(const QString&) + MonitorDialogBase + checkValues() + + + oid + textChanged(const QString&) + MonitorDialogBase + checkValues() + + + displayType + activated(const QString&) + MonitorDialogBase + checkValues() + + + customFormatStringCheckBox + toggled(bool) + customFormatString + setEnabled(bool) + + + browseButton + clicked() + MonitorDialogBase + browse() + + + + monitorName + host + oid + updateIntervalMinutes + updateIntervalSeconds + displayType + buttonOk + buttonCancel + + + checkValues() + browse() + + + + kdialog.h + kpushbutton.h + + diff --git a/ksim/monitors/snmp/pdu.cpp b/ksim/monitors/snmp/pdu.cpp new file mode 100644 index 0000000..1619086 --- /dev/null +++ b/ksim/monitors/snmp/pdu.cpp @@ -0,0 +1,98 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "pdu.h" +#include "snmp_p.h" +#include "value_p.h" + +#include +#include + +#include + +using namespace KSim::Snmp; + +PDU::PDU() + : d( 0 ) +{ +} + +PDU::PDU( int requestType ) +{ + d = SnmpLib::self()->snmp_pdu_create( requestType ); +} + +PDU::~PDU() +{ + if ( d ) + SnmpLib::self()->snmp_free_pdu( d ); +} + +void PDU::addNullVariables( const IdentifierList &oids ) +{ + std::for_each( oids.begin(), oids.end(), + std::bind1st( std::mem_fun( &PDU::addNullVariable ), this ) ); +} + +void PDU::addNullVariable( Identifier oid ) +{ + assert( d ); + SnmpLib::self()->snmp_add_null_var( d, oid.d->data, oid.d->length ); +} + +netsnmp_pdu *PDU::release() +{ + netsnmp_pdu *res = d; + d = 0; + return res; +} + +bool PDU::hasError() const +{ + if ( !d ) + return false; + + return d->errstat != SNMP_ERR_NOERROR; +} + +int PDU::errorCode() const +{ + return d->errstat; +} + +ValueMap PDU::variables() const +{ + if ( !d ) + return ValueMap(); + + ValueMap result; + + for ( variable_list *var = d->variables; var; var = var->next_variable ) { + Identifier oid( new Identifier::Data( var->name, var->name_length ) ); + Value value( new ValueImpl( var ) ); + + result.insert( oid, value ); + } + + return result; +} + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/pdu.h b/ksim/monitors/snmp/pdu.h new file mode 100644 index 0000000..2e648d4 --- /dev/null +++ b/ksim/monitors/snmp/pdu.h @@ -0,0 +1,60 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef PDU_H +#define PDU_H + +#include "identifier.h" +#include "snmplib.h" + +namespace KSim +{ + +namespace Snmp +{ + +class PDU +{ +public: + PDU(); + PDU( int requestType ); + ~PDU(); + + void addNullVariables( const IdentifierList &oids ); + void addNullVariable( Identifier oid ); + + netsnmp_pdu **operator&() { return &d; } + + netsnmp_pdu *release(); + + bool hasError() const; + int errorCode() const; + + ValueMap variables() const; + +private: + netsnmp_pdu *d; +}; + +} +} + +#endif // PDU_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/plugin.cpp b/ksim/monitors/snmp/plugin.cpp new file mode 100644 index 0000000..90683a2 --- /dev/null +++ b/ksim/monitors/snmp/plugin.cpp @@ -0,0 +1,52 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "plugin.h" +#include "view.h" +#include "configpage.h" + +using namespace KSim::Snmp; + +KSIM_INIT_PLUGIN( Plugin ); + +Plugin::Plugin( const char *name ) + : KSim::PluginObject( name ) +{ +} + +Plugin::~Plugin() +{ +} + +KSim::PluginView *Plugin::createView( const char *name ) +{ + return new View( this, name ); +} + +KSim::PluginPage *Plugin::createConfigPage( const char *name ) +{ + return new ConfigPage( this, name ); +} + +void Plugin::showAbout() +{ +} + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/plugin.h b/ksim/monitors/snmp/plugin.h new file mode 100644 index 0000000..3e0fb66 --- /dev/null +++ b/ksim/monitors/snmp/plugin.h @@ -0,0 +1,49 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSIM_PLUGIN_H +#define KSIM_PLUGIN_H + +#include + +namespace KSim +{ + +namespace Snmp +{ + +class Plugin : public KSim::PluginObject +{ +public: + Plugin( const char *name ); + ~Plugin(); + + virtual KSim::PluginView *createView( const char *name ); + virtual KSim::PluginPage *createConfigPage( const char *name ); + + virtual void showAbout(); +}; + +} + +} + +#endif // KSIM_PLUGIN_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/probedialog.cpp b/ksim/monitors/snmp/probedialog.cpp new file mode 100644 index 0000000..d45db6b --- /dev/null +++ b/ksim/monitors/snmp/probedialog.cpp @@ -0,0 +1,117 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "probedialog.h" +#include "monitor.h" + +#include + +#include +#include + +using namespace KSim::Snmp; + +static const char * const probeIdentifiers[] = +{ + "system.sysDescr.0", + "system.sysName.0", + "system.sysUpTime.0", + "system.sysContact.0", + "system.sysObjectID.0", + ".1.3.6.1.2.1.25.1.1.0", + 0 +}; + +ProbeDialog::ProbeDialog( const HostConfig &hostConfig, QWidget *parent, const char *name ) + : KProgressDialog( parent, name, i18n( "SNMP Host Probe" ), QString::null, true /* modal */ ), + m_host( hostConfig ), m_currentMonitor( 0 ), m_canceled( false ) +{ + setLabel( i18n( "Probing for common object identifiers..." ) ); + + for ( uint i = 0; probeIdentifiers[ i ]; ++i ) { + Identifier id = Identifier::fromString( probeIdentifiers[ i ] ); + if ( !id.isNull() ) + m_probeOIDs << id; + } + + progressBar()->setTotalSteps( m_probeOIDs.count() ); + + setAutoClose( false ); + + nextProbe(); +} + +void ProbeDialog::done( int code ) +{ + if ( code == QDialog::Rejected && m_currentMonitor ) { + setLabel( "Probe aborted. Waiting for job to finish..." ); + m_canceled = true; + return; + } + KProgressDialog::done( code ); +} + +void ProbeDialog::probeOne() +{ + if ( m_probeOIDs.isEmpty() ) { + accept(); + return; + } + + Identifier oid = m_probeOIDs.pop(); + + delete m_currentMonitor; + m_currentMonitor = new Monitor( m_host, oid, 0 /* no refresh */, this ); + + connect( m_currentMonitor, SIGNAL( newData( const Identifier &, const Value & ) ), + this, SLOT( probeResult( const Identifier &, const Value & ) ) ); + connect( m_currentMonitor, SIGNAL( error( const Identifier &, const ErrorInfo & ) ), + this, SLOT( probeError( const Identifier &, const ErrorInfo & ) ) ); +} + +void ProbeDialog::probeResult( const Identifier &oid, const Value &value ) +{ + if ( !m_canceled ) + m_results << ProbeResult( oid, value ); + + nextProbe(); +} + +void ProbeDialog::probeError( const Identifier &oid, const ErrorInfo &errorInfo ) +{ + if ( !m_canceled ) + m_results << ProbeResult( oid, errorInfo ); + + nextProbe(); +} + +void ProbeDialog::nextProbe() +{ + progressBar()->setProgress( progressBar()->totalSteps() - m_probeOIDs.count() ); + + if ( m_canceled ) + KProgressDialog::done( QDialog::Rejected ); + else + QTimer::singleShot( 0, this, SLOT( probeOne() ) ); +} + +#include "probedialog.moc" + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/probedialog.h b/ksim/monitors/snmp/probedialog.h new file mode 100644 index 0000000..47a5fb0 --- /dev/null +++ b/ksim/monitors/snmp/probedialog.h @@ -0,0 +1,87 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef PROBEDIALOG_H +#define PROBEDIALOG_H + +#include + +#include + +#include "hostconfig.h" +#include "identifier.h" + +namespace KSim +{ + +namespace Snmp +{ + +class Monitor; + +class ProbeDialog : public KProgressDialog +{ + Q_OBJECT +public: + ProbeDialog( const HostConfig &hostConfig, QWidget *parent, const char *name = 0 ); + + struct ProbeResult + { + ProbeResult() : success( false ) {} + ProbeResult( const Identifier &_oid, const Value &_value ) + : oid( _oid ), value( _value ), success( true ) + {} + ProbeResult( const Identifier &_oid, const ErrorInfo &_errorInfo ) + : oid( _oid ), success( false ), errorInfo( _errorInfo ) + {} + + Identifier oid; + Value value; + bool success; + ErrorInfo errorInfo; + }; + typedef QValueList ProbeResultList; + + ProbeResultList probeResults() const { return m_results; } + +protected: + virtual void done( int code ); + +private slots: + void probeOne(); + void probeResult( const Identifier &oid, const Value &value ); + void probeError( const Identifier &oid, const ErrorInfo &errorInfo ); + +private: + void nextProbe(); + + HostConfig m_host; + QValueStack m_probeOIDs; + Monitor *m_currentMonitor; + + ProbeResultList m_results; + bool m_canceled; +}; + +} +} + +#endif // PROBEDIALOG_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/proberesultdialog.cpp b/ksim/monitors/snmp/proberesultdialog.cpp new file mode 100644 index 0000000..641f12e --- /dev/null +++ b/ksim/monitors/snmp/proberesultdialog.cpp @@ -0,0 +1,55 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "proberesultdialog.h" + +#include + +#include +#include + +using namespace KSim::Snmp; + +ProbeResultDialog::ProbeResultDialog( const HostConfig &hostConfig, const ProbeDialog::ProbeResultList &probeResults, + QWidget *parent, const char *name ) + : ProbeResultDialogBase( parent, name ) +{ + info->setText( i18n( "Results of scanning host %1:" ).arg( hostConfig.name ) ); + + for ( ProbeDialog::ProbeResultList::ConstIterator it = probeResults.begin(); + it != probeResults.end(); ++it ) + addResultItem( *it ); +} + +void ProbeResultDialog::addResultItem( const ProbeDialog::ProbeResult &result ) +{ + QListViewItem *item = new QListViewItem( probeResultView ); + + item->setText( 0, result.oid.toString() ); + + if ( result.success ) + item->setText( 1, result.value.toString( Value::TimeTicksWithSeconds ) ); + else + item->setText( 1, QString( "ERROR: " ) + result.errorInfo.errorMessage() ); +} + +#include "proberesultdialog.moc" + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/proberesultdialog.h b/ksim/monitors/snmp/proberesultdialog.h new file mode 100644 index 0000000..9ba3523 --- /dev/null +++ b/ksim/monitors/snmp/proberesultdialog.h @@ -0,0 +1,49 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef PROBERESULTDIALOG_H +#define PROBERESULTDIALOG_H + +#include "proberesultdialogbase.h" + +#include "probedialog.h" + +namespace KSim +{ + +namespace Snmp +{ + +class ProbeResultDialog : public ProbeResultDialogBase +{ + Q_OBJECT +public: + ProbeResultDialog( const HostConfig &hostConfig, const ProbeDialog::ProbeResultList &probeResults, + QWidget *parent, const char *name = 0 ); + +private: + void addResultItem( const ProbeDialog::ProbeResult &result ); +}; + +} + +} +#endif // PROBERESULTDIALOG_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/proberesultdialogbase.ui b/ksim/monitors/snmp/proberesultdialogbase.ui new file mode 100644 index 0000000..01b0c70 --- /dev/null +++ b/ksim/monitors/snmp/proberesultdialogbase.ui @@ -0,0 +1,124 @@ + +KSim::Snmp::ProbeResultDialogBase + + + ProbeResultDialogBase + + + + 0 + 0 + 501 + 321 + + + + Probe Results + + + true + + + + unnamed + + + + info + + + + + + + + + Object + + + true + + + true + + + + + Value + + + true + + + true + + + + probeResultView + + + true + + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + true + + + true + + + + + + + + + buttonOk + clicked() + ProbeResultDialogBase + accept() + + + + + klistview.h + + diff --git a/ksim/monitors/snmp/session.cpp b/ksim/monitors/snmp/session.cpp new file mode 100644 index 0000000..d7de283 --- /dev/null +++ b/ksim/monitors/snmp/session.cpp @@ -0,0 +1,283 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "session.h" +#include "snmp.h" +#include "snmp_p.h" +#include "snmplib.h" +#include "pdu.h" + +#include + +using namespace KSim::Snmp; + +// ### clean me up +struct Session::Data +{ + Data() : session( 0 ) {} + + netsnmp_session defaultSession; + netsnmp_session *session; + + bool initialized; + + HostConfig source; + + QCString host; + QCString community; + QCString securityName; + QCString authPassPhrase; + QCString privPassPhrase; +}; + +Session::Session( const HostConfig &source ) +{ + d = new Data; + d->initialized = false; + + d->source = source; + + // unicode madness + d->host = source.name.ascii(); + d->community = source.community.ascii(); + d->securityName = source.securityName.ascii(); + d->authPassPhrase = source.authentication.key.ascii(); + d->privPassPhrase = source.privacy.key.ascii(); + + SnmpLib::self()->snmp_sess_init( &d->defaultSession ); +} + +bool Session::snmpGetInternal( int getType, const IdentifierList &identifiers, ValueMap &variables, ErrorInfo *error ) +{ + if ( !d->initialized && !initialize( error ) ) + return false; + + bool result = false; + + if ( getType != SNMP_MSG_GETNEXT && d->session ) { + SnmpLib::self()->snmp_close( d->session ); + d->session = 0; + } + + if ( getType != SNMP_MSG_GETNEXT || + !d->session ) { + + if ( ( d->session = SnmpLib::self()->snmp_open( &d->defaultSession ) ) == 0 ) { + if ( error ) + *error = ErrorInfo( sessionErrorCode( d->defaultSession ) ); + return false; + } + } + + PDU request( getType ); + PDU response; + + request.addNullVariables( identifiers ); + + int status = SnmpLib::self()->snmp_synch_response( d->session, request.release(), &response ); + + if ( status == STAT_SUCCESS ) { + + if ( response.hasError() ) { + + if ( error ) + *error = ErrorInfo( response.errorCode() ); + + } else { + + variables = response.variables(); + result = true; + + if ( error ) + *error = ErrorInfo( ErrorInfo::NoError ); + } + + } else if ( status == STAT_TIMEOUT ) { + + if ( error ) + *error = ErrorInfo( ErrorInfo::ErrTimeout ); + + } else { + + if ( error ) + *error = ErrorInfo( sessionErrorCode( *d->session ) ); + + } + + if ( getType != SNMP_MSG_GETNEXT ) { + SnmpLib::self()->snmp_close( d->session ); + d->session = 0; + } + + return result; + +} + +bool Session::initialize( ErrorInfo *error ) +{ + if ( d->initialized ) { + if ( error ) + *error = ErrorInfo( ErrorInfo::NoError ); + return true; + } + + HostConfig &source = d->source; + + d->defaultSession.peername = d->host.data(); + + d->defaultSession.version = snmpVersionToSnmpLibConstant( source.version ); + + if ( source.version != SnmpVersion3 ) { + d->defaultSession.community = reinterpret_cast( d->community.data() ); + d->defaultSession.community_len = d->community.length(); + d->initialized = true; + return true; + } + + d->defaultSession.securityName = d->securityName.data(); + d->defaultSession.securityNameLen = d->securityName.length(); + + d->defaultSession.securityLevel = snmpSecurityLevelToSnmpLibConstant( source.securityLevel ); + + // ### clean me up + switch ( source.authentication.protocol ) { + case MD5Auth: { + d->defaultSession.securityAuthProto = usmHMACMD5AuthProtocol; + d->defaultSession.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; + break; + } + case SHA1Auth: { + d->defaultSession.securityAuthProto = usmHMACSHA1AuthProtocol; + d->defaultSession.securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; + break; + } + default: assert( false ); + } + + d->defaultSession.securityAuthKeyLen = USM_AUTH_KU_LEN; + + int result; + if ( ( result = SnmpLib::self()->generate_Ku( d->defaultSession.securityAuthProto, d->defaultSession.securityAuthProtoLen, + reinterpret_cast( d->authPassPhrase.data() ), d->authPassPhrase.length(), + d->defaultSession.securityAuthKey, &d->defaultSession.securityAuthKeyLen ) ) + != SNMPERR_SUCCESS ) { + + if ( error ) + *error = ErrorInfo( result ); + + return false; + } + + switch ( source.privacy.protocol ) { + case DESPrivacy: { + d->defaultSession.securityPrivProto = usmDESPrivProtocol; + d->defaultSession.securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; + break; + } + default: assert( false ); + } + + d->defaultSession.securityPrivKeyLen = USM_PRIV_KU_LEN; + + if ( ( result = SnmpLib::self()->generate_Ku( d->defaultSession.securityAuthProto, d->defaultSession.securityAuthProtoLen, + reinterpret_cast( d->privPassPhrase.data() ), d->privPassPhrase.length(), + d->defaultSession.securityPrivKey, &d->defaultSession.securityPrivKeyLen ) ) + != SNMPERR_SUCCESS ) { + + if ( error ) + *error = ErrorInfo( result ); + + + return false; + } + + d->initialized = true; + return true; +} + +bool Session::snmpGet( const QString &identifier, Value &value, ErrorInfo *error ) +{ + bool ok = false; + Identifier oid = Identifier::fromString( identifier, &ok ); + if ( !ok ) { + if ( error ) + *error = ErrorInfo( ErrorInfo::ErrUnknownOID ); + return false; + } + + return snmpGet( oid, value, error ); +} + +bool Session::snmpGet( const Identifier &identifier, Value &value, ErrorInfo *error ) +{ + ValueMap vars; + IdentifierList ids; + + ids << identifier; + + if ( !snmpGet( ids, vars, error ) ) + return false; + + ValueMap::ConstIterator it = vars.find( identifier ); + if ( it == vars.end() ) { + if ( error ) + *error = ErrorInfo( ErrorInfo::ErrMissingVariables ); + return false; + } + + value = it.data(); + + return true; +} + +bool Session::snmpGet( const IdentifierList &identifiers, ValueMap &variables, ErrorInfo *error ) +{ + return snmpGetInternal( SNMP_MSG_GET, identifiers, variables, error ); +} + +bool Session::snmpGetNext( Identifier &identifier, Value &value, ErrorInfo *error ) +{ + ValueMap vars; + IdentifierList ids; + + ids << identifier; + + if ( !snmpGetInternal( SNMP_MSG_GETNEXT, ids, vars, error ) ) + return false; + + assert( vars.count() == 1 ); + + ValueMap::ConstIterator it = vars.begin(); + identifier = it.key(); + value = it.data(); + + return true; + +} + +Session::~Session() +{ + if ( d->session ) + SnmpLib::self()->snmp_close( d->session ); + delete d; +} + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/session.h b/ksim/monitors/snmp/session.h new file mode 100644 index 0000000..0d5cda3 --- /dev/null +++ b/ksim/monitors/snmp/session.h @@ -0,0 +1,64 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SESSION_H +#define SESSION_H + +#include "hostconfig.h" +#include "value.h" +#include "identifier.h" + +namespace KSim +{ + +namespace Snmp +{ + +class Session +{ +public: + struct Data; + + Session( const HostConfig &snmpHostConfig ); + ~Session(); + + bool snmpGet( const QString &identifier, Value &value, ErrorInfo *error = 0 ); + bool snmpGet( const Identifier &identifier, Value &value, ErrorInfo *error = 0 ); + bool snmpGet( const IdentifierList &identifiers, ValueMap &variables, ErrorInfo *error = 0 ); + + bool snmpGetNext( Identifier &identifier, Value &value, ErrorInfo *error = 0 ); + +private: + Data *d; + + bool snmpGetInternal( int getType, const IdentifierList &identifiers, ValueMap &variables, ErrorInfo *error = 0 ); + + bool initialize( ErrorInfo *error ); + + Session( const Session & ); + Session &operator=( const Session & ); +}; + +} + +} + +#endif // SESSION_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/snmp.cpp b/ksim/monitors/snmp/snmp.cpp new file mode 100644 index 0000000..80fb073 --- /dev/null +++ b/ksim/monitors/snmp/snmp.cpp @@ -0,0 +1,320 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "snmp.h" +#include "snmp_p.h" +#include "snmplib.h" +#include "value_p.h" + +#include + +#include + +using namespace KSim::Snmp; + +static const struct EnumStringMapInfo +{ + const int enumValue; + const char *stringValue; + const char snmpLibConstant; +} snmpVersionStrings[ 4 ] = { + { SnmpVersion1, "1", SNMP_VERSION_1 }, + { SnmpVersion2c, "2c", SNMP_VERSION_2c }, + { SnmpVersion3, "3", SNMP_VERSION_3 }, + { 0, 0, 0 } +}, securityLevelStrings[ 4 ] = { + { NoAuthPriv, "NoAuthPriv", SNMP_SEC_LEVEL_NOAUTH }, + { AuthNoPriv, "AuthNoPriv", SNMP_SEC_LEVEL_AUTHNOPRIV }, + { AuthPriv, "AuthPriv", SNMP_SEC_LEVEL_AUTHPRIV }, + { 0, 0, 0 } +}, authenticationProtocolStrings[ 3 ] = { + { MD5Auth, "MD5", 0 }, + { SHA1Auth, "SHA1", 0 }, + { 0, 0, 0 } +}, privacyProtocolStrings[ 2 ] = { + { DESPrivacy, "DES", 0 }, + { 0, 0, 0 } +}; + +static QStringList allStrings( const EnumStringMapInfo *array ) +{ + QStringList result; + for ( uint i = 0; array[ i ].stringValue; ++i ) + result << QString::fromLatin1( array[ i ].stringValue ); + return result; +} + +static QString enumToString( const EnumStringMapInfo *array, int value ) +{ + for ( uint i = 0; array[ i ].stringValue; ++i ) + if ( array[ i ].enumValue == value ) + return QString::fromLatin1( array[ i ].stringValue ); + + assert( false ); + return QString::null; +} + +static int stringToEnum( const EnumStringMapInfo *array, QString string, bool *ok ) +{ + string = string.lower(); + uint i; + for ( i = 0; array[ i ].stringValue; ++i ) + if ( QString::fromLatin1( array[ i ].stringValue ).lower() == string ) { + if ( ok ) *ok = true; + return array[ i ].enumValue; + } + + if ( ok ) + *ok = false; + + // something.. + return array[ 0 ].enumValue; +} + +static int extractSnmpLibConstant( const EnumStringMapInfo *array, int enumValue ) +{ + for ( uint i = 0; array[ i ].stringValue; ++i ) + if ( array[ i ].enumValue == enumValue ) + return array[ i ].snmpLibConstant; + + assert( false ); + return 0; +} + +int KSim::Snmp::snmpVersionToSnmpLibConstant( SnmpVersion version ) +{ + return extractSnmpLibConstant( snmpVersionStrings, version ); +} + +int KSim::Snmp::snmpSecurityLevelToSnmpLibConstant( SecurityLevel secLevel ) +{ + return extractSnmpLibConstant( securityLevelStrings, secLevel ); +} + +QStringList KSim::Snmp::allSnmpVersions() +{ + return allStrings( snmpVersionStrings ); +} + +QString KSim::Snmp::snmpVersionToString( SnmpVersion version ) +{ + return enumToString( snmpVersionStrings, version ); +} + +SnmpVersion KSim::Snmp::stringToSnmpVersion( QString string, bool *ok ) +{ + return static_cast( stringToEnum( snmpVersionStrings, string, ok ) ); +} + +QStringList KSim::Snmp::allSecurityLevels() +{ + return allStrings( securityLevelStrings ); +} + +QString KSim::Snmp::securityLevelToString( SecurityLevel level ) +{ + return enumToString( securityLevelStrings, level ); +} + +SecurityLevel KSim::Snmp::stringToSecurityLevel( QString string, bool *ok ) +{ + return static_cast( stringToEnum( securityLevelStrings, string, ok ) ); +} + +QStringList KSim::Snmp::allAuthenticationProtocols() +{ + return allStrings( authenticationProtocolStrings ); +} + +QString KSim::Snmp::authenticationProtocolToString( AuthenticationProtocol proto ) +{ + return enumToString( authenticationProtocolStrings, proto ); +} + +AuthenticationProtocol KSim::Snmp::stringToAuthenticationProtocol( QString string, bool *ok ) +{ + return static_cast( stringToEnum( authenticationProtocolStrings, string, ok ) ); +} + +QStringList KSim::Snmp::allPrivacyProtocols() +{ + return allStrings( privacyProtocolStrings ); +} + +QString KSim::Snmp::privacyProtocolToString( PrivacyProtocol proto ) +{ + return enumToString( privacyProtocolStrings, proto ); +} + +PrivacyProtocol KSim::Snmp::stringToPrivacyProtocol( QString string, bool *ok ) +{ + return static_cast( stringToEnum( privacyProtocolStrings, string, ok ) ); +} + +// I'm afraid of them changing the order in the error constants or the like, hence the +// slow list instead of a fast lookup table +static const struct ErrorMapInfo +{ + int errorCode; + ErrorInfo::ErrorType enumValue; +} errorMap[] = +{ + // API Errors + { SNMPERR_GENERR, ErrorInfo::ErrGeneric }, + { SNMPERR_BAD_LOCPORT, ErrorInfo::ErrInvalidLocalPort }, + { SNMPERR_BAD_ADDRESS, ErrorInfo::ErrUnknownHost }, + { SNMPERR_BAD_SESSION, ErrorInfo::ErrUnknownSession }, + { SNMPERR_TOO_LONG, ErrorInfo::ErrTooLong }, + { SNMPERR_NO_SOCKET, ErrorInfo::ErrNoSocket }, + { SNMPERR_V2_IN_V1, ErrorInfo::ErrCannotSendV2PDUOnV1Session }, + { SNMPERR_V1_IN_V2, ErrorInfo::ErrCannotSendV1PDUOnV2Session }, + { SNMPERR_BAD_REPEATERS, ErrorInfo::ErrBadValueForNonRepeaters }, + { SNMPERR_BAD_REPETITIONS, ErrorInfo::ErrBadValueForMaxRepetitions }, + { SNMPERR_BAD_ASN1_BUILD, ErrorInfo::ErrBuildingASN1Representation }, + { SNMPERR_BAD_SENDTO, ErrorInfo::ErrFailureInSendto }, + { SNMPERR_BAD_PARSE, ErrorInfo::ErrBadParseOfASN1Type }, + { SNMPERR_BAD_VERSION, ErrorInfo::ErrBadVersion }, + { SNMPERR_BAD_SRC_PARTY, ErrorInfo::ErrBadSourceParty }, + { SNMPERR_BAD_DST_PARTY, ErrorInfo::ErrBadDestinationParty }, + { SNMPERR_BAD_CONTEXT, ErrorInfo::ErrBadContext }, + { SNMPERR_BAD_COMMUNITY, ErrorInfo::ErrBadCommunity }, + { SNMPERR_NOAUTH_DESPRIV, ErrorInfo::ErrCannotSendNoAuthDesPriv }, + { SNMPERR_BAD_ACL, ErrorInfo::ErrBadACL }, + { SNMPERR_BAD_PARTY, ErrorInfo::ErrBadParty }, + { SNMPERR_ABORT, ErrorInfo::ErrSessionAbortFailure }, + { SNMPERR_UNKNOWN_PDU, ErrorInfo::ErrUnknownPDU }, + { SNMPERR_TIMEOUT, ErrorInfo::ErrTimeout }, + { SNMPERR_BAD_RECVFROM, ErrorInfo::ErrFailureInRecvfrom }, + { SNMPERR_BAD_ENG_ID, ErrorInfo::ErrUnableToDetermineContextEngineID }, + { SNMPERR_BAD_SEC_NAME, ErrorInfo::ErrNoSecurityName }, + { SNMPERR_BAD_SEC_LEVEL, ErrorInfo::ErrUnableToDetermineSecurityLevel }, + { SNMPERR_ASN_PARSE_ERR, ErrorInfo::ErrASN1ParseError }, + { SNMPERR_UNKNOWN_SEC_MODEL, ErrorInfo::ErrUnknownSecurityModel }, + { SNMPERR_INVALID_MSG, ErrorInfo::ErrInvalidMessage }, + { SNMPERR_UNKNOWN_ENG_ID, ErrorInfo::ErrUnknownEngineID }, + { SNMPERR_UNKNOWN_USER_NAME, ErrorInfo::ErrUnknownUserName }, + { SNMPERR_UNSUPPORTED_SEC_LEVEL, ErrorInfo::ErrUnsupportedSecurityLevel }, + { SNMPERR_AUTHENTICATION_FAILURE, ErrorInfo::ErrAuthenticationFailure }, + { SNMPERR_NOT_IN_TIME_WINDOW, ErrorInfo::ErrNotInTimeWindow }, + { SNMPERR_DECRYPTION_ERR, ErrorInfo::ErrDecryptionError }, + { SNMPERR_SC_GENERAL_FAILURE, ErrorInfo::ErrSCAPIGeneralFailure }, + { SNMPERR_SC_NOT_CONFIGURED, ErrorInfo::ErrSCAPISubSystemNotConfigured }, + { SNMPERR_KT_NOT_AVAILABLE, ErrorInfo::ErrNoKeyTools }, + { SNMPERR_UNKNOWN_REPORT, ErrorInfo::ErrUnknownReport }, + { SNMPERR_USM_GENERICERROR, ErrorInfo::ErrUSMGenericError }, + { SNMPERR_USM_UNKNOWNSECURITYNAME, ErrorInfo::ErrUSMUnknownSecurityName }, + { SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL, ErrorInfo::ErrUSMUnsupportedSecurityLevel }, + { SNMPERR_USM_ENCRYPTIONERROR, ErrorInfo::ErrUSMEncryptionError }, + { SNMPERR_USM_AUTHENTICATIONFAILURE, ErrorInfo::ErrUSMAuthenticationFailure }, + { SNMPERR_USM_PARSEERROR, ErrorInfo::ErrUSMParseError }, + { SNMPERR_USM_UNKNOWNENGINEID, ErrorInfo::ErrUSMUnknownEngineID }, + { SNMPERR_USM_NOTINTIMEWINDOW, ErrorInfo::ErrUSMNotInTimeWindow }, + { SNMPERR_USM_DECRYPTIONERROR, ErrorInfo::ErrUSMDecryptionError }, + { SNMPERR_NOMIB, ErrorInfo::ErrMIBNotInitialized }, + { SNMPERR_RANGE, ErrorInfo::ErrValueOutOfRange }, + { SNMPERR_MAX_SUBID, ErrorInfo::ErrSubIdOutOfRange }, + { SNMPERR_BAD_SUBID, ErrorInfo::ErrBadSubIdInOID }, + { SNMPERR_LONG_OID, ErrorInfo::ErrOIDTooLong }, + { SNMPERR_BAD_NAME, ErrorInfo::ErrBadValueName }, + { SNMPERR_VALUE, ErrorInfo::ErrBadValueNotation }, + { SNMPERR_UNKNOWN_OBJID, ErrorInfo::ErrUnknownOID }, + { SNMPERR_NULL_PDU, ErrorInfo::ErrNullPDU }, + { SNMPERR_NO_VARS, ErrorInfo::ErrMissingVariables }, + { SNMPERR_VAR_TYPE, ErrorInfo::ErrBadVariableType }, + { SNMPERR_MALLOC, ErrorInfo::ErrOOM }, + { SNMPERR_KRB5, ErrorInfo::ErrKerberos }, + + // PDU response errors + { SNMP_ERR_TOOBIG, ErrorInfo::ErrResponseTooLarge }, + { SNMP_ERR_NOSUCHNAME, ErrorInfo::ErrNoSuchVariable }, + { SNMP_ERR_BADVALUE, ErrorInfo::ErrBadValue }, + { SNMP_ERR_READONLY, ErrorInfo::ErrReadOnly }, + { SNMP_ERR_GENERR, ErrorInfo::ErrGeneric }, + { SNMP_ERR_NOACCESS, ErrorInfo::ErrNoAccess }, + { SNMP_ERR_WRONGTYPE, ErrorInfo::ErrWrongType }, + { SNMP_ERR_WRONGLENGTH, ErrorInfo::ErrWrongLength }, + { SNMP_ERR_WRONGENCODING, ErrorInfo::ErrWrongEncoding }, + { SNMP_ERR_WRONGVALUE, ErrorInfo::ErrWrongValue }, + { SNMP_ERR_NOCREATION, ErrorInfo::ErrNoCreation }, + { SNMP_ERR_INCONSISTENTVALUE, ErrorInfo::ErrInconsistentValue }, + { SNMP_ERR_RESOURCEUNAVAILABLE, ErrorInfo::ErrResourceUnavailable }, + { SNMP_ERR_COMMITFAILED, ErrorInfo::ErrCommitFailed }, + { SNMP_ERR_UNDOFAILED, ErrorInfo::ErrUndoFailed }, + { SNMP_ERR_AUTHORIZATIONERROR, ErrorInfo::ErrAuthorizationFailed }, + { SNMP_ERR_NOTWRITABLE, ErrorInfo::ErrNotWritable }, + { SNMP_ERR_INCONSISTENTNAME, ErrorInfo::ErrInconsistentName }, + + { SNMPERR_SUCCESS, ErrorInfo::NoError } +}; + +ErrorInfo::ErrorType KSim::Snmp::convertSnmpLibErrorToErrorInfo( int error ) +{ + for ( uint i = 0; errorMap[ i ].errorCode != SNMPERR_SUCCESS; ++i ) + if ( errorMap[ i ].errorCode == error ) + return errorMap[ i ].enumValue; + return ErrorInfo::ErrUnknown; +} + +int KSim::Snmp::convertErrorInfoToSnmpLibError( ErrorInfo::ErrorType error ) +{ + for ( uint i = 0; errorMap[ i ].errorCode != SNMPERR_SUCCESS; ++i ) + if ( errorMap[ i ].enumValue == error ) + return errorMap[ i ].errorCode; + assert( false ); + return SNMPERR_SUCCESS; +} + +int KSim::Snmp::sessionErrorCode( netsnmp_session &session ) +{ + int errorCode = 0; + SnmpLib::self()->snmp_error( &session, 0, &errorCode, 0 ); + return errorCode; +} + +static QString messageForErrorCode( int errorCode ) +{ + if ( errorCode >= SNMPERR_MAX && errorCode <= SNMPERR_GENERR ) + return QString::fromLatin1( SnmpLib::self()->snmp_api_errstring( errorCode ) ); + if ( errorCode >= SNMP_ERR_NOERROR && errorCode <= MAX_SNMP_ERR ) + return QString::fromLatin1( SnmpLib::self()->snmp_errstring( errorCode ) ); + + return QString::null; +} + +ErrorInfo::ErrorInfo() +{ + m_errorCode = NoError; +} + +ErrorInfo::ErrorInfo( int internalErrorCode ) +{ + m_errorCode = convertSnmpLibErrorToErrorInfo( internalErrorCode ); + m_errorMessage = messageForErrorCode( internalErrorCode ); +} + +ErrorInfo::ErrorInfo( ErrorType error ) +{ + m_errorCode = error; + if ( error != NoError && error != ErrUnknown ) + m_errorMessage = messageForErrorCode( convertErrorInfoToSnmpLibError( error ) ); +} + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/snmp.h b/ksim/monitors/snmp/snmp.h new file mode 100644 index 0000000..4710c2d --- /dev/null +++ b/ksim/monitors/snmp/snmp.h @@ -0,0 +1,165 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KSIM_SNMP_H +#define KSIM_SNMP_H + +#include + +#include + + +namespace KSim +{ + +namespace Snmp +{ + +enum SnmpVersion { SnmpVersion1, SnmpVersion2c, SnmpVersion3, SnmpLastVersion }; +QStringList allSnmpVersions(); +QString snmpVersionToString( SnmpVersion version ); +SnmpVersion stringToSnmpVersion( QString string, bool *ok = 0 ); + +enum SecurityLevel { NoAuthPriv, AuthNoPriv, AuthPriv, LastSecurityLevel }; +QStringList allSecurityLevels(); +QString securityLevelToString( SecurityLevel level ); +SecurityLevel stringToSecurityLevel( QString string, bool *ok = 0 ); + +enum AuthenticationProtocol { MD5Auth, SHA1Auth, LastAuthenticationProtocol }; +QStringList allAuthenticationProtocols(); +QString authenticationProtocolToString( AuthenticationProtocol proto ); +AuthenticationProtocol stringToAuthenticationProtocol( QString string, bool *ok = 0 ); + +enum PrivacyProtocol { DESPrivacy }; +QStringList allPrivacyProtocols(); +QString privacyProtocolToString( PrivacyProtocol proto ); +PrivacyProtocol stringToPrivacyProtocol( QString string, bool *ok = 0 ); + +class ErrorInfo +{ +public: + enum ErrorType { + NoError = 0, + ErrUnknown, // ... if we forgot a mapping of error codes + + // api errors + ErrGeneric, + ErrInvalidLocalPort, + ErrUnknownHost, + ErrUnknownSession, + ErrTooLong, + ErrNoSocket, + ErrCannotSendV2PDUOnV1Session, + ErrCannotSendV1PDUOnV2Session, + ErrBadValueForNonRepeaters, + ErrBadValueForMaxRepetitions, + ErrBuildingASN1Representation, + ErrFailureInSendto, + ErrBadParseOfASN1Type, + ErrBadVersion, + ErrBadSourceParty, + ErrBadDestinationParty, + ErrBadContext, + ErrBadCommunity, + ErrCannotSendNoAuthDesPriv, + ErrBadACL, + ErrBadParty, + ErrSessionAbortFailure, + ErrUnknownPDU, + ErrTimeout, + ErrFailureInRecvfrom, + ErrUnableToDetermineContextEngineID, + ErrNoSecurityName, + ErrUnableToDetermineSecurityLevel, + ErrASN1ParseError, + ErrUnknownSecurityModel, + ErrInvalidMessage, + ErrUnknownEngineID, + ErrUnknownUserName, + ErrUnsupportedSecurityLevel, + ErrAuthenticationFailure, + ErrNotInTimeWindow, + ErrDecryptionError, + ErrSCAPIGeneralFailure, + ErrSCAPISubSystemNotConfigured, + ErrNoKeyTools, + ErrUnknownReport, + ErrUSMGenericError, + ErrUSMUnknownSecurityName, + ErrUSMUnsupportedSecurityLevel, + ErrUSMEncryptionError, + ErrUSMAuthenticationFailure, + ErrUSMParseError, + ErrUSMUnknownEngineID, + ErrUSMNotInTimeWindow, + ErrUSMDecryptionError, + ErrMIBNotInitialized, + ErrValueOutOfRange, + ErrSubIdOutOfRange, + ErrBadSubIdInOID, + ErrOIDTooLong, + ErrBadValueName, + ErrBadValueNotation, + ErrUnknownOID, + ErrNullPDU, + ErrMissingVariables, + ErrBadVariableType, + ErrOOM, + ErrKerberos, + + // pdu response errors + + ErrResponseTooLarge, + ErrNoSuchVariable, + ErrBadValue, + ErrReadOnly, + ErrNoAccess, + ErrWrongType, + ErrWrongLength, + ErrWrongEncoding, + ErrWrongValue, + ErrNoCreation, + ErrInconsistentValue, + ErrResourceUnavailable, + ErrCommitFailed, + ErrUndoFailed, + ErrAuthorizationFailed, + ErrNotWritable, + ErrInconsistentName + }; + + ErrorInfo(); + ErrorInfo( int internalErrorCode ); + ErrorInfo( ErrorType error ); + + ErrorType errorCode() const { return m_errorCode; } + QString errorMessage() const { return m_errorMessage; } + +private: + ErrorType m_errorCode; + QString m_errorMessage; +}; + +} + +} + +#endif // KSIMSNMP_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/snmp_p.h b/ksim/monitors/snmp/snmp_p.h new file mode 100644 index 0000000..9d96868 --- /dev/null +++ b/ksim/monitors/snmp/snmp_p.h @@ -0,0 +1,59 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SNMP_P_H +#define SNMP_P_H + +#define HAVE_STRLCPY 1 +#include +#include + +#include "snmp.h" +#include "identifier.h" + +namespace KSim +{ + +namespace Snmp +{ + +ErrorInfo::ErrorType convertSnmpLibErrorToErrorInfo( int error ); +int convertErrorInfoToSnmpLibError( ErrorInfo::ErrorType error ); + +int snmpVersionToSnmpLibConstant( SnmpVersion version ); +int snmpSecurityLevelToSnmpLibConstant( SecurityLevel secLevel ); + +int sessionErrorCode( netsnmp_session &session ); + +struct Identifier::Data +{ + Data() : length( 0 ) {} + Data( const oid *d, size_t length ); + + oid data[ MAX_OID_LEN ]; + size_t length; +}; + +} + +} + +#endif // SNMP_P_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/snmplib.cpp b/ksim/monitors/snmp/snmplib.cpp new file mode 100644 index 0000000..a063203 --- /dev/null +++ b/ksim/monitors/snmp/snmplib.cpp @@ -0,0 +1,151 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "snmplib.h" +#include "snmp_p.h" + +#include + +using namespace KSim::Snmp; + +SnmpLib *SnmpLib::s_self; + +::KStaticDeleter sd; + +SnmpLib::SnmpLib() +{ + m_lockHelper = new ClassLocker( &m_guard, this ); + + init_snmp( "ksim" ); +} + +SnmpLib::~SnmpLib() +{ + delete m_lockHelper; +} + +ClassLocker &SnmpLib::self() +{ + if ( !s_self ) { + static QMutex singletonGuard; + + QMutexLocker locker( &singletonGuard ); + if ( !s_self ) + sd.setObject( s_self, new SnmpLib ); + } + return *s_self->m_lockHelper; +} + +oid *SnmpLib::snmp_parse_oid( const char *name, oid *oid, size_t *length ) +{ + return ::snmp_parse_oid( name, oid, length ); +} + +int SnmpLib::netsnmp_ds_set_int( int storeid, int which, int value ) +{ + return ::netsnmp_ds_set_int( storeid, which, value ); +} + +int SnmpLib::netsnmp_ds_get_int( int storeid, int which ) +{ + return ::netsnmp_ds_get_int( storeid, which ); +} + +struct tree *SnmpLib::netsnmp_sprint_realloc_objid_tree( u_char ** buf, + size_t * buf_len, + size_t * out_len, + int allow_realloc, + int *buf_overflow, + const oid * objid, + size_t objidlen ) +{ + return ::netsnmp_sprint_realloc_objid_tree( buf, buf_len, out_len, allow_realloc, buf_overflow, objid, objidlen ); +} + +int SnmpLib::netsnmp_oid_equals( const oid *firstOid, size_t firstOidLen, const oid *secondOid, size_t secondOidLen ) +{ + return ::netsnmp_oid_equals( firstOid, firstOidLen, secondOid, secondOidLen ); +} + +int SnmpLib::snmp_oid_compare( const oid *firstOid, size_t firstOidLen, const oid *secondOid, size_t secondOidLen ) +{ + return ::snmp_oid_compare( firstOid, firstOidLen, secondOid, secondOidLen ); +} + +void SnmpLib::snmp_error( netsnmp_session *session, int *p_errno, int *p_snmp_errno, char **p_str ) +{ + ::snmp_error( session, p_errno, p_snmp_errno, p_str ); +} + +const char *SnmpLib::snmp_api_errstring( int code ) +{ + return ::snmp_api_errstring( code ); +} + +const char *SnmpLib::snmp_errstring( int code ) +{ + return ::snmp_errstring( code ); +} + +netsnmp_pdu *SnmpLib::snmp_pdu_create( int pduType ) +{ + return ::snmp_pdu_create( pduType ); +} + +void SnmpLib::snmp_free_pdu( netsnmp_pdu *pdu ) +{ + ::snmp_free_pdu( pdu ); +} + +netsnmp_variable_list *SnmpLib::snmp_add_null_var( netsnmp_pdu *pdu, oid *var, size_t varlen ) +{ + return ::snmp_add_null_var( pdu, var, varlen ); +} + +void SnmpLib::snmp_sess_init( netsnmp_session *session ) +{ + ::snmp_sess_init( session ); +} + +netsnmp_session *SnmpLib::snmp_open( netsnmp_session *session ) +{ + return ::snmp_open( session ); +} + +int SnmpLib::snmp_close( netsnmp_session *session ) +{ + return ::snmp_close( session ); +} + +int SnmpLib::snmp_synch_response( netsnmp_session *session, netsnmp_pdu *pdu, + netsnmp_pdu **response ) +{ + return ::snmp_synch_response( session, pdu, response ); +} + +int SnmpLib::generate_Ku( const oid * hashtype, u_int hashtype_len, + u_char * P, size_t pplen, + u_char * Ku, size_t * kulen ) +{ + return ::generate_Ku( hashtype, hashtype_len, P, pplen, Ku, kulen ); +} + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/snmplib.h b/ksim/monitors/snmp/snmplib.h new file mode 100644 index 0000000..e8b14a4 --- /dev/null +++ b/ksim/monitors/snmp/snmplib.h @@ -0,0 +1,143 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SNMPLIB_H +#define SNMPLIB_H + +// ### REMOVEME: move snmplib somewhere else +#define HAVE_STRLCPY 1 +#include +#include + +#include + +template class KStaticDeleter; + +namespace KSim +{ + +namespace Snmp +{ + +template +class ClassLocker +{ +public: + ClassLocker( QMutex *guard, T *obj ) + : m_guard( guard ), m_obj( obj ) + {} + + struct ClassLockerHelper + { + ClassLockerHelper( QMutex *guard, T *obj ) + : m_guard( guard ), m_obj( obj ), m_locked( false ) + {} + + ~ClassLockerHelper() + { + if ( m_locked ) + m_guard->unlock(); + } + + T *operator->() + { + m_guard->lock(); + m_locked = true; + return m_obj; + } + + private: + QMutex *m_guard; + T *m_obj; + bool m_locked; + }; + + ClassLockerHelper operator->() + { + return ClassLockerHelper( m_guard, m_obj ); + } + +private: + ClassLocker( const ClassLocker & ); + ClassLocker &operator=( const ClassLocker & ); + + QMutex *m_guard; + T *m_obj; +}; + +class SnmpLib +{ + friend class KStaticDeleter; +public: + + static ClassLocker &self(); + + oid *snmp_parse_oid( const char *name, oid *oid, size_t *length ); + + int netsnmp_ds_set_int( int storeid, int which, int value ); + int netsnmp_ds_get_int( int storeid, int which ); + + struct tree *netsnmp_sprint_realloc_objid_tree( u_char ** buf, + size_t * buf_len, + size_t * out_len, + int allow_realloc, + int *buf_overflow, + const oid * objid, + size_t objidlen ); + + int netsnmp_oid_equals( const oid *firstOid, size_t firstOidLen, const oid *secondOid, size_t secondOidLen ); + int snmp_oid_compare( const oid *firstOid, size_t firstOidLen, const oid *secondOid, size_t secondOidLen ); + + void snmp_error( netsnmp_session *session, int *p_errno, int *p_snmp_errno, char **p_str ); + const char *snmp_api_errstring( int code ); + const char *snmp_errstring( int code ); + + netsnmp_pdu *snmp_pdu_create( int pduType ); + void snmp_free_pdu( netsnmp_pdu *pdu ); + netsnmp_variable_list *snmp_add_null_var( netsnmp_pdu *pdu, oid *var, size_t varlen ); + + void snmp_sess_init( netsnmp_session *session ); + netsnmp_session *snmp_open( netsnmp_session *session ); + int snmp_close( netsnmp_session *session ); + + int snmp_synch_response( netsnmp_session *session, netsnmp_pdu *pdu, + netsnmp_pdu **response ); + + int generate_Ku( const oid * hashtype, u_int hashtype_len, + u_char * P, size_t pplen, + u_char * Ku, size_t * kulen ); + +private: + SnmpLib(); + ~SnmpLib(); + + QMutex m_guard; + ClassLocker *m_lockHelper; + + static SnmpLib *s_self; +}; + +} +} + + +#endif // SNMPLIB_H +/* vim: et sw=4 ts=4 + */ + diff --git a/ksim/monitors/snmp/value.cpp b/ksim/monitors/snmp/value.cpp new file mode 100644 index 0000000..fe42a08 --- /dev/null +++ b/ksim/monitors/snmp/value.cpp @@ -0,0 +1,333 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "value.h" +#include "value_p.h" +#include "snmp_p.h" + +#include + +#include + +#include + +using namespace KSim::Snmp; + +ValueImpl::ValueImpl( variable_list *var ) +{ + switch ( var->type ) { + case ASN_INTEGER: { + type = Value::Int; + data = QVariant( static_cast( *var->val.integer ) ); + break; + } + case ASN_UINTEGER: { + type = Value::UInt; + data = QVariant( static_cast( *var->val.integer ) ); + break; + } + case ASN_OCTET_STR: { + type = Value::ByteArray; + QByteArray d; + d.setRawData( reinterpret_cast( var->val.string ), var->val_len ); + QByteArray copy = d; + copy.detach(); + d.resetRawData( reinterpret_cast( var->val.string ), var->val_len ); + data = QVariant( copy ); + break; + } + case ASN_NULL: { + type = Value::Null; + break; + } + case ASN_OBJECT_ID: { + type = Value::Oid; + oid = Identifier( new Identifier::Data( var->val.objid, var->val_len / sizeof( oid ) ) ); + break; + } + case ASN_IPADDRESS: { + type = Value::IpAddress; + addr = QHostAddress( static_cast( *var->val.integer ) ); + break; + } + case ASN_COUNTER: { + type = Value::Counter; + data = QVariant( static_cast( *var->val.integer ) ); + break; + } + case ASN_GAUGE: { + type = Value::Gauge; + data = QVariant( static_cast( *var->val.integer ) ); + break; + } + case ASN_COUNTER64: { + type = Value::Counter64; + ctr64 = ( ( ( Q_UINT64 )var->val.counter64->high ) << 32 ) | ( var->val.counter64->low ); + break; + } + case ASN_TIMETICKS: { + type = Value::TimeTicks; + data = QVariant( static_cast( *var->val.integer ) ); + break; + } + case SNMP_NOSUCHOBJECT: { + type = Value::NoSuchObject; + break; + } + case SNMP_NOSUCHINSTANCE: { + type = Value::NoSuchInstance; + break; + } + case SNMP_ENDOFMIBVIEW: { + type = Value::EndOfMIBView; + break; + } +#if defined( OPAQUE_SPECIAL_TYPES ) + case ASN_OPAQUE_FLOAT: { + type = Value::Double; + data = QVariant( static_cast( *var->val.floatVal ) ); + break; + } + case ASN_OPAQUE_DOUBLE: { + type = Value::Double; + data = QVariant( static_cast( *var->val.doubleVal ) ); + break; + } +#endif + default: { + qDebug( "ValueImp: converting from %i to invalid", var->type ); + type = Value::Invalid; break; + } + } +} + +Value::Value() +{ + d = new ValueImpl; +} + +Value::Value( ValueImpl *impl ) + : d( impl ) +{ +} + +Value::Value( int val, Type type ) +{ + d = new ValueImpl; + + assert( type == Int || type == TimeTicks ); + + d->type = type; + d->data = QVariant( val ); +} + +Value::Value( uint val, Type type ) +{ + d = new ValueImpl; + + assert( type == UInt || type == Counter || type == Gauge ); + + d->type = type; + d->data = QVariant( val ); +} + +Value::Value( double val ) +{ + d = new ValueImpl; + d->type = Double; + d->data = QVariant( val ); +} + +Value::Value( const QByteArray &data ) +{ + d = new ValueImpl; + d->type = ByteArray; + d->data = QVariant( data ); +} + +Value::Value( const KSim::Snmp::Identifier &oid ) +{ + d = new ValueImpl; + d->type = Value::Oid; + d->oid = oid; +} + +Value::Value( const QHostAddress &address ) +{ + d = new ValueImpl; + d->type = IpAddress; + d->addr = address; +} + +Value::Value( Q_UINT64 counter ) +{ + d = new ValueImpl; + d->type = Counter64; + d->ctr64 = counter; +} + +Value::Value( const Value &rhs ) +{ + d = new ValueImpl( *rhs.d ); +} + +Value &Value::operator=( const Value &rhs ) +{ + if ( this == &rhs ) + return *this; + + delete d; + d = new ValueImpl( *rhs.d ); + + return *this; +} + +Value::~Value() +{ + delete d; +} + +Value::Type Value::type() const +{ + return d->type; +} + +int Value::toInt() const +{ + switch ( d->type ) { + case Int: + case TimeTicks: return d->data.toInt(); + case Invalid: qDebug( "cannot convert from invalid to int" ); + default: assert( false ); + } + assert( false ); + return -1; +} + +uint Value::toUInt() const +{ + switch ( d->type ) { + case UInt: + case Counter: + case Gauge: return d->data.toUInt(); + case Invalid: qDebug( "cannot convert from invalid to uint" ); + default: assert( false ); + } + assert( false ); + return 0; +} + +double Value::toDouble() const +{ + assert( d->type == Double ); + return d->data.toDouble(); +} + +const QByteArray Value::toByteArray() const +{ + assert( d->type == ByteArray ); + return d->data.toByteArray(); +} + +const Identifier Value::toOID() const +{ + assert( d->type == Oid ); + return d->oid; +} + +const QHostAddress Value::toIpAddress() const +{ + assert( d->type == IpAddress ); + return d->addr; +} + +uint Value::toCounter() const +{ + return toUInt(); +} + +uint Value::toGauge() const +{ + return toUInt(); +} + +int Value::toTimeTicks() const +{ + return toInt(); +} + +Q_UINT64 Value::toCounter64() const +{ + assert( d->type == Counter64 ); + return d->ctr64; +} + +QString Value::toString( int conversionFlags ) const +{ + switch ( type() ) { + case Value::Int: return QString::number( toInt() ); + case Value::Gauge: + case Value::Counter: + case Value::UInt: return QString::number( toUInt() ); + case Value::Double: return QString::number( toDouble() ); + case Value::Counter64: return QString::number( toCounter64() ); + case Value::ByteArray: return QString::fromAscii( toByteArray().data(), toByteArray().size() ); + case Value::IpAddress: return toIpAddress().toString(); + case Value::Oid: return toOID().toString(); + case Value::TimeTicks: return formatTimeTicks( toTimeTicks(), conversionFlags ); + // not using i18n here, because it may be called from within a worker thread, and I'm + // not sure it makes sense to translate it anyway + case Value::NoSuchObject: return QString::fromLatin1( "No Such Object" ); + case Value::NoSuchInstance: return QString::fromLatin1( "No Such Instance" ); + case Value::EndOfMIBView: return QString::fromLatin1( "End Of MIB View" ); + case Value::Invalid: + case Value::Null: return QString::null; + } + return QString::null; +} + +QString Value::formatTimeTicks( int ticks, int conversionFlags ) +{ + ticks /= 100; + + int days = ticks / ( 60 * 60 * 24 ); + ticks %= 60 * 60 * 24; + + int hours = ticks / ( 60 * 60 ); + ticks %= 60 * 60; + + int minutes = ticks / 60; + int seconds = ticks % 60; + + QString result; + + if ( days > 0 ) + result += QString::number( days ) + "d:"; + + result += QString::fromAscii( "%1h:%2m" ).arg( hours ).arg( minutes ); + + if ( conversionFlags & TimeTicksWithSeconds ) + result += ":" + QString::number( seconds ) + "s"; + + return result; +} + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/value.h b/ksim/monitors/snmp/value.h new file mode 100644 index 0000000..4ffdcbb --- /dev/null +++ b/ksim/monitors/snmp/value.h @@ -0,0 +1,106 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef VALUE_H +#define VALUE_H + +#include + +namespace KSim +{ + +namespace Snmp +{ + +class ValueImpl; + +class Identifier; + +struct ValueImpl; + +class Value +{ +public: + enum Type { + Invalid, + Int, + UInt, + Double, + ByteArray, + Null, + Oid, + IpAddress, + Counter, + Gauge, + TimeTicks, + Counter64, + NoSuchObject, + NoSuchInstance, + EndOfMIBView + }; + + enum StringConversionFlags { TimeTicksWithSeconds = 0x1 }; + + Value(); + + Value( ValueImpl *imp ); + + Value( int val, Type type ); + Value( uint val, Type type ); + Value( float val ); + Value( double val ); + Value( const QByteArray &data ); + Value( const Identifier &oid ); + Value( const QHostAddress &address ); + Value( Q_UINT64 counter ); + + Value( const Value &rhs ); + Value &operator=( const Value &rhs ); + ~Value(); + + Type type() const; + + bool isCounterType() const { return type() == Value::Counter || type() == Value::Counter64; } + + int toInt() const; + uint toUInt() const; + double toDouble() const; + const QByteArray toByteArray() const; + const Identifier toOID() const; + const QHostAddress toIpAddress() const; + uint toCounter() const; + uint toGauge() const; + int toTimeTicks() const; + Q_UINT64 toCounter64() const; + + QString toString( int conversionFlags = 0 ) const; + +private: + static QString formatTimeTicks( int ticks, int conversionFlags ); + + ValueImpl *d; +}; + +} + +} + +#endif // VALUE_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/value_p.h b/ksim/monitors/snmp/value_p.h new file mode 100644 index 0000000..8d61f59 --- /dev/null +++ b/ksim/monitors/snmp/value_p.h @@ -0,0 +1,63 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef VALUE_P_H +#define VALUE_P_H + +#define HAVE_STRLCPY 1 +#include +#include + +#include + +#include "identifier.h" + +namespace KSim +{ + +namespace Snmp +{ + +struct ValueImpl +{ + ValueImpl() + : type( Value::Invalid ) + {} + + ValueImpl( const ValueImpl &rhs ) + { + ( *this ) = rhs; + } + + ValueImpl( variable_list *var ); + + Value::Type type; + QVariant data; + Identifier oid; + QHostAddress addr; + Q_UINT64 ctr64; +}; + +} + +} + +#endif // VALUE_P_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/view.cpp b/ksim/monitors/snmp/view.cpp new file mode 100644 index 0000000..0a4b276 --- /dev/null +++ b/ksim/monitors/snmp/view.cpp @@ -0,0 +1,80 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "view.h" +#include "plugin.h" +#include "monitorconfig.h" + +#include + +#include + +#include + +using namespace KSim::Snmp; + +View::View( Plugin *parent, const char *name ) + : KSim::PluginView( parent, name ) +{ + m_layout = new QVBoxLayout( this ); + + reparseConfig(); +} + +View::~View() +{ +} + +void View::reparseConfig() +{ + m_widgets.setAutoDelete( true ); + m_widgets.clear(); + m_widgets.setAutoDelete( false ); + + KConfig &cfg = *config(); + cfg.setGroup( "General" ); + QStringList allHosts = cfg.readListEntry( "Hosts" ); + QStringList monitors = cfg.readListEntry( "Monitors" ); + + HostConfigMap hosts; + hosts.load( cfg, allHosts ); + + MonitorConfigMap monitorConfigs; + monitorConfigs.load( cfg, monitors, hosts ); + + for ( MonitorConfigMap::ConstIterator it = monitorConfigs.begin(); + it != monitorConfigs.end(); ++it ) { + + MonitorConfig monitorConfig = *it; + + QWidget *w = monitorConfig.createMonitorWidget( this ); + if ( !w ) + continue; + + m_widgets.append( w ); + m_layout->addWidget( w ); + + w->show(); + } +} + +#include "view.moc" + +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/view.h b/ksim/monitors/snmp/view.h new file mode 100644 index 0000000..f03a59c --- /dev/null +++ b/ksim/monitors/snmp/view.h @@ -0,0 +1,55 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef VIEW_H +#define VIEW_H + +#include + +class QBoxLayout; + +namespace KSim +{ + +namespace Snmp +{ + +class Plugin; + +class View : public KSim::PluginView +{ + Q_OBJECT +public: + View( Plugin *parent, const char *name ); + ~View(); + + virtual void reparseConfig(); + +private: + QPtrList m_widgets; + QBoxLayout *m_layout; +}; + +} + +} + +#endif // VIEW_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/walker.cpp b/ksim/monitors/snmp/walker.cpp new file mode 100644 index 0000000..593cd04 --- /dev/null +++ b/ksim/monitors/snmp/walker.cpp @@ -0,0 +1,121 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "walker.h" + +#include + +#include +#include + +using namespace KSim::Snmp; + +namespace +{ + template + struct Deleter : public std::unary_function + { + void operator()( T arg ) + { delete arg; } + }; +} + +static const uint walkerRefresh = 0; + +Walker::Walker( const HostConfig &host, const Identifier &startOid, QObject *parent, const char *name ) + : QObject( parent, name ), m_stop( false ), m_oid( startOid ), m_session( host ) +{ + m_timerId = startTimer( walkerRefresh ); + start(); +} + +Walker::~Walker() +{ + m_stopGuard.lock(); + m_stop = true; + m_stopGuard.unlock(); + + if ( QThread::running() ) + QThread::wait(); + + std::for_each( m_results.begin(), m_results.end(), Deleter() ); +} + +void Walker::run() +{ + while ( !m_stop ) { + Result *result = new Result; + + result->success = m_session.snmpGetNext( m_oid, result->data, &result->error ); + result->oid = m_oid; + + // do it here, because it sometimes is slow and can block for a bit + if ( result->success ) { + result->identifierString = result->oid.toString(); + result->dataString = result->data.toString(); + } + + m_stopGuard.lock(); + if ( !m_stop ) + m_stop = !result->success; + m_stopGuard.unlock(); + + m_resultGuard.lock(); + m_results << result; + m_resultGuard.unlock(); + } + + // cause finished signal to be emitted + QApplication::postEvent( this, new QCustomEvent( QEvent::User ) ); +} + +void Walker::timerEvent( QTimerEvent *ev ) +{ + if ( ev->timerId() != m_timerId ) + return; + + Result *result = 0; + + m_resultGuard.lock(); + if ( !m_results.isEmpty() ) { + result = m_results.first(); + m_results.remove( m_results.begin() ); + } + m_resultGuard.unlock(); + + if ( result ) { + emit resultReady( *result ); + + delete result; + } + + if ( !QThread::running() && !result ) { + killTimer( m_timerId ); + m_timerId = 0; + } +} + +void Walker::customEvent( QCustomEvent * ) +{ + emit finished(); +} + +#include "walker.moc" +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/monitors/snmp/walker.h b/ksim/monitors/snmp/walker.h new file mode 100644 index 0000000..e1b1ace --- /dev/null +++ b/ksim/monitors/snmp/walker.h @@ -0,0 +1,82 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Simon Hausmann + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef WALKER_H +#define WALKER_H + +#include +#include +#include +#include + +#include "session.h" + +namespace KSim +{ + +namespace Snmp +{ + +class Walker : public QObject, public QThread +{ + Q_OBJECT +public: + Walker( const HostConfig &host, const Identifier &startOid, QObject *parent, const char *name = 0 ); + virtual ~Walker(); + + struct Result + { + Result() : success( false ) {} + bool success; + Identifier oid; + QString identifierString; + Value data; + QString dataString; + ErrorInfo error; + }; + +signals: + void resultReady( const Walker::Result &result ); + void finished(); + +protected: + virtual void run(); + virtual void timerEvent( QTimerEvent *ev ); + virtual void customEvent( QCustomEvent *ev ); + +private: + typedef QValueList ResultList; + + ResultList m_results; + QMutex m_resultGuard; + + bool m_stop; + QMutex m_stopGuard; + + Identifier m_oid; + int m_timerId; + Session m_session; +}; + +} +} + +#endif // WALKER_H +/* vim: et sw=4 ts=4 + */ diff --git a/ksim/pics/Makefile.am b/ksim/pics/Makefile.am new file mode 100644 index 0000000..1cceeb0 --- /dev/null +++ b/ksim/pics/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = misc +KDE_ICON = AUTO diff --git a/ksim/pics/cr16-app-ksim.png b/ksim/pics/cr16-app-ksim.png new file mode 100644 index 0000000..60c99da Binary files /dev/null and b/ksim/pics/cr16-app-ksim.png differ diff --git a/ksim/pics/cr32-app-ksim.png b/ksim/pics/cr32-app-ksim.png new file mode 100644 index 0000000..f889a5a Binary files /dev/null and b/ksim/pics/cr32-app-ksim.png differ diff --git a/ksim/pics/cr48-app-ksim.png b/ksim/pics/cr48-app-ksim.png new file mode 100644 index 0000000..e7a7bd3 Binary files /dev/null and b/ksim/pics/cr48-app-ksim.png differ diff --git a/ksim/pics/misc/Makefile.am b/ksim/pics/misc/Makefile.am new file mode 100644 index 0000000..64229a0 --- /dev/null +++ b/ksim/pics/misc/Makefile.am @@ -0,0 +1,5 @@ +ksim_images = clock.png uptime.png +EXTRA_DIST = $(ksim_images) + +images_DATA = $(ksim_images) +imagesdir = $(kde_datadir)/ksim/pics diff --git a/ksim/pics/misc/clock.png b/ksim/pics/misc/clock.png new file mode 100644 index 0000000..dca2c7e Binary files /dev/null and b/ksim/pics/misc/clock.png differ diff --git a/ksim/pics/misc/uptime.png b/ksim/pics/misc/uptime.png new file mode 100644 index 0000000..08e90f7 Binary files /dev/null and b/ksim/pics/misc/uptime.png differ diff --git a/ksim/systeminfo.cpp b/ksim/systeminfo.cpp new file mode 100644 index 0000000..567477c --- /dev/null +++ b/ksim/systeminfo.cpp @@ -0,0 +1,277 @@ +/* System Information + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include "systeminfo.h" + +#ifdef __linux__ +#include +#include +#endif + +#ifdef HAVE_SYS_LOADAVG_H +#include +#endif + +#ifdef __FreeBSD__ +#include +#include +#include +#include +#include +#include +#if __FreeBSD_version < 400000 +#include +#endif +#include +#include +#include +#include +#include +#endif + +// Some global vars +// expand as needed for other platforms +int System::bytesToMegs( unsigned long value ) +{ +#ifdef __linux__ + return ((((value / 1024) >> 10) | 11) + 1); +#endif + +#ifdef __FreeBSD__ + return (((value) + (1 << 19)) >> 20); +#endif +} + +System * System::m_self = 0; // initialize pointer +System & System::self() +{ + if ( !m_self ) + { + m_self = new System; + atexit( System::cleanup ); + } + + m_self->updateData(); + return *m_self; +} + +void System::cleanup() +{ + if ( !m_self ) + return; + + delete m_self; + m_self = 0; +} + +double System::loadAverage( int load ) const +{ + int value = --load; + return loadAverages()[ value > 2 ? 2 : value ]; +} + +System::System() +{ + m_loads[ 0 ] = 0; + m_loads[ 1 ] = 0; + m_loads[ 2 ] = 0; + + m_uptime = 0; + m_totalram = 0; + m_usedram = 0; + m_freeram = 0; + m_sharedram = 0; + m_bufferram = 0; + m_cacheram = 0; + m_totalhigh = 0; + m_freehigh = 0; + m_totalswap = 0; + m_usedswap = 0; + m_freeswap = 0; + m_procs = 0; + + m_self = this; +} + +System::~System() +{ +} + +void System::updateData() +{ +#ifdef __linux__ + struct sysinfo system; + if (sysinfo(&system) < 0) { + fprintf(stderr, "Error calling sysinfo()\n"); + return; + } + + m_uptime = system.uptime; + m_totalram = system.totalram; + m_sharedram = system.sharedram; + m_bufferram = system.bufferram; + m_usedram = m_totalram - m_freeram; + +#ifdef HAVE_SYSINFO_HIGH + m_totalhigh = system.totalhigh; + m_freehigh = system.freehigh; +#else +#ifdef __GNUC__ +#warning "TODO: find alternative way to get total high and freehigh" +#endif +#endif + + m_totalswap = system.totalswap; + m_freeswap = system.freeswap; + m_procs = system.procs; + m_cacheram = 0; + + FILE *file = fopen("/proc/meminfo", "r"); + char buffer[70]; + if (file) { + while (fgets(buffer, sizeof(buffer), file)) { + sscanf(buffer, "Mem: %*d %*d %*d %*d %*d %lu", &m_cacheram); + if (m_cacheram != 0) + break; + } + + fclose(file); + } + + m_freeram = system.freeram; +#endif + +#ifdef __FreeBSD__ + struct timeval bootTime; + size_t size = sizeof(bootTime); + + if (sysctlbyname("kern.boottime", + &bootTime, &size, NULL, 0) != -1 && bootTime.tv_sec != 0) { + m_uptime = time(0) - bootTime.tv_sec + 30; + } + + char buf[80]; + char *used; + char *total; + FILE *pipe; + static int psize = 0, pshift = 0; + static int name2oid[2] = { 0, 3 }; + struct vmtotal vmt; + size_t vmtLength = sizeof(vmt); + static char name[] = "vfs.bufspace"; + static int oidBufspace[CTL_MAXNAME + 2]; + static size_t oidBufspaceLength = sizeof(oidBufspace); + size_t bufspaceLength = sizeof(int); + static int initialized = 0; + unsigned long memXUsed, memTotal; + size_t memLength = sizeof(memTotal); + + if (pshift == 0) { + psize = getpagesize(); + while (psize > 1) { + ++pshift; + psize >>= 1; + } + } + + unsigned long xused1, xused2; + size_t xused1Length = sizeof(xused1); + size_t xused2Length = sizeof(xused2); + if (sysctlbyname("vm.stats.vm.v_active_count", &xused1, &xused1Length, NULL, 0) == 0 + && sysctlbyname("vm.stats.vm.v_inactive_count", &xused2, &xused2Length, NULL, 0) == 0) { + memXUsed = (xused1 + xused2) << pshift; + } + + unsigned long cacheRam; + size_t cacheSize = sizeof(cacheRam); + if (sysctlbyname("vm.stats.vm.v_active_count", &cacheRam, &cacheSize, NULL, 0) == 0) { + m_cacheram = cacheRam << pshift; + } + + if (!m_totalram && sysctlbyname("hw.physmem", &memTotal, &memLength, NULL, 0) == 0) + m_totalram = memTotal; + + if (sysctlbyname("vm.meter", &vmt, &vmtLength, NULL, 0) == 0) + m_sharedram = vmt.t_rmshr << pshift; + + if (!initialized) { + if (sysctl(name2oid, 2, oidBufspace, &oidBufspaceLength, + name, strlen(name)) < 0) + return; + + oidBufspaceLength /= sizeof(int); + ++initialized; + } + + if (sysctl(oidBufspace, oidBufspaceLength, + &m_bufferram, &bufspaceLength, 0, 0) < 0) + return; + + m_usedram = memXUsed - m_bufferram - m_cacheram; + m_freeram = memTotal - m_usedram; + + //TODO: get the total and free high mem values + m_totalhigh = 0; + m_freehigh = 0; + + if ((pipe = popen("/usr/sbin/swapinfo -k", "r")) == 0) { + fprintf(stderr, "Error reading swap info\n"); + m_freeswap = m_totalswap = 1; + return; + } + + fgets(buf, sizeof(buf), pipe); + fgets(buf, sizeof(buf), pipe); + fgets(buf, sizeof(buf), pipe); + fgets(buf, sizeof(buf), pipe); + pclose(pipe); + + strtok(buf, " "); + total = strtok(NULL, " "); + used = strtok(NULL, " "); + unsigned long usedSwap = atol(used) * 1024; + + m_totalswap = atol(total) * 1024; + m_freeswap = m_totalswap - usedSwap; + + //TODO: get amount of procs + m_procs = 0; +#endif + +#ifdef HAVE_GETLOADAVG + double load[3]; + if (getloadavg(load, 3) != -1) { + m_loads[0] = load[0]; + m_loads[1] = load[1]; + m_loads[2] = load[2]; + } +#else +#warning "TODO: Find an alternative method for getloadavg" +#endif + + m_usedswap = m_totalswap - m_freeswap; +} diff --git a/ksim/systeminfo.h b/ksim/systeminfo.h new file mode 100644 index 0000000..39f5a73 --- /dev/null +++ b/ksim/systeminfo.h @@ -0,0 +1,137 @@ +/* System Information + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SYSTEMINFO_H +#define SYSTEMINFO_H + +class System +{ + public: + /** + * converts bytes to megabytes + */ + static int bytesToMegs( unsigned long ); + + /** + * @return a pointer to the instance + */ + static System & self(); + /** + * Deletes the instance and cleans up after itself + */ + static void cleanup(); + + /** + * @return the total amount of seconds + * the pc has been running + */ + long uptime() const { return m_uptime; } + /** + * @return the 3 load averages + */ + const double * loadAverages() const { return m_loads; } + /** + * this function does the same as the + * above but returns only the @ref load + * average + */ + double loadAverage( int ) const; + /** + * @return the total ram the system has + */ + unsigned long totalRam() const { return m_totalram; } + /** + * @return the total used ram + */ + unsigned long usedRam() const { return m_usedram; } + /** + * @return the total free ram the system has + */ + unsigned long freeRam() const { return m_freeram; } + /** + * @return the amount of shared + * memory in the system + */ + unsigned long sharedRam() const { return m_sharedram; } + /** + * @return the amount of buffered + * memory in the system + */ + unsigned long bufferRam() const { return m_bufferram; } + /** + * @return the amount of buffered + * memory in the system + */ + unsigned long cacheRam() const { return m_cacheram; } + /** + * @return the total amount of + * high memory + */ + unsigned long totalHigh() const { return m_totalhigh; } + /** + * @return the total amount of + * high free memory + */ + unsigned long freeHigh() const { return m_freehigh; } + /** + * @return the total amount of + * swap the system has + */ + unsigned long totalSwap() const { return m_totalswap; } + /** + * @return the total amount of + * swap used + */ + unsigned long usedSwap() const { return m_usedswap; } + /** + * @return the total amount of + * free swap the system has + */ + unsigned long freeSwap() const { return m_freeswap; } + /** + * @return the number of + * procs running + */ + unsigned short procs() const { return m_procs; } + + private: + System(); + System( const System & ); + System & operator=( const System & ); + ~System(); + + void updateData(); + + long m_uptime; // seconds since boot + double m_loads[3]; // 1, 5, and 15 minute load averages + unsigned long m_totalram; // Total usable main memory size + unsigned long m_usedram; // Used memory size + unsigned long m_freeram; // Available memory size + unsigned long m_sharedram; // Amount of shared memory + unsigned long m_bufferram; // Memory used by buffers + unsigned long m_cacheram; // Amount of cached ram + unsigned long m_totalhigh; // Total high memory size + unsigned long m_freehigh; // Available high memory size + unsigned long m_totalswap; // Total swap space size + unsigned long m_usedswap; // Used swap space size + unsigned long m_freeswap; // Swap space still available + unsigned short m_procs; // Number of current processes + static System * m_self; +}; +#endif diff --git a/ksim/themeprefs.cpp b/ksim/themeprefs.cpp new file mode 100644 index 0000000..3951f61 --- /dev/null +++ b/ksim/themeprefs.cpp @@ -0,0 +1,272 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "themeprefs.h" +#include "themeprefs.moc" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class ThemeViewItem : public KListViewItem +{ + public: + ThemeViewItem(QListView *parent, const QString &text, + const KURL &url) : KListViewItem(parent, text) + { + m_url = url; + } + + const KURL &url() const { return m_url; } + + private: + KURL m_url; +}; + +KSim::ThemePrefs::ThemePrefs(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + m_themeLayout = new QGridLayout(this); + m_themeLayout->setSpacing(6); + + m_label = new QLabel(this); + m_label->setText(i18n("GKrellm theme support. To use" + " gkrellm themes just untar the themes into the folder below")); + m_label->setAlignment(QLabel::WordBreak | + QLabel::AlignVCenter | QLabel::AlignLeft); + m_themeLayout->addMultiCellWidget(m_label, 0, 0, 0, 4); + + QString themeDir(locateLocal("data", "ksim")); + themeDir += QString::fromLatin1("/themes"); + + m_urlLabel = new KURLLabel(this); + m_urlLabel->setText(i18n("Open Konqueror in KSim's theme folder")); + m_urlLabel->setURL(QString::fromLatin1("file://") + themeDir); + connect(m_urlLabel, SIGNAL(leftClickedURL(const QString &)), + this, SLOT(openURL(const QString &))); + m_themeLayout->addMultiCellWidget(m_urlLabel, 1, 1, 0, 4); + + m_line = new KSeparator(Horizontal, this); + m_themeLayout->addMultiCellWidget(m_line, 2, 2, 0, 4); + + m_authorLabel = new QLabel(this); + m_authorLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, + QSizePolicy::Minimum)); + m_authorLabel->setText(i18n("Author:")); + m_themeLayout->addMultiCellWidget(m_authorLabel, 3, 3, 0, 0); + + m_authLabel = new KSqueezedTextLabel(this); + m_authLabel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Minimum)); + m_authLabel->setText(i18n("None")); + m_themeLayout->addMultiCellWidget(m_authLabel, 3, 3, 1, 4); + + m_listView = new KListView(this); + m_listView->addColumn(i18n("Theme")); + m_listView->setFullWidth(true); + connect(m_listView, SIGNAL(currentChanged(QListViewItem *)), + this, SLOT(selectItem(QListViewItem *))); + m_themeLayout->addMultiCellWidget(m_listView, 4, 4, 0, 4); + + m_alternateLabel = new QLabel(this); + m_alternateLabel->setText(i18n("Alternate themes:")); + m_alternateLabel->setAlignment(AlignVCenter | AlignRight); + m_themeLayout->addMultiCellWidget(m_alternateLabel, 5, 5, 0, 1); + + m_altTheme = new KIntSpinBox(this); + m_themeLayout->addMultiCellWidget(m_altTheme, 5, 5, 2, 2); + + m_fontLabel = new QLabel(this); + m_fontLabel->setText(i18n("Font:")); + m_fontLabel->setAlignment(AlignVCenter | AlignRight); + m_fontLabel->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, + QSizePolicy::Fixed)); + m_themeLayout->addMultiCellWidget(m_fontLabel, 5, 5, 3, 3); + + m_fontsCombo = new KComboBox(this); + m_fontsCombo->insertItem(i18n("Small")); + m_fontsCombo->insertItem(i18n("Normal")); + m_fontsCombo->insertItem(i18n("Large")); + m_fontsCombo->insertItem(i18n("Custom")); + m_fontsCombo->insertItem(i18n("Default")); + m_fontsCombo->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Fixed)); + connect(m_fontsCombo, SIGNAL(activated(int)), + this, SLOT(showFontDialog(int))); + m_themeLayout->addMultiCellWidget(m_fontsCombo, 5, 5, 4, 4); + + QStringList locatedFiles = KGlobal::dirs()->findDirs("data", "ksim/themes"); + for (QStringList::ConstIterator it = locatedFiles.begin(); it != locatedFiles.end(); ++it) + readThemes(*it); +} + +KSim::ThemePrefs::~ThemePrefs() +{ +} + +void KSim::ThemePrefs::saveConfig(KSim::Config *config) +{ + config->setThemeName(m_currentTheme.name); + config->setThemeAlt(m_altTheme->value()); + config->setThemeFontItem(m_fontsCombo->currentItem()); + config->setThemeFont(m_font); +} + +void KSim::ThemePrefs::readConfig(KSim::Config *config) +{ + setCurrentTheme(ThemeInfo(KSim::ThemeLoader::currentName(), + KURL( KSim::ThemeLoader::currentUrl() ), KSim::ThemeLoader::self().current().alternatives())); + m_altTheme->setValue(config->themeAlt()); + m_fontsCombo->setCurrentItem(config->themeFontItem()); + m_font = config->themeFont(); +} + +void KSim::ThemePrefs::setCurrentTheme(const ThemeInfo &theme) +{ + if (theme == m_currentTheme) + return; + + m_currentTheme = theme; + completed(); +} + +void KSim::ThemePrefs::setThemeAlts(int alternatives) +{ + m_currentTheme.alternatives = alternatives; + m_altTheme->setMaxValue(alternatives); + if (m_altTheme->value() > m_altTheme->maxValue()) + m_altTheme->setValue(m_altTheme->maxValue()); + + m_altTheme->setEnabled(alternatives == 0 ? false : true); + m_alternateLabel->setEnabled(alternatives == 0 ? false : true); +} + +void KSim::ThemePrefs::openURL(const QString &url) +{ + kapp->invokeBrowser(url); +} + +void KSim::ThemePrefs::insertItems(const ThemeInfoList &itemList) +{ + ThemeInfoList::ConstIterator it; + for (it = itemList.begin(); it != itemList.end(); ++it) { + (void) new ThemeViewItem(m_listView, (*it).name, (*it).url); + m_themeList.append((*it)); + } + + completed(); +} + +void KSim::ThemePrefs::clear() +{ + m_themeList.clear(); +} + +void KSim::ThemePrefs::completed() +{ + kdDebug(2003) << "Finished listing" << endl; + + for (QListViewItemIterator it(m_listView); it.current(); it++) + { + if (it.current()->text(0) == m_currentTheme.name) + { + m_listView->setSelected(it.current(), true); + m_listView->setCurrentItem(it.current()); + m_listView->ensureItemVisible(it.current()); + + selectItem( it.current() ); + break; + } + } +} + +void KSim::ThemePrefs::selectItem(QListViewItem *item) +{ + if (!item) + return; + + ThemeViewItem *themeItem = static_cast(item); + ThemeInfoList::ConstIterator it = qFind(m_themeList.begin(), + m_themeList.end(), ThemeInfo(themeItem->text(0), themeItem->url())); + + if (it == m_themeList.end()) + return; + + m_currentTheme = (*it); + + const KSim::Theme &theme(KSim::ThemeLoader::self().theme(m_currentTheme.url.path())); + if (theme.name() != "ksim") + KSim::ThemeLoader::self().parseDir(theme.path(), theme.alternatives()); + + QToolTip::remove(m_authLabel); + if (theme.author().isEmpty()) { + m_authLabel->setText(i18n("None Specified")); + QToolTip::add(m_authLabel, i18n("None specified")); + } + else { + m_authLabel->setText(theme.author()); + QToolTip::add(m_authLabel, theme.author()); + } + + kdDebug( 2003 ) << "theme.alternatives() = " << theme.alternatives() << endl; + setThemeAlts(theme.alternatives()); +} + +void KSim::ThemePrefs::readThemes(const QString &location) +{ + kdDebug(2003) << "readThemes(" << location << ")" << endl; + ThemeInfoList themeList; + QStringList items(QDir(location).entryList(QDir::Dirs, QDir::IgnoreCase)); + QStringList::ConstIterator it; + for (it = items.begin(); it != items.end(); ++it) { + if ((*it) != "." && (*it) != "..") + themeList.append(ThemeInfo((*it), KURL(location + (*it) + "/"))); + } + + insertItems(themeList); +} + +void KSim::ThemePrefs::showFontDialog(int currentItem) +{ + if (currentItem == 3) { + QFont customFont = m_font; + int result = KFontDialog::getFont(customFont); + if (result == KFontDialog::Accepted) + m_font = customFont; + } +} diff --git a/ksim/themeprefs.h b/ksim/themeprefs.h new file mode 100644 index 0000000..8ae569e --- /dev/null +++ b/ksim/themeprefs.h @@ -0,0 +1,115 @@ +/* ksim - a system monitor for kde + * + * Copyright (C) 2001 Robbie Ward + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef THEMEIMPL_H +#define THEMEIMPL_H + +#include +#include + +class QListViewItem; +class QGridLayout; +class QLabel; +class KListView; +class KURLLabel; +class KComboBox; +class KSqueezedTextLabel; +class KIntSpinBox; +class KSeparator; + +namespace KSim +{ + class Config; + + class ThemeInfo + { + public: + ThemeInfo() : name(0), url(0), alternatives(0) {} + ThemeInfo(const QString &name, const KURL &url, int alts=0) + : name(name), url(url), alternatives(alts) {} + + bool operator==(const ThemeInfo &rhs) const + { + return (rhs.name == name && rhs.url == url + && rhs.alternatives == alternatives); + } + + bool operator!=(const ThemeInfo &rhs) const + { + return !(operator==(rhs)); + } + + ThemeInfo &operator=(const ThemeInfo &rhs) + { + if (*this == rhs) + return *this; + + name = rhs.name; + url = rhs.url; + alternatives = rhs.alternatives; + return *this; + } + + QString name; + KURL url; + int alternatives; + }; + + typedef QValueList ThemeInfoList; + + class ThemePrefs : public QWidget + { + Q_OBJECT + public: + ThemePrefs(QWidget *parent, const char *name=0); + ~ThemePrefs(); + + public slots: + void saveConfig(KSim::Config *); + void readConfig(KSim::Config *); + + private slots: + void setCurrentTheme(const ThemeInfo &); + void setThemeAlts(int); + void openURL(const QString &); + void insertItems(const ThemeInfoList &); + void clear(); + void completed(); + void selectItem(QListViewItem *item); + void readThemes(const QString &); + void showFontDialog(int); + + private: + KListView *m_listView; + KURLLabel *m_urlLabel; + KIntSpinBox *m_altTheme; + KComboBox *m_fontsCombo; + QLabel *m_label; + QLabel *m_authorLabel; + KSqueezedTextLabel *m_authLabel; + QLabel *m_alternateLabel; + QLabel *m_fontLabel; + KSeparator *m_line; + ThemeInfo m_currentTheme; + QFont m_font; + ThemeInfoList m_themeList; + QGridLayout *m_themeLayout; + }; +} +#endif diff --git a/ksim/themes/Makefile.am b/ksim/themes/Makefile.am new file mode 100644 index 0000000..ccdc199 --- /dev/null +++ b/ksim/themes/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = ksim diff --git a/ksim/themes/ksim/Makefile.am b/ksim/themes/ksim/Makefile.am new file mode 100644 index 0000000..44b0dca --- /dev/null +++ b/ksim/themes/ksim/Makefile.am @@ -0,0 +1,24 @@ +theme_images = bg_grid.png \ + bg_panel.png \ + krell_meter.png \ + krell_slider.png \ + bg_chart.png \ + bg_meter.png \ + gkrellmrc \ + gkrellmrc_ksim \ + krell_panel.png \ + frame_top.png \ + frame_bottom.png \ + frame_left.png \ + frame_right.png + +net_images = decal_net_leds.png + +EXTRA_DIST = $(theme_images) $(net_images) +SUBDIRS = host mail + +theme_DATA = $(theme_images) +themedir = $(kde_datadir)/ksim/themes/ksim + +net_DATA = $(net_images) +netdir = $(kde_datadir)/ksim/themes/ksim/net diff --git a/ksim/themes/ksim/bg_chart.png b/ksim/themes/ksim/bg_chart.png new file mode 100644 index 0000000..e193b2b Binary files /dev/null and b/ksim/themes/ksim/bg_chart.png differ diff --git a/ksim/themes/ksim/bg_grid.png b/ksim/themes/ksim/bg_grid.png new file mode 100644 index 0000000..3d971e6 Binary files /dev/null and b/ksim/themes/ksim/bg_grid.png differ diff --git a/ksim/themes/ksim/bg_meter.png b/ksim/themes/ksim/bg_meter.png new file mode 100644 index 0000000..e49f839 Binary files /dev/null and b/ksim/themes/ksim/bg_meter.png differ diff --git a/ksim/themes/ksim/bg_panel.png b/ksim/themes/ksim/bg_panel.png new file mode 100644 index 0000000..2582eaf Binary files /dev/null and b/ksim/themes/ksim/bg_panel.png differ diff --git a/ksim/themes/ksim/decal_net_leds.png b/ksim/themes/ksim/decal_net_leds.png new file mode 100644 index 0000000..b8990c0 Binary files /dev/null and b/ksim/themes/ksim/decal_net_leds.png differ diff --git a/ksim/themes/ksim/frame_bottom.png b/ksim/themes/ksim/frame_bottom.png new file mode 100644 index 0000000..f23d03f Binary files /dev/null and b/ksim/themes/ksim/frame_bottom.png differ diff --git a/ksim/themes/ksim/frame_left.png b/ksim/themes/ksim/frame_left.png new file mode 100644 index 0000000..a7d1009 Binary files /dev/null and b/ksim/themes/ksim/frame_left.png differ diff --git a/ksim/themes/ksim/frame_right.png b/ksim/themes/ksim/frame_right.png new file mode 100644 index 0000000..63b0e7a Binary files /dev/null and b/ksim/themes/ksim/frame_right.png differ diff --git a/ksim/themes/ksim/frame_top.png b/ksim/themes/ksim/frame_top.png new file mode 100644 index 0000000..ad3cc3e Binary files /dev/null and b/ksim/themes/ksim/frame_top.png differ diff --git a/ksim/themes/ksim/gkrellmrc b/ksim/themes/ksim/gkrellmrc new file mode 100644 index 0000000..dc44c93 --- /dev/null +++ b/ksim/themes/ksim/gkrellmrc @@ -0,0 +1,47 @@ +author = Robbie Ward + +# krell_meter.png taken from ShinyAll2 + +frame_top_height = 2 +frame_bottom_height = 2 +frame_left_width = 2 +frame_right_width = 2 + +chart_in_color = #7B9DDE +chart_in_color_grid = gray20 +chart_out_color = #CDE2FF +chart_out_color_grid = gray20 + +bg_grid_mode = 1 + +normal_font = -adobe-helvetica-medium-r-normal-*-*-100-*-*-p-*-iso8859-1 +large_font = -adobe-helvetica-medium-r-normal-*-*-120-*-*-p-*-iso8859-1 +small_font = -adobe-helvetica-medium-r-normal-*-*-80-*-*-p-*-iso8859-1 + +rx_led_x = 2 +rx_led_y = 3 +tx_led_x = -2 +tx_led_y = 3 + +decal_mail_frames = 18 +decal_mail_delay = 1 + +timer_time_x = 2 +timer_button_x = -2 + +krell_slider_x_hot = 1 + +StyleChart *.border = 2,2,2,2 +StyleChart *.textcolor = black white shadow + +StylePanel *.border = 2,2,2,2 +StylePanel *.textcolor = black white shadow +StylePanel *.label_position = 50 +StylePanel *.krell_depth = 4 + +StyleMeter *.border = 2,2,2,2 +StyleMeter *.textcolor = black white shadow +StyleMeter *.label_position = 50 +StyleMeter fs.label_position = 0 +StyleMeter cal.font = large_font +StyleMeter clock.font = large_font diff --git a/ksim/themes/ksim/gkrellmrc_ksim b/ksim/themes/ksim/gkrellmrc_ksim new file mode 100644 index 0000000..dc44c93 --- /dev/null +++ b/ksim/themes/ksim/gkrellmrc_ksim @@ -0,0 +1,47 @@ +author = Robbie Ward + +# krell_meter.png taken from ShinyAll2 + +frame_top_height = 2 +frame_bottom_height = 2 +frame_left_width = 2 +frame_right_width = 2 + +chart_in_color = #7B9DDE +chart_in_color_grid = gray20 +chart_out_color = #CDE2FF +chart_out_color_grid = gray20 + +bg_grid_mode = 1 + +normal_font = -adobe-helvetica-medium-r-normal-*-*-100-*-*-p-*-iso8859-1 +large_font = -adobe-helvetica-medium-r-normal-*-*-120-*-*-p-*-iso8859-1 +small_font = -adobe-helvetica-medium-r-normal-*-*-80-*-*-p-*-iso8859-1 + +rx_led_x = 2 +rx_led_y = 3 +tx_led_x = -2 +tx_led_y = 3 + +decal_mail_frames = 18 +decal_mail_delay = 1 + +timer_time_x = 2 +timer_button_x = -2 + +krell_slider_x_hot = 1 + +StyleChart *.border = 2,2,2,2 +StyleChart *.textcolor = black white shadow + +StylePanel *.border = 2,2,2,2 +StylePanel *.textcolor = black white shadow +StylePanel *.label_position = 50 +StylePanel *.krell_depth = 4 + +StyleMeter *.border = 2,2,2,2 +StyleMeter *.textcolor = black white shadow +StyleMeter *.label_position = 50 +StyleMeter fs.label_position = 0 +StyleMeter cal.font = large_font +StyleMeter clock.font = large_font diff --git a/ksim/themes/ksim/host/Makefile.am b/ksim/themes/ksim/host/Makefile.am new file mode 100644 index 0000000..d6e8739 --- /dev/null +++ b/ksim/themes/ksim/host/Makefile.am @@ -0,0 +1,4 @@ +EXTRA_DIST = bg_meter.png +host_DATA = bg_meter.png + +hostdir = $(kde_datadir)/ksim/themes/ksim/host diff --git a/ksim/themes/ksim/host/bg_meter.png b/ksim/themes/ksim/host/bg_meter.png new file mode 100644 index 0000000..538c560 Binary files /dev/null and b/ksim/themes/ksim/host/bg_meter.png differ diff --git a/ksim/themes/ksim/krell_meter.png b/ksim/themes/ksim/krell_meter.png new file mode 100644 index 0000000..2222fb0 Binary files /dev/null and b/ksim/themes/ksim/krell_meter.png differ diff --git a/ksim/themes/ksim/krell_panel.png b/ksim/themes/ksim/krell_panel.png new file mode 100644 index 0000000..e9a7c8f Binary files /dev/null and b/ksim/themes/ksim/krell_panel.png differ diff --git a/ksim/themes/ksim/krell_slider.png b/ksim/themes/ksim/krell_slider.png new file mode 100644 index 0000000..5ce131d Binary files /dev/null and b/ksim/themes/ksim/krell_slider.png differ diff --git a/ksim/themes/ksim/mail/Makefile.am b/ksim/themes/ksim/mail/Makefile.am new file mode 100644 index 0000000..ea1fa28 --- /dev/null +++ b/ksim/themes/ksim/mail/Makefile.am @@ -0,0 +1,3 @@ +pics_DATA = decal_mail.png krell_mail_daemon.png krell_mail.png + +picsdir = $(kde_datadir)/ksim/themes/ksim/mail diff --git a/ksim/themes/ksim/mail/decal_mail.png b/ksim/themes/ksim/mail/decal_mail.png new file mode 100644 index 0000000..53576df Binary files /dev/null and b/ksim/themes/ksim/mail/decal_mail.png differ diff --git a/ksim/themes/ksim/mail/krell_mail.png b/ksim/themes/ksim/mail/krell_mail.png new file mode 100644 index 0000000..c92d426 Binary files /dev/null and b/ksim/themes/ksim/mail/krell_mail.png differ diff --git a/ksim/themes/ksim/mail/krell_mail_daemon.png b/ksim/themes/ksim/mail/krell_mail_daemon.png new file mode 100644 index 0000000..18eb051 Binary files /dev/null and b/ksim/themes/ksim/mail/krell_mail_daemon.png differ diff --git a/ktimer/Makefile.am b/ktimer/Makefile.am new file mode 100644 index 0000000..35d6283 --- /dev/null +++ b/ktimer/Makefile.am @@ -0,0 +1,24 @@ +INCLUDES = $(all_includes) +AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) +LDADD = $(LIB_KDEUI) $(LIB_KFILE) + +bin_PROGRAMS = ktimer + +METASOURCES = AUTO + +ktimer_SOURCES = main.cpp ktimer.cpp prefwidget.ui +# ktimer.cpp pref.cpp +noinst_HEADERS = ktimer.h + +KDE_ICON = ktimer + +xdg_apps_DATA = ktimer.desktop + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/ktimer.pot + + +srcdoc: + kdoc -a -p -H -d $$HOME/web/src/ktimer ktimer *.h -lkdecore -lkdeui -lqt + + diff --git a/ktimer/hi128-app-ktimer.png b/ktimer/hi128-app-ktimer.png new file mode 100644 index 0000000..692b050 Binary files /dev/null and b/ktimer/hi128-app-ktimer.png differ diff --git a/ktimer/hi16-app-ktimer.png b/ktimer/hi16-app-ktimer.png new file mode 100644 index 0000000..dca2c7e Binary files /dev/null and b/ktimer/hi16-app-ktimer.png differ diff --git a/ktimer/hi32-app-ktimer.png b/ktimer/hi32-app-ktimer.png new file mode 100644 index 0000000..0f93b36 Binary files /dev/null and b/ktimer/hi32-app-ktimer.png differ diff --git a/ktimer/hi48-app-ktimer.png b/ktimer/hi48-app-ktimer.png new file mode 100644 index 0000000..b974797 Binary files /dev/null and b/ktimer/hi48-app-ktimer.png differ diff --git a/ktimer/ktimer.cpp b/ktimer/ktimer.cpp new file mode 100644 index 0000000..2b1b1c8 --- /dev/null +++ b/ktimer/ktimer.cpp @@ -0,0 +1,516 @@ +/* + * (c) 2001 Stefan Schimanski <1Stein@gmx.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ktimer.h" +#include + + +class KTimerJobItem : public QListViewItem { +public: + KTimerJobItem( KTimerJob *job, QListView *parent ) + : QListViewItem( parent ) { + m_job = job; + m_error = false; + update(); + }; + + KTimerJobItem( KTimerJob *job, QListView *parent, QListViewItem *after ) + : QListViewItem( parent, after ) { + m_job = job; + m_error = false; + update(); + }; + + virtual ~KTimerJobItem() { + delete m_job; + }; + + KTimerJob *job() { return m_job; }; + + void setStatus( bool error ) { + m_error = error; + update(); + } + + void update() { + setText( 0, QString::number(m_job->value()) ); + + if( m_error ) + setPixmap( 0, SmallIcon("stop") ); + else + setPixmap( 0, QPixmap() ); + + setText( 1, QString::number(m_job->delay()) ); + + switch( m_job->state() ) { + case KTimerJob::Stopped: setPixmap( 2, SmallIcon("player_stop") ); break; + case KTimerJob::Paused: setPixmap( 2, SmallIcon("player_pause") ); break; + case KTimerJob::Started: setPixmap( 2, SmallIcon("1rightarrow") ); break; + } + + setText( 3, m_job->command() ); + }; + +private: + bool m_error; + KTimerJob *m_job; +}; + + +/***************************************************************/ + + +struct KTimerPrefPrivate +{ + QPtrList jobs; +}; + +KTimerPref::KTimerPref( QWidget *parent, const char *name ) + : PrefWidget( parent, name ) +{ + d = new KTimerPrefPrivate; + + d->jobs.setAutoDelete( true ); + + // set icons + m_stop->setIconSet( SmallIconSet("player_stop") ); + m_pause->setIconSet( SmallIconSet("player_pause") ); + m_start->setIconSet( SmallIconSet("1rightarrow") ); + + // create tray icon + KSystemTray *tray = new KSystemTray( this, "TimerTray" ); + tray->show(); + tray->setPixmap( SmallIcon( "ktimer" ) ); + + // connect + connect( m_add, SIGNAL(clicked()), SLOT(add()) ); + connect( m_remove, SIGNAL(clicked()), SLOT(remove()) ); + connect( m_list, SIGNAL(currentChanged(QListViewItem*)), + SLOT(currentChanged(QListViewItem*)) ); + loadJobs( kapp->config() ); + + show(); +} + + +KTimerPref::~KTimerPref() +{ + saveJobs( kapp->config() ); + delete d; +} + + +void KTimerPref::add() +{ + KTimerJob *job = new KTimerJob; + KTimerJobItem *item = new KTimerJobItem( job, m_list ); + + connect( job, SIGNAL(delayChanged(KTimerJob*,unsigned)), + SLOT(jobChanged(KTimerJob*)) ); + connect( job, SIGNAL(valueChanged(KTimerJob*,unsigned)), + SLOT(jobChanged(KTimerJob*)) ); + connect( job, SIGNAL(stateChanged(KTimerJob*,States)), + SLOT(jobChanged(KTimerJob*)) ); + connect( job, SIGNAL(commandChanged(KTimerJob*,const QString&)), + SLOT(jobChanged(KTimerJob*)) ); + connect( job, SIGNAL(finished(KTimerJob*,bool)), + SLOT(jobFinished(KTimerJob*,bool)) ); + + job->setUser( item ); + + // Qt drops currentChanged signals on first item (bug?) + if( m_list->childCount()==1 ) + currentChanged( item ); + + m_list->setCurrentItem( item ); + m_list->triggerUpdate(); +} + + +void KTimerPref::remove() +{ + delete m_list->currentItem(); + m_list->triggerUpdate(); +} + + +void KTimerPref::currentChanged( QListViewItem *i ) +{ + KTimerJobItem *item = static_cast(i); + if( item ) { + KTimerJob *job = item->job(); + + m_state->setEnabled( true ); + m_settings->setEnabled( true ); + m_remove->setEnabled( true ); + + m_delay->disconnect(); + m_loop->disconnect(); + m_one->disconnect(); + m_start->disconnect(); + m_pause->disconnect(); + m_stop->disconnect(); + m_counter->disconnect(); + m_slider->disconnect(); + + connect( m_commandLine->lineEdit(), SIGNAL(textChanged(const QString &)), + job, SLOT(setCommand(const QString &)) ); + connect( m_delay, SIGNAL(valueChanged(int)), + job, SLOT(setDelay(int)) ); + connect( m_loop, SIGNAL(toggled(bool)), + job, SLOT(setLoop(bool)) ); + connect( m_one, SIGNAL(toggled(bool)), + job, SLOT(setOneInstance(bool)) ); + connect( m_stop, SIGNAL(clicked()), + job, SLOT(stop()) ); + connect( m_pause, SIGNAL(clicked()), + job, SLOT(pause()) ); + connect( m_start, SIGNAL(clicked()), + job, SLOT(start()) ); + connect( m_slider, SIGNAL(valueChanged(int)), + job, SLOT(setValue(int)) ); + + m_commandLine->lineEdit()->setText( job->command() ); + m_delay->setValue( job->delay() ); + m_loop->setChecked( job->loop() ); + m_one->setChecked( job->oneInstance() ); + m_counter->display( (int)job->value() ); + m_slider->setMaxValue( job->delay() ); + m_slider->setValue( job->value() ); + + } else { + m_state->setEnabled( false ); + m_settings->setEnabled( false ); + m_remove->setEnabled( false ); + } +} + + +void KTimerPref::jobChanged( KTimerJob *job ) +{ + KTimerJobItem *item = static_cast(job->user()); + if( item ) { + item->update(); + m_list->triggerUpdate(); + + if( item==m_list->currentItem() ) { + + // XXX optimize + m_slider->setMaxValue( job->delay() ); + m_slider->setValue( job->value() ); + m_counter->display( (int)job->value() ); + } + } +} + + +void KTimerPref::jobFinished( KTimerJob *job, bool error ) +{ + KTimerJobItem *item = static_cast(job->user()); + item->setStatus( error ); + m_list->triggerUpdate(); +} + + +void KTimerPref::saveJobs( KConfig *cfg ) +{ + int num = 0; + KTimerJobItem *item = static_cast(m_list->firstChild()); + while( item ) { + item->job()->save( cfg, QString("Job%1").arg( num ) ); + item = static_cast(item->nextSibling()); + num++; + } + + cfg->setGroup( "Jobs" ); + cfg->writeEntry( "Number", num ); + + cfg->sync(); +} + + +void KTimerPref::loadJobs( KConfig *cfg ) +{ + cfg->setGroup( "Jobs" ); + int num = cfg->readNumEntry( "Number", 0 ); + for( int n=0; nload( cfg, QString( "Job%1" ).arg(n) ); + + job->setUser( item ); + } + + m_list->triggerUpdate(); +} + + +/*********************************************************************/ + + +struct KTimerJobPrivate { + unsigned delay; + QString command; + bool loop; + bool oneInstance; + unsigned value; + KTimerJob::States state; + QPtrList processes; + void *user; + + QTimer *timer; +}; + + +KTimerJob::KTimerJob( QObject *parent, const char *name ) + : QObject( parent, name ) +{ + d = new KTimerJobPrivate; + + d->delay = 100; + d->loop = false; + d->oneInstance = true; + d->value = 100; + d->state = Stopped; + d->processes.setAutoDelete( true ); + d->user = 0; + + d->timer = new QTimer( this ); + connect( d->timer, SIGNAL(timeout()), SLOT(timeout()) ); +} + + +KTimerJob::~KTimerJob() +{ + delete d; +} + + +void KTimerJob::load( KConfig *cfg, const QString& grp ) +{ + cfg->setGroup( grp ); + cfg->writeEntry( "Delay", d->delay ); + cfg->writePathEntry( "Command", d->command ); + cfg->writeEntry( "Loop", d->loop ); + cfg->writeEntry( "OneInstance", d->oneInstance ); + cfg->writeEntry( "State", (int)d->state ); +} + + +void KTimerJob::save( KConfig *cfg, const QString& grp ) +{ + cfg->setGroup( grp ); + setDelay( cfg->readNumEntry( "Delay", 100 ) ); + setCommand( cfg->readPathEntry( "Command" ) ); + setLoop( cfg->readBoolEntry( "Loop", false ) ); + setOneInstance( cfg->readBoolEntry( "OneInstance", d->oneInstance ) ); + setState( (States)cfg->readNumEntry( "State", (int)Stopped ) ); +} + + +void *KTimerJob::user() +{ + return d->user; +} + + +void KTimerJob::setUser( void *user ) +{ + d->user = user; +} + + +unsigned KTimerJob::delay() +{ + return d->delay; +} + + +void KTimerJob::setDelay( unsigned sec ) +{ + if( d->delay!=sec ) { + d->delay = sec; + + if( d->state==Stopped ) + setValue( sec ); + + emit delayChanged( this, sec ); + emit changed( this ); + } +} + + +QString KTimerJob::command() +{ + return d->command; +} + + +void KTimerJob::setCommand( const QString &cmd ) +{ + if( d->command!=cmd ) { + d->command = cmd; + emit commandChanged( this, cmd ); + emit changed( this ); + } +} + + +bool KTimerJob::loop() +{ + return d->loop; +} + + +void KTimerJob::setLoop( bool loop ) +{ + if( d->loop!=loop ) { + d->loop = loop; + emit loopChanged( this, loop ); + emit changed( this ); + } +} + + +bool KTimerJob::oneInstance() +{ + return d->oneInstance; +} + + +void KTimerJob::setOneInstance( bool one ) +{ + if( d->oneInstance!=one ) { + d->oneInstance = one; + emit oneInstanceChanged( this, one ); + emit changed( this ); + } +} + + +unsigned KTimerJob::value() +{ + return d->value; +} + + +void KTimerJob::setValue( unsigned value ) +{ + if( d->value!=value ) { + d->value = value; + emit valueChanged( this, value ); + emit changed( this ); + } +} + + +KTimerJob::States KTimerJob::state() +{ + return d->state; +} + + +void KTimerJob::setState( KTimerJob::States state ) +{ + if( d->state!=state ) { + if( state==Started ) + d->timer->start( 1000 ); + else + d->timer->stop(); + + if( state==Stopped ) + setValue( d->delay ); + + d->state = state; + emit stateChanged( this, state ); + emit changed( this ); + } +} + + +void KTimerJob::timeout() +{ + if( d->state==Started && d->value!=0 ) { + setValue( d->value-1 ); + if( d->value==0 ) { + fire(); + if( d->loop ) + setValue( d->delay ); + else + stop(); + } + } +} + + +void KTimerJob::processExited(KProcess *proc) +{ + bool ok = proc->exitStatus()==0; + d->processes.remove( proc ); + if( !ok ) emit error( this ); + emit finished( this, !ok ); +} + + +void KTimerJob::fire() +{ + if( !d->oneInstance || d->processes.isEmpty() ) { + KShellProcess *proc = new KShellProcess; + (*proc) << d->command; + d->processes.append( proc ); + connect( proc, SIGNAL(processExited(KProcess*)), + SLOT(processExited(KProcess*)) ); + bool ok = proc->start( KProcess::NotifyOnExit ); + emit fired( this ); + if( !ok ) { + d->processes.remove( proc ); + emit error( this ); + emit finished( this, true ); + } + } +} +#include "ktimer.moc" diff --git a/ktimer/ktimer.desktop b/ktimer/ktimer.desktop new file mode 100644 index 0000000..d34c43b --- /dev/null +++ b/ktimer/ktimer.desktop @@ -0,0 +1,63 @@ +[Desktop Entry] +GenericName=Countdown Launcher +GenericName[ar]=بادئ العدّ التنازلى +GenericName[bg]=Хронометър +GenericName[ca]=Llançador amb compte enrere +GenericName[cs]=Stopky +GenericName[cy]=Cychwynydd Cyfrif yn Ôl +GenericName[da]=Nedtællingsstarter +GenericName[de]=Startet den Zähler +GenericName[el]=Αντίστροφη μέτρηση για την ενεργοποίηση λογισμικού +GenericName[es]=Lanzador de cuenta atrás +GenericName[et]=Ajaarvestuse käivitaja +GenericName[eu]=Atzekoz aurrera zenbaketa jaurtitzen du +GenericName[fa]=راه‌انداز شمارش معکوس +GenericName[fi]=Lähtölaskenta +GenericName[fr]=Lanceur de compte à rebours +GenericName[hu]=Visszaszámláló +GenericName[is]=Niðurteljari +GenericName[it]=Conto alla rovescia +GenericName[ja]=起動マネージャ +GenericName[kk]=Кері санақ +GenericName[km]=កម្មវិធី​បើក​រហ័ស​របស់​កម្មវិធី​រាប់ថតក្រោយ +GenericName[lt]=Laiko skaičiuoklė +GenericName[nb]=Beskjedverktøy +GenericName[nds]=Teller starten +GenericName[ne]=काउन्टडाउन आरम्भकर्ता +GenericName[nn]=Nedteljing +GenericName[pl]=Odliczanie +GenericName[pt]=Contagem Decrescente +GenericName[pt_BR]=Abre a contador de tempo +GenericName[ro]=Cronometru +GenericName[ru]=Обратный отсчёт +GenericName[sk]=Odpočítavané spúšťanie +GenericName[sl]=Zaganjalec odštevanja +GenericName[sr]=Лансер одбројавања +GenericName[sr@Latn]=Lanser odbrojavanja +GenericName[sv]=Nerräknande startprogram +GenericName[ta]= குறிப்பு எடுப்பான் நேரக்குறைப்பான் +GenericName[tr]=Gerisayım Çalıştırıcı +GenericName[uk]=Таймер +GenericName[zh_CN]=倒计时 +GenericName[zh_TW]=倒數發射計時 +Exec=ktimer +Icon=ktimer +Type=Application +Terminal=false +Name=KTimer +Name[af]=Ktimer +Name[eo]=Tempoplanilo +Name[hi]=के-टाइमर +Name[lv]=KTaimers +Name[ne]=केडीई समय सूचक +Name[pl]=Czasomierz +Name[sv]=Ktimer +Name[ta]= Kநேரம் காட்டி +Name[tg]=KВақтсанҷ +Name[th]=ตั้งเวลาทำงาน +Name[ven]=Ratshikhathi wa K +Name[xh]=Umjongi Wexesha +Name[zh_TW]=KDE 計時器 +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Utility;X-KDE-More; diff --git a/ktimer/ktimer.h b/ktimer/ktimer.h new file mode 100644 index 0000000..3b7c406 --- /dev/null +++ b/ktimer/ktimer.h @@ -0,0 +1,113 @@ +/* + * (c) 2001 Stefan Schimanski <1Stein@gmx.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KTIMER_H_INCLUDED +#define KTIMER_H_INCLUDED + +#include +#include +#include +#include + +#include "prefwidget.h" + + +class KTimerJob : public QObject { + Q_OBJECT + + public: + KTimerJob( QObject *parent=0, const char *name=0 ); + virtual ~KTimerJob(); + + enum States { Stopped, Paused, Started }; + + unsigned delay(); + QString command(); + bool loop(); + bool oneInstance(); + unsigned value(); + States state(); + void *user(); + void setUser( void *user ); + + void load( KConfig *cfg, const QString& grp ); + void save( KConfig *cfg, const QString& grp ); + + public slots: + void setDelay( unsigned sec ); + void setDelay( int sec ) { setDelay( (unsigned)sec ); }; + void setCommand( const QString &cmd ); + void setLoop( bool loop ); + void setOneInstance( bool one ); + void setValue( unsigned value ); + void setValue( int value ) { setValue( (unsigned)value ); }; + void setState( States state ); + + void pause() { setState( Paused ); } + void stop() { setState( Stopped ); } + void start() { setState( Started ); } + + signals: + void stateChanged( KTimerJob *job, States state ); + void delayChanged( KTimerJob *job, unsigned sec ); + void commandChanged( KTimerJob *job, const QString &cmd ); + void loopChanged( KTimerJob *job, bool loop ); + void oneInstanceChanged( KTimerJob *job, bool one ); + void valueChanged( KTimerJob *job, unsigned value ); + + void changed( KTimerJob *job ); + void fired( KTimerJob *job ); + void finished( KTimerJob *job, bool error ); + void error( KTimerJob *job ); + + protected slots: + virtual void fire(); + + private slots: + void timeout(); + void processExited(KProcess *proc); + + private: + struct KTimerJobPrivate *d; +}; + + +class KTimerPref : public PrefWidget +{ + Q_OBJECT + public: + KTimerPref( QWidget *parent=0, const char *name = 0 ); + virtual ~KTimerPref(); + + protected slots: + void add(); + void remove(); + void currentChanged( QListViewItem * ); + + void saveJobs( KConfig *cfg ); + void loadJobs( KConfig *cfg ); + + private slots: + void jobChanged( KTimerJob *job ); + void jobFinished( KTimerJob *job, bool error ); + + private: + struct KTimerPrefPrivate *d; +}; + +#endif diff --git a/ktimer/main.cpp b/ktimer/main.cpp new file mode 100644 index 0000000..1deb4ac --- /dev/null +++ b/ktimer/main.cpp @@ -0,0 +1,46 @@ +/* + * (c) 2001 Stefan Schimanski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "ktimer.h" + +static const char description[] = + I18N_NOOP("KDE Timer"); + +static const char version[] = "v0.1"; + +int main( int argc, char **argv ) +{ + KAboutData aboutData( "ktimer", I18N_NOOP("KTimer"), + version, description, KAboutData::License_GPL, + "(c) 2001, Stefan Schimanski"); + aboutData.addAuthor("Stefan Schimanski",0, "schimmi@kde.org"); + KCmdLineArgs::init( argc, argv, &aboutData ); + + KApplication app; + + KTimerPref *timer = new KTimerPref; + app.setMainWidget( timer ); + app.setTopWidget( timer ); + + return app.exec(); +} diff --git a/ktimer/prefwidget.ui b/ktimer/prefwidget.ui new file mode 100644 index 0000000..15cee2b --- /dev/null +++ b/ktimer/prefwidget.ui @@ -0,0 +1,278 @@ + +PrefWidget + + + PrefWidget + + + + 0 + 0 + 479 + 344 + + + + Timer Settings + + + + unnamed + + + 11 + + + 6 + + + + + Counter [s] + + + true + + + true + + + + + Delay [s] + + + true + + + true + + + + + State + + + true + + + true + + + + + Command + + + true + + + true + + + + m_list + + + true + + + + + m_add + + + &New + + + + + m_remove + + + false + + + &Remove + + + + + Spacer4 + + + Vertical + + + Expanding + + + + 20 + 20 + + + + + + m_settings + + + false + + + Settings + + + + unnamed + + + 11 + + + 6 + + + + m_loop + + + &Loop + + + + + TextLabel2 + + + Delay: + + + + + m_delay + + + 99999 + + + + + m_one + + + Start only &one instance + + + + + TextLabel3 + + + seconds + + + + + Spacer1 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + m_commandLine + + + + + TextLabel1 + + + Command line: + + + + + + + m_state + + + false + + + State + + + + unnamed + + + 11 + + + 6 + + + + m_slider + + + Horizontal + + + + + m_counter + + + + + m_pause + + + || + + + + + m_start + + + > + + + + + m_stop + + + = + + + + + + + + kseparator.h + + + + kurlrequester.h + klineedit.h + kpushbutton.h + + diff --git a/kwallet/Makefile.am b/kwallet/Makefile.am new file mode 100644 index 0000000..5c5fe28 --- /dev/null +++ b/kwallet/Makefile.am @@ -0,0 +1,26 @@ +INCLUDES= $(all_includes) + +SUBDIRS=. icons konfigurator + +bin_PROGRAMS = kwalletmanager +kwalletmanager_SOURCES = walletwidget.ui kwalletmanager.cpp \ + kwalletmanager.skel main.cpp kwalletpopup.cpp \ + kwalleteditor.cpp kwmapeditor.cpp allyourbase.cpp \ + kbetterthankdialogbase.ui +kwalletmanager_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kwalletmanager_LDADD = $(LIB_KIO) -lkwalletclient +METASOURCES = AUTO +noinst_HEADERS = kwalletmanager.h kwalletpopup.h walletwidget.h kwalleteditor.h\ + allyourbase.h kwmapeditor.h + +xdg_apps_DATA = kwalletmanager.desktop kwalletmanager-kwalletd.desktop + +KDE_ICON = kwalletmanager + +rc_DATA = kwalletmanager.rc kwalleteditor.rc +rcdir = $(kde_datadir)/kwalletmanager + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kwalletmanager.pot + +kbetterthankdialogbase.lo: kbetterthankdialogbase.ui kbetterthankdialogbase.ui.h diff --git a/kwallet/TODO b/kwallet/TODO new file mode 100644 index 0000000..145fa7b --- /dev/null +++ b/kwallet/TODO @@ -0,0 +1,13 @@ +Things left: + +Backend: +- test 64 bit, zSeries +- refactor the hashes to make it efficient + +Integration: +- Cookie jar +- KMail + +Future ideas: +- Make it a kpart + diff --git a/kwallet/allyourbase.cpp b/kwallet/allyourbase.cpp new file mode 100644 index 0000000..add178b --- /dev/null +++ b/kwallet/allyourbase.cpp @@ -0,0 +1,733 @@ +/* + Copyright (C) 2003-2005 George Staikos + Copyright (C) 2005 Isaac Clerencia + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "allyourbase.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/**************** + * KWalletFolderItem - ListView items to represent kwallet folders + */ +KWalletFolderItem::KWalletFolderItem(KWallet::Wallet *w, QListView* parent, const QString &name, int entries) +: KListViewItem(parent),_wallet(w),_name(name),_entries(entries) { + setText(0, QString("%1 (%2)").arg(_name).arg(_entries)); + setRenameEnabled(0, false); + setDragEnabled(true); + setDropEnabled(true); + + QPixmap pix = getFolderIcon(KIcon::Small); + + setPixmap(0,pix); +} + +QPixmap KWalletFolderItem::getFolderIcon(KIcon::Group group){ + KIconLoader *loader = KGlobal::instance()->iconLoader(); + QPixmap pix = loader->loadIcon( _name, group, 0, + KIcon::DefaultState, 0, true ); + if (pix.isNull()) + pix = loader->loadIcon( _name.lower(), group, 0, + KIcon::DefaultState, 0, true); + if (pix.isNull()) + pix = loader->loadIcon( "folder_red", group, 0, + KIcon::DefaultState, 0, true); + return pix; +} + +void KWalletFolderItem::refresh() { + QString saveFolder = _wallet->currentFolder(); + _wallet->setFolder(_name); + setText(0, QString("%1 (%2)").arg(_name).arg(_wallet->entryList().count())); + _wallet->setFolder(saveFolder); +} + +KWalletContainerItem* KWalletFolderItem::getContainer(KWallet::Wallet::EntryType type) { + for (QListViewItem *i = firstChild(); i; i = i->nextSibling()) { + KWalletContainerItem *ci = dynamic_cast(i); + if (!ci) { + continue; + } + if (ci->type() == type) { + return ci; + } + } + return 0; +} + +bool KWalletFolderItem::contains(const QString& key) { + return (getItem(key) != 0); +} + +QListViewItem* KWalletFolderItem::getItem(const QString& key) { + for (QListViewItem *i = firstChild(); i; i = i->nextSibling()) { + KWalletContainerItem *ci = dynamic_cast(i); + if (!ci) { + continue; + } + QListViewItem *tmp = ci->getItem(key); + if (tmp) { + return tmp; + } + } + return 0; +} + +bool KWalletFolderItem::acceptDrop(const QMimeSource *mime) const { + return mime->provides("application/x-kwallet-entry") || + mime->provides("text/uri-list"); +} + +int KWalletFolderItem::rtti() const { + return KWalletFolderItemClass; +} + +QString KWalletFolderItem::name() const { + return _name; +} + +KWalletFolderItem::~KWalletFolderItem() { +} + +/**************** + * KWalletContainerItem - ListView items to represent kwallet containers, i.e. + * passwords, maps, ... + */ +KWalletContainerItem::KWalletContainerItem(QListViewItem* parent, const QString &name, KWallet::Wallet::EntryType type) +: KListViewItem(parent, name), _type(type) { + setRenameEnabled(0, false); + setDragEnabled(true); +} + +KWalletContainerItem::~KWalletContainerItem() { +} + +int KWalletContainerItem::rtti() const { + return KWalletContainerItemClass; +} + +KWallet::Wallet::EntryType KWalletContainerItem::type() { + return _type; +} + +bool KWalletContainerItem::contains(const QString& key) { + return getItem(key) != 0; +} + +QListViewItem *KWalletContainerItem::getItem(const QString& key) { + for (QListViewItem *i = firstChild(); i; i = i->nextSibling()) { + if (i->text(0) == key) { + return i; + } + } + return 0; +} + +/**************** + * KWalletEntryItem - ListView items to represent kwallet entries + */ +KWalletEntryItem::KWalletEntryItem(KWallet::Wallet *w, QListViewItem* parent, const QString& ename) +: KListViewItem(parent, ename), _wallet(w), _oldName(ename) { + setRenameEnabled(0, true); + setDragEnabled(true); +} + +int KWalletEntryItem::rtti() const { + return KWalletEntryItemClass; +} + +KWalletEntryItem::~KWalletEntryItem() { +} + +/**************** + * KWalletItem - IconView items to represent wallets + */ +KWalletItem::KWalletItem(QIconView *parent, const QString& walletName) +: QIconViewItem(parent, walletName, DesktopIcon("kwalletmanager")) { +} + +KWalletItem::~KWalletItem() { +} + +bool KWalletItem::acceptDrop(const QMimeSource *mime) const { + return mime->provides("application/x-kwallet-folder") || + mime->provides("text/uri-list"); +} + +static bool decodeEntry(KWallet::Wallet *_wallet, QDataStream& ds) { + Q_UINT32 magic; + ds >> magic; + if (magic != KWALLETENTRYMAGIC) { + kdDebug() << "bad magic" << endl; + return false; + } + QString name; + QByteArray value; + KWallet::Wallet::EntryType et; + ds >> name; + if (_wallet->hasEntry(name)) { + int rc = KMessageBox::warningContinueCancel(0L, i18n("An entry by the name '%1' already exists. Would you like to continue?").arg(name)); + if (rc == KMessageBox::Cancel) { + return false; + } + } + long l; + ds >> l; + et = KWallet::Wallet::EntryType(l); + ds >> value; + _wallet->writeEntry(name, value, et); + return true; +} + +static bool decodeFolder(KWallet::Wallet *_wallet, QDataStream& ds) { + Q_UINT32 magic; + ds >> magic; + if (magic != KWALLETFOLDERMAGIC) { + kdDebug() << "bad magic" << endl; + return false; + } + QString folder; + ds >> folder; + if (_wallet->hasFolder(folder)) { + int rc = KMessageBox::warningYesNoCancel(0L, i18n("A folder by the name '%1' already exists. What would you like to do?").arg(folder), QString::null, KStdGuiItem::cont(), i18n("Replace")); + if (rc == KMessageBox::Cancel) { + return false; + } + if (rc == KMessageBox::No) { + _wallet->removeFolder(folder); + _wallet->createFolder(folder); + } + } else { + _wallet->createFolder(folder); + } + + _wallet->setFolder(folder); + while (!ds.atEnd()) { + QString name; + QByteArray value; + KWallet::Wallet::EntryType et; + ds >> name; + long l; + ds >> l; + et = KWallet::Wallet::EntryType(l); + ds >> value; + _wallet->writeEntry(name, value, et); + } + return true; +} + +void KWalletItem::dropped(QDropEvent *e, const QValueList& lst) { + Q_UNUSED(lst); + if (e->provides("application/x-kwallet-folder") || + e->provides("text/uri-list")) { + + // FIXME: don't allow the drop if the wallet name is the same + + KWallet::Wallet *_wallet = KWallet::Wallet::openWallet(text()); + if (!_wallet) { + e->ignore(); + return; + } + + QString saveFolder = _wallet->currentFolder(); + + QFile file; + QDataStream *ds = 0L; + + if (e->provides("application/x-kwallet-folder")) { + QByteArray edata = e->encodedData("application/x-kwallet-folder"); + if (!edata.isEmpty()) { + ds = new QDataStream(edata, IO_ReadOnly); + } + } else { // text/uri-list + QStrList urls; + QUriDrag::decode(e, urls); + + if (urls.isEmpty()) { + e->ignore(); + return; + } + + KURL u(urls.first()); + if (u.fileName().isEmpty()) { + e->ignore(); + return; + } + QString tmpFile; + if (KIO::NetAccess::download(u, tmpFile, 0L)) { + file.setName(tmpFile); + file.open(IO_ReadOnly); + ds = new QDataStream(&file); + KIO::NetAccess::removeTempFile(tmpFile); + } else { + KMessageBox::error(iconView(), KIO::NetAccess::lastErrorString()); + } + } + if (ds) { + decodeFolder(_wallet, *ds); + delete ds; + } + _wallet->setFolder(saveFolder); + delete _wallet; + + //delete the folder from the source if we were moving + Qt::ButtonState state = kapp->keyboardMouseState(); + if (e->source() && e->source()->parent() && + !strcmp(e->source()->parent()->className(), "KWalletEntryList") && + !(state & Qt::ControlButton)) { + + KWalletEntryList *el = + dynamic_cast(e->source()->parent()); + if (el) { + KWalletFolderItem *fi = + dynamic_cast(el->selectedItem()); + if (fi) { + el->_wallet->removeFolder(fi->name()); + } + } + } + e->accept(); + } else { + e->ignore(); + return; + } +} + +/**************** + * KWalletEntryDrag - Stores data for wallet entry drags + */ +class KWalletEntryDrag : public QStoredDrag { + public: + KWalletEntryDrag(QWidget *dragSource, const char *name = 0L) + : QStoredDrag("application/x-kwallet-entry", dragSource, name) { + } + + virtual ~KWalletEntryDrag() {} +}; + +/**************** + * KWalletFolderDrag - Stores data for wallet folder drags + */ +class KWalletFolderDrag : public QStoredDrag { + public: + KWalletFolderDrag(QWidget *dragSource, const char *name = 0L) + : QStoredDrag("application/x-kwallet-folder", dragSource, name) { + } + + virtual ~KWalletFolderDrag() {} +}; + +/**************** + * KWalletEntryList - A listview to store wallet entries + */ +KWalletEntryList::KWalletEntryList(QWidget *parent, const char *name) +: KListView(parent, name) { + addColumn(i18n("Folders")); + setRootIsDecorated(true); + setDefaultRenameAction(Reject); + setAcceptDrops(true); + setItemsMovable(false); + setDropVisualizer(false); + viewport()->setAcceptDrops(true); +} + +KWalletEntryList::~KWalletEntryList() { +} + +bool KWalletEntryList::acceptDrag(QDropEvent* e) const { + QListViewItem *i = itemAt(contentsToViewport(e->pos())); + if (i) { + if (e->provides("application/x-kwallet-entry") || + e->provides("text/uri-list")) { + return true; + } + } + if ((e->provides("application/x-kwallet-folder") && + e->source() != viewport()) || + e->provides("text/uri-list")) { + return true; + } + return false; +} + +//returns true if the item has been dropped successfully +void KWalletEntryList::itemDropped(QDropEvent *e, QListViewItem *item) { + bool ok = true; + bool isEntry; + QFile file; + QDataStream *ds; + + KWalletEntryList *el = 0L; + QListViewItem *sel = 0L; + + //detect if we are dragging from kwallet itself + if (e->source() && e->source()->parent() && + !strcmp(e->source()->parent()->className(), "KWalletEntryList")) { + + el = dynamic_cast(e->source()->parent()); + if (!el) { + KMessageBox::error(this, i18n("An unexpected error occurred trying to drop the item")); + } else + sel = el->selectedItem(); + } + + if (e->provides("application/x-kwallet-entry")) { + //do nothing if we are in the same folder + if (sel && sel->parent()->parent() == + KWalletEntryList::getItemFolder(item)) { + e->ignore(); + return; + } + isEntry = true; + QByteArray data = e->encodedData("application/x-kwallet-entry"); + if (data.isEmpty()) { + e->ignore(); + return; + } + ds = new QDataStream(data, IO_ReadOnly); + } else if (e->provides("application/x-kwallet-folder")) { + //do nothing if we are in the same wallet + if (this == el) { + e->ignore(); + return; + } + isEntry = false; + QByteArray data = e->encodedData("application/x-kwallet-folder"); + if (data.isEmpty()) { + e->ignore(); + return; + } + ds = new QDataStream(data, IO_ReadOnly); + } else if (e->provides("text/uri-list")) { + QStrList urls; + QUriDrag::decode(e, urls); + if (urls.isEmpty()) { + e->ignore(); + return; + } + KURL u(urls.first()); + if (u.fileName().isEmpty()) { + e->ignore(); + return; + } + QString tmpFile; + if (KIO::NetAccess::download(u, tmpFile, 0L)) { + file.setName(tmpFile); + file.open(IO_ReadOnly); + ds = new QDataStream(&file); + //check magic to discover mime type + Q_UINT32 magic; + (*ds) >> magic; + if (magic == KWALLETENTRYMAGIC) { + isEntry = true; + } else if (magic == KWALLETFOLDERMAGIC) { + isEntry = false; + } else { + kdDebug() << "bad magic" << endl; + e->ignore(); + return; + } + delete ds; + //set the file back to the beginning + file.reset(); + ds = new QDataStream(&file); + KIO::NetAccess::removeTempFile(tmpFile); + } else { + KMessageBox::error(this, KIO::NetAccess::lastErrorString()); + return; + } + } else { + e->ignore(); + return; + } + Qt::ButtonState state = kapp->keyboardMouseState(); + if (isEntry) { + if (!item) { + e->ignore(); + return; + } + KWalletFolderItem *fi = KWalletEntryList::getItemFolder(item); + if (!fi) { + KMessageBox::error(this, i18n("An unexpected error occurred trying to drop the entry")); + delete(ds); + e->accept(); + return; + } + QString saveFolder = _wallet->currentFolder(); + _wallet->setFolder(fi->name()); + ok = decodeEntry(_wallet, *ds); + _wallet->setFolder(saveFolder); + fi->refresh(); + delete(ds); + //delete source if we were moving, i.e., we are dragging + //from kwalletmanager and Control is not pressed + if (ok && el && !(state & Qt::ControlButton) && sel) { + el->_wallet->removeEntry(sel->text(0)); + delete sel; + } + e->accept(); + } else { + ok = decodeFolder(_wallet, *ds); + delete ds; + //delete source if we were moving, i.e., we are dragging + //from kwalletmanager and Control is not pressed + if (ok && el && !(state & Qt::ControlButton) && sel) { + KWalletFolderItem *fi = dynamic_cast(sel); + if (fi) { + el->_wallet->removeFolder(fi->name()); + delete sel; + } else { + KMessageBox::error(this, i18n("An unexpected error occurred trying to delete the original folder, but the folder has been copied successfully")); + } + } + e->accept(); + } +} + +void KWalletEntryList::setWallet(KWallet::Wallet *w) { + _wallet = w; +} + +bool KWalletEntryList::existsFolder(const QString& name) { + for (QListViewItem *vi = firstChild(); vi; vi = vi->nextSibling()) { + KWalletFolderItem *fi = dynamic_cast(vi); + if (!fi) { + continue; + } + if (name == fi->name()) { + return true; + } + } + return false; +} + +void KWalletEntryList::contentsDropEvent(QDropEvent *e) { + QListViewItem *i = itemAt(contentsToViewport(e->pos())); + itemDropped(e, i); +} + +void KWalletEntryList::contentsDragEnterEvent(QDragEnterEvent *e) { + if (e->provides("application/x-kwallet-entry") || + e->provides("application/x-kwallet-folder") || + e->provides("application/uri-list")) { + e->accept(); + } else { + e->ignore(); + } +} + +KWalletFolderItem* KWalletEntryList::getFolder(const QString& name) { + for (QListViewItem *vi = firstChild(); vi; vi = vi->nextSibling()) { + KWalletFolderItem *fi = dynamic_cast(vi); + if (!fi) { + continue; + } + if (name == fi->name()) { + return fi; + } + } + return 0; +} + +KWalletFolderItem *KWalletEntryList::getItemFolder(QListViewItem *item) { + switch (item->rtti()) { + case KWalletFolderItemClass: + return dynamic_cast(item); + case KWalletContainerItemClass: + return dynamic_cast(item->parent()); + case KWalletEntryItemClass: + return dynamic_cast(item->parent()->parent()); + } + return 0; +} + +/**************** + * KWalletIconDrag - Stores the data for wallet drags + */ +class KWalletIconDrag : public QIconDrag { + public: + KWalletIconDrag(QWidget *dragSource, const char *name = 0L) + : QIconDrag(dragSource, name) { + } + + virtual ~KWalletIconDrag() {} + + virtual const char *format(int i = 0) const { + if (i == 0) { + return "application/x-qiconlist"; + } else if (i == 1) { + return "text/uri-list"; + } + return 0L; + } + + QByteArray encodedData(const char *mime) const { + QByteArray a; + QCString mimetype(mime); + if (mimetype == "application/x-qiconlist") { + return QIconDrag::encodedData(mime); + } else if (mimetype == "text/uri-list") { + QCString s = _urls.join("\r\n").latin1(); + if (_urls.count() > 0) { + s.append("\r\n"); + } + a.resize(s.length() + 1); + memcpy(a.data(), s.data(), s.length() + 1); + } + return a; + } + + void append(const QIconDragItem &item, const QRect &pr, + const QRect &tr, const QString &url) { + QIconDrag::append(item, pr, tr); + _urls.append(url); + } + + private: + QStringList _urls; +}; + +/**************** +* * KWalletIconView - An iconview to store wallets +* */ +KWalletIconView::KWalletIconView(QWidget *parent, const char *name) +: KIconView(parent, name) { + KGlobal::dirs()->addResourceType("kwallet", "share/apps/kwallet"); + connect(this, SIGNAL(dropped(QDropEvent*, const QValueList&)), SLOT(slotDropped(QDropEvent*, const QValueList&))); +} + +KWalletIconView::~KWalletIconView() { +} + +void KWalletIconView::slotDropped(QDropEvent *e, const QValueList& /*lst*/) { + if (e->source() == viewport()) { + e->ignore(); + return; + } + + if (!e->provides("text/uri-list")) { + e->ignore(); + return; + } + + QByteArray edata = e->encodedData("text/uri-list"); + QCString urls = edata.data(); + + QStringList ul = QStringList::split("\r\n", urls); + if (ul.isEmpty() || ul.first().isEmpty()) { + e->ignore(); + return; + } + + KURL u(ul.first()); + + if (u.fileName().isEmpty()) { + e->ignore(); + return; + } + + QString dest = KGlobal::dirs()->saveLocation("kwallet") + u.fileName(); + if (QFile::exists(dest)) { + KMessageBox::sorry(viewport(), i18n("That wallet file already exists. You cannot overwrite wallets.")); + e->ignore(); + return; + } + + // FIXME: verify that it is a real wallet file first + KIO::NetAccess::file_copy(u, KURL::fromPathOrURL(dest)); + e->accept(); +} + +void KWalletIconView::contentsMousePressEvent(QMouseEvent *e) { + _mousePos = e->pos(); + if (!findItem(_mousePos)) { + clearSelection(); + } + KIconView::contentsMousePressEvent( e ); +} + +QDragObject *KWalletIconView::dragObject() { + KWalletIconDrag* id = new KWalletIconDrag(viewport(), "KWallet Drag"); + QString path = "file:" + KGlobal::dirs()->saveLocation("kwallet"); + QPoint pos = _mousePos; + for (QIconViewItem *item = firstItem(); item; item = item->nextItem()) { + if (item->isSelected()) { + QString url = path + item->text() + ".kwl"; + QIconDragItem idi; + idi.setData(url.local8Bit()); + id->append(idi, + QRect(item->pixmapRect(false).topLeft() - pos, + item->pixmapRect(false).size()), + QRect(item->textRect(false).topLeft() - pos, + item->textRect(false).size()), + url); + } + } + + id->setPixmap(*currentItem()->pixmap(), + pos - currentItem()->pixmapRect(false).topLeft()); + + return id; +} + +QDragObject *KWalletEntryList::dragObject() { + QListViewItem *i = currentItem(); + + QStoredDrag *sd = 0L; + + if (i->rtti() == KWalletEntryItemClass) { + KWalletEntryItem *ei = dynamic_cast(i); + if (!ei) { + return 0L; + } + sd = new KWalletEntryDrag(viewport(), "KWallet Entry Drag"); + QByteArray a; + QDataStream ds(a, IO_WriteOnly); + ds << KWALLETENTRYMAGIC; + ds << *ei; + sd->setEncodedData(a); + } else if (i->rtti() == KWalletFolderItemClass) { + KWalletFolderItem *fi = dynamic_cast(i); + if (!fi) { + return 0L; + } + sd = new KWalletFolderDrag(viewport(), "KWallet Folder Drag"); + QByteArray a; + QDataStream ds(a, IO_WriteOnly); + + ds << KWALLETFOLDERMAGIC; + ds << *fi; + sd->setEncodedData(a); + } + return sd; +} + +#include "allyourbase.moc" diff --git a/kwallet/allyourbase.h b/kwallet/allyourbase.h new file mode 100644 index 0000000..7f5ae92 --- /dev/null +++ b/kwallet/allyourbase.h @@ -0,0 +1,178 @@ +/* + Copyright (C) 2003-2005 George Staikos + Copyright (C) 2005 Isaac Clerencia + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef ALLYOURBASE_H +#define ALLYOURBASE_H + +#include +#include +#include +#include +#include + +#define KWALLETENTRYMAGIC ((Q_UINT32) 0x6B776C65) +#define KWALLETFOLDERMAGIC ((Q_UINT32) 0x6B776C66) + +enum KWalletListItemClasses { + KWalletFolderItemClass = 1000, + KWalletContainerItemClass, + KWalletEntryItemClass, + KWalletUnknownClass = 2000 +}; + +class KWalletEntryItem : public KListViewItem { + public: + KWalletEntryItem(KWallet::Wallet *w, QListViewItem* parent, const QString& ename); + virtual ~KWalletEntryItem(); + + const QString& oldName() { return _oldName; } + QString currentName() { return text(0); } + + void clearOldName() { _oldName = text(0); } + virtual int rtti() const; + + public: + KWallet::Wallet *_wallet; + + private: + QString _oldName; +}; + +class KWalletContainerItem : public KListViewItem { + public: + KWalletContainerItem(QListViewItem* parent, const QString& name, + KWallet::Wallet::EntryType type); + virtual ~KWalletContainerItem(); + + public: + virtual int rtti() const; + KWallet::Wallet::EntryType type(); + bool contains(const QString& itemKey); + QListViewItem* getItem(const QString& itemKey); + + private: + KWallet::Wallet::EntryType _type; +}; + +class KWalletFolderItem : public KListViewItem { + public: + KWalletFolderItem(KWallet::Wallet *w, QListView* parent, + const QString& name, int entries); + virtual ~KWalletFolderItem(); + + virtual bool acceptDrop(const QMimeSource *mime) const; + virtual int rtti() const; + + QString name() const; + void refresh(); + KWalletContainerItem* getContainer(KWallet::Wallet::EntryType type); + QPixmap getFolderIcon(KIcon::Group group); + bool contains(const QString& itemKey); + QListViewItem* getItem(const QString& itemKey); + + public: + KWallet::Wallet *_wallet; + + private: + QString _name; + int _entries; +}; + +class KWalletEntryList : public KListView { + Q_OBJECT + public: + KWalletEntryList(QWidget *parent, const char *name = 0L); + virtual ~KWalletEntryList(); + + bool existsFolder(const QString& name); + KWalletFolderItem* getFolder(const QString& name); + void contentsDropEvent(QDropEvent *e); + void contentsDragEnterEvent(QDragEnterEvent *e); + void setWallet(KWallet::Wallet *w); + + protected: + void itemDropped(QDropEvent *e, QListViewItem *item); + virtual QDragObject *dragObject(); + virtual bool acceptDrag (QDropEvent* event) const; + + private: + static KWalletFolderItem *getItemFolder(QListViewItem *item); + + public: + KWallet::Wallet *_wallet; +}; + +class KWalletItem : public QIconViewItem { + public: + KWalletItem(QIconView *parent, const QString& walletName); + virtual ~KWalletItem(); + + virtual bool acceptDrop(const QMimeSource *mime) const; + + protected: + virtual void dropped(QDropEvent *e, const QValueList& lst); +}; + + +class KWalletIconView : public KIconView { + Q_OBJECT + public: + KWalletIconView(QWidget *parent, const char *name = 0L); + virtual ~KWalletIconView(); + + protected slots: + virtual void slotDropped(QDropEvent *e, const QValueList& lst); + + protected: + virtual QDragObject *dragObject(); + virtual void contentsMousePressEvent(QMouseEvent *e); + QPoint _mousePos; +}; + + +inline QDataStream& operator<<(QDataStream& str, const KWalletEntryItem& w) { + QString name = w.text(0); + str << name; + KWallet::Wallet::EntryType et = w._wallet->entryType(name); + str << long(et); + QByteArray a; + w._wallet->readEntry(name, a); + str << a; + return str; +} + +inline QDataStream& operator<<(QDataStream& str, const KWalletFolderItem& w) { + QString oldFolder = w._wallet->currentFolder(); + str << w.name(); + w._wallet->setFolder(w.name()); + QStringList entries = w._wallet->entryList(); + for (QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) { + str << *it; + KWallet::Wallet::EntryType et = w._wallet->entryType(*it); + str << long(et); + QByteArray a; + w._wallet->readEntry(*it, a); + str << a; + } + w._wallet->setFolder(oldFolder); + return str; +} + +#endif diff --git a/kwallet/hi128-app-kwalletmanager.png b/kwallet/hi128-app-kwalletmanager.png new file mode 100644 index 0000000..ccdd7c9 Binary files /dev/null and b/kwallet/hi128-app-kwalletmanager.png differ diff --git a/kwallet/hi128-app-kwalletmanager2.png b/kwallet/hi128-app-kwalletmanager2.png new file mode 100644 index 0000000..e3937db Binary files /dev/null and b/kwallet/hi128-app-kwalletmanager2.png differ diff --git a/kwallet/hi16-app-kwalletmanager.png b/kwallet/hi16-app-kwalletmanager.png new file mode 100644 index 0000000..4f9f4fd Binary files /dev/null and b/kwallet/hi16-app-kwalletmanager.png differ diff --git a/kwallet/hi16-app-kwalletmanager2.png b/kwallet/hi16-app-kwalletmanager2.png new file mode 100644 index 0000000..b2f9004 Binary files /dev/null and b/kwallet/hi16-app-kwalletmanager2.png differ diff --git a/kwallet/hi22-app-kwalletmanager.png b/kwallet/hi22-app-kwalletmanager.png new file mode 100644 index 0000000..8bc4cdb Binary files /dev/null and b/kwallet/hi22-app-kwalletmanager.png differ diff --git a/kwallet/hi32-app-kwalletmanager.png b/kwallet/hi32-app-kwalletmanager.png new file mode 100644 index 0000000..69a7c1e Binary files /dev/null and b/kwallet/hi32-app-kwalletmanager.png differ diff --git a/kwallet/hi32-app-kwalletmanager2.png b/kwallet/hi32-app-kwalletmanager2.png new file mode 100644 index 0000000..3cfc4e2 Binary files /dev/null and b/kwallet/hi32-app-kwalletmanager2.png differ diff --git a/kwallet/hi48-app-kwalletmanager.png b/kwallet/hi48-app-kwalletmanager.png new file mode 100644 index 0000000..5b46a87 Binary files /dev/null and b/kwallet/hi48-app-kwalletmanager.png differ diff --git a/kwallet/hi48-app-kwalletmanager2.png b/kwallet/hi48-app-kwalletmanager2.png new file mode 100644 index 0000000..3ae286d Binary files /dev/null and b/kwallet/hi48-app-kwalletmanager2.png differ diff --git a/kwallet/hi64-app-kwalletmanager.png b/kwallet/hi64-app-kwalletmanager.png new file mode 100644 index 0000000..38a581c Binary files /dev/null and b/kwallet/hi64-app-kwalletmanager.png differ diff --git a/kwallet/hi64-app-kwalletmanager2.png b/kwallet/hi64-app-kwalletmanager2.png new file mode 100644 index 0000000..2e5be4b Binary files /dev/null and b/kwallet/hi64-app-kwalletmanager2.png differ diff --git a/kwallet/icons/Makefile.am b/kwallet/icons/Makefile.am new file mode 100644 index 0000000..8bad46c --- /dev/null +++ b/kwallet/icons/Makefile.am @@ -0,0 +1,5 @@ +KDE_ICON = kwalletmanager + +pics_ICON = AUTO +picsdir = $(kde_datadir)/kwalletmanager/icons + diff --git a/kwallet/icons/cr22-action-folder_closed.png b/kwallet/icons/cr22-action-folder_closed.png new file mode 100644 index 0000000..e3ebad3 Binary files /dev/null and b/kwallet/icons/cr22-action-folder_closed.png differ diff --git a/kwallet/icons/cr22-action-folder_open.png b/kwallet/icons/cr22-action-folder_open.png new file mode 100644 index 0000000..ea175b7 Binary files /dev/null and b/kwallet/icons/cr22-action-folder_open.png differ diff --git a/kwallet/icons/cr22-action-wallet_closed.png b/kwallet/icons/cr22-action-wallet_closed.png new file mode 100644 index 0000000..57558ac Binary files /dev/null and b/kwallet/icons/cr22-action-wallet_closed.png differ diff --git a/kwallet/icons/cr22-action-wallet_open.png b/kwallet/icons/cr22-action-wallet_open.png new file mode 100644 index 0000000..55a447f Binary files /dev/null and b/kwallet/icons/cr22-action-wallet_open.png differ diff --git a/kwallet/kbetterthankdialogbase.ui b/kwallet/kbetterthankdialogbase.ui new file mode 100644 index 0000000..30d2d93 --- /dev/null +++ b/kwallet/kbetterthankdialogbase.ui @@ -0,0 +1,154 @@ + +KBetterThanKDialogBase + + + KBetterThanKDialogBase + + + + 0 + 0 + 479 + 109 + + + + + + + + unnamed + + + Fixed + + + + _label + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 41 + 21 + + + + + + layout1 + + + + unnamed + + + + _allowOnce + + + &Replace + + + true + + + + + _allowAlways + + + Replace &All + + + + + _deny + + + &Skip + + + + + _denyForever + + + Skip A&ll + + + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 61 + 21 + + + + + + + + + + _allowOnce + clicked() + KBetterThanKDialogBase + clicked() + + + _allowAlways + clicked() + KBetterThanKDialogBase + clicked() + + + _deny + clicked() + KBetterThanKDialogBase + clicked() + + + _denyForever + clicked() + KBetterThanKDialogBase + clicked() + + + + kactivelabel.h + kbetterthankdialogbase.ui.h + + + clicked() + setLabel( const QString & label ) + init() + accept() + reject() + + + + kactivelabel.h + + diff --git a/kwallet/kbetterthankdialogbase.ui.h b/kwallet/kbetterthankdialogbase.ui.h new file mode 100644 index 0000000..3937746 --- /dev/null +++ b/kwallet/kbetterthankdialogbase.ui.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you want to add, delete, or rename functions or slots, use +** Qt Designer to update this file, preserving your code. +** +** You should not define a constructor or destructor in this file. +** Instead, write your code in functions called init() and destroy(). +** These will automatically be called by the form's constructor and +** destructor. +*****************************************************************************/ + + +void KBetterThanKDialogBase::clicked() +{ + if (sender() == _allowOnce) { + done(3); + } else if (sender() == _allowAlways) { + done(1); + } else if (sender() == _deny) { + done(4); + } else if (sender() == _denyForever) { + done(2); + } +} + + +void KBetterThanKDialogBase::setLabel( const QString & label ) +{ + _label->setText(label); +} + + +void KBetterThanKDialogBase::init() +{ + _allowOnce->setFocus(); +} + + +void KBetterThanKDialogBase::accept() +{ + setResult(3); +} + + +void KBetterThanKDialogBase::reject() +{ + QDialog::reject(); + setResult(4); +} diff --git a/kwallet/konfigurator/Makefile.am b/kwallet/konfigurator/Makefile.am new file mode 100644 index 0000000..fab7551 --- /dev/null +++ b/kwallet/konfigurator/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO + +kde_module_LTLIBRARIES = kcm_kwallet.la +kcm_kwallet_la_SOURCES = walletconfigwidget.ui konfigurator.cpp +kcm_kwallet_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +kcm_kwallet_la_LIBADD = $(LIB_KDEUI) -lkwalletclient + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcmkwallet.pot + +xdg_apps_DATA = kwalletconfig.desktop + +kde_services_DATA = kwallet_config.desktop kwalletmanager_show.desktop + diff --git a/kwallet/konfigurator/konfigurator.cpp b/kwallet/konfigurator/konfigurator.cpp new file mode 100644 index 0000000..a5fc336 --- /dev/null +++ b/kwallet/konfigurator/konfigurator.cpp @@ -0,0 +1,323 @@ +/* + Copyright (C) 2003 George Staikos + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "konfigurator.h" +#include "walletconfigwidget.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +typedef KGenericFactory KWalletFactory; +K_EXPORT_COMPONENT_FACTORY(kcm_kwallet, KWalletFactory("kcmkwallet")) + +KWalletConfig::KWalletConfig(QWidget *parent, const char *name, const QStringList&) +: KCModule(KWalletFactory::instance(), parent, name) { + + KAboutData *about = + new KAboutData(I18N_NOOP("kcmkwallet"), + I18N_NOOP("KDE Wallet Control Module"), + 0, 0, KAboutData::License_GPL, + I18N_NOOP("(c) 2003 George Staikos")); + about->addAuthor("George Staikos", 0, "staikos@kde.org"); + setAboutData( about ); + + _cfg = new KConfig("kwalletrc", false, false); + + QVBoxLayout *vbox = new QVBoxLayout(this, 0, KDialog::spacingHint()); + vbox->add(_wcw = new WalletConfigWidget(this)); + + connect(_wcw->_enabled, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(_wcw->_launchManager, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(_wcw->_autocloseManager, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(_wcw->_autoclose, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(_wcw->_closeIdle, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(_wcw->_openPrompt, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(_wcw->_screensaverLock, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(_wcw->_localWalletSelected, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(_wcw->_idleTime, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + connect(_wcw->_launch, SIGNAL(clicked()), this, SLOT(launchManager())); + connect(_wcw->_newWallet, SIGNAL(clicked()), this, SLOT(newNetworkWallet())); + connect(_wcw->_newLocalWallet, SIGNAL(clicked()), this, SLOT(newLocalWallet())); + connect(_wcw->_localWallet, SIGNAL(activated(int)), this, SLOT(configChanged())); + connect(_wcw->_defaultWallet, SIGNAL(activated(int)), this, SLOT(configChanged())); + connect(_wcw->_accessList, SIGNAL(contextMenuRequested(QListViewItem*, const QPoint&, int)), this, SLOT(contextMenuRequested(QListViewItem*, const QPoint&, int))); + + _wcw->_accessList->setAllColumnsShowFocus(true); + updateWalletLists(); + load(); + + if (DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) { + _wcw->_launch->hide(); + } + +} + + +KWalletConfig::~KWalletConfig() { + delete _cfg; + _cfg = 0L; +} + + +void KWalletConfig::updateWalletLists() { + QString p1, p2; + p1 = _wcw->_localWallet->currentText(); + p2 = _wcw->_defaultWallet->currentText(); + + _wcw->_localWallet->clear(); + _wcw->_defaultWallet->clear(); + + QStringList wl = KWallet::Wallet::walletList(); + _wcw->_localWallet->insertStringList(wl); + _wcw->_defaultWallet->insertStringList(wl); + + if (wl.contains(p1)) { + _wcw->_localWallet->setCurrentText(p1); + } + + if (wl.contains(p2)) { + _wcw->_defaultWallet->setCurrentText(p2); + } +} + + +QString KWalletConfig::newWallet() { + bool ok; + + QString n = KInputDialog::getText(i18n("New Wallet"), + i18n("Please choose a name for the new wallet:"), + QString::null, + &ok, + this); + + if (!ok) { + return QString::null; + } + + KWallet::Wallet *w = KWallet::Wallet::openWallet(n); + if (!w) { + return QString::null; + } + + delete w; + return n; +} + + +void KWalletConfig::newLocalWallet() { + QString n = newWallet(); + if (n.isEmpty()) { + return; + } + + updateWalletLists(); + + _wcw->_localWallet->setCurrentText(n); + + emit changed(true); +} + + +void KWalletConfig::newNetworkWallet() { + QString n = newWallet(); + if (n.isEmpty()) { + return; + } + + updateWalletLists(); + + _wcw->_defaultWallet->setCurrentText(n); + + emit changed(true); +} + + +void KWalletConfig::launchManager() { + if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) { + KApplication::startServiceByDesktopName("kwalletmanager_show"); + } else { + DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1"); + r.send("show"); + r.send("raise"); + } +} + + +void KWalletConfig::configChanged() { + emit changed(true); +} + +void KWalletConfig::load() { + load( false ); +} + +void KWalletConfig::load(bool useDefaults) { + KConfigGroup config(_cfg, "Wallet"); + config.setReadDefaults( useDefaults ); + _wcw->_enabled->setChecked(config.readBoolEntry("Enabled", true)); + _wcw->_openPrompt->setChecked(config.readBoolEntry("Prompt on Open", true)); + _wcw->_launchManager->setChecked(config.readBoolEntry("Launch Manager", true)); + _wcw->_autocloseManager->setChecked(! config.readBoolEntry("Leave Manager Open", false)); + _wcw->_screensaverLock->setChecked(config.readBoolEntry("Close on Screensaver", false)); + _wcw->_autoclose->setChecked(!config.readBoolEntry("Leave Open", false)); + _wcw->_closeIdle->setChecked(config.readBoolEntry("Close When Idle", false)); + _wcw->_idleTime->setValue(config.readNumEntry("Idle Timeout", 10)); + if (config.hasKey("Default Wallet")) { + _wcw->_defaultWallet->setCurrentText(config.readEntry("Default Wallet")); + } else { + _wcw->_defaultWallet->setCurrentItem(0); + } + if (config.hasKey("Local Wallet")) { + _wcw->_localWalletSelected->setChecked( !config.readBoolEntry("Use One Wallet") ); + _wcw->_localWallet->setCurrentText(config.readEntry("Local Wallet")); + } else { + _wcw->_localWalletSelected->setChecked(false); + } + _wcw->_accessList->clear(); + _cfg->setGroup("Auto Deny"); + QStringList denykeys = _cfg->entryMap("Auto Deny").keys(); + _cfg->setGroup("Auto Allow"); + QStringList keys = _cfg->entryMap("Auto Allow").keys(); + for (QStringList::Iterator i = keys.begin(); i != keys.end(); ++i) { + _cfg->setGroup("Auto Allow"); + QStringList apps = _cfg->readListEntry(*i); + _cfg->setGroup("Auto Deny"); + QStringList denyapps = _cfg->readListEntry(*i); + denykeys.remove(*i); + QListViewItem *lvi = new QListViewItem(_wcw->_accessList, *i); + for (QStringList::Iterator j = apps.begin(); j != apps.end(); ++j) { + new QListViewItem(lvi, QString::null, *j, i18n("Always Allow")); + } + for (QStringList::Iterator j = denyapps.begin(); j != denyapps.end(); ++j) { + new QListViewItem(lvi, QString::null, *j, i18n("Always Deny")); + } + } + _cfg->setGroup("Auto Deny"); + for (QStringList::Iterator i = denykeys.begin(); i != denykeys.end(); ++i) { + QStringList denyapps = _cfg->readListEntry(*i); + QListViewItem *lvi = new QListViewItem(_wcw->_accessList, *i); + for (QStringList::Iterator j = denyapps.begin(); j != denyapps.end(); ++j) { + new QListViewItem(lvi, QString::null, *j, i18n("Always Deny")); + } + } + emit changed(useDefaults); +} + + +void KWalletConfig::save() { + KConfigGroup config(_cfg, "Wallet"); + config.writeEntry("Enabled", _wcw->_enabled->isChecked()); + config.writeEntry("Launch Manager", _wcw->_launchManager->isChecked()); + config.writeEntry("Leave Manager Open", !_wcw->_autocloseManager->isChecked()); + config.writeEntry("Leave Open", !_wcw->_autoclose->isChecked()); + config.writeEntry("Close When Idle", _wcw->_closeIdle->isChecked()); + config.writeEntry("Idle Timeout", _wcw->_idleTime->value()); + config.writeEntry("Prompt on Open", _wcw->_openPrompt->isChecked()); + config.writeEntry("Close on Screensaver", _wcw->_screensaverLock->isChecked()); + + config.writeEntry("Use One Wallet", !_wcw->_localWalletSelected->isChecked()); + if (_wcw->_localWalletSelected->isChecked()) { + config.writeEntry("Local Wallet", _wcw->_localWallet->currentText()); + } else { + config.deleteEntry("Local Wallet"); + } + + if (_wcw->_defaultWallet->currentItem() != -1) { + config.writeEntry("Default Wallet", _wcw->_defaultWallet->currentText()); + } else { + config.deleteEntry("Default Wallet"); + } + + // FIXME: won't survive a language change + _cfg->deleteGroup("Auto Allow"); + _cfg->deleteGroup("Auto Deny"); + _cfg->setGroup("Auto Allow"); + for (QListViewItem *i = _wcw->_accessList->firstChild(); i; i = i->nextSibling()) { + QStringList al; + for (QListViewItem *j = i->firstChild(); j; j = j->nextSibling()) { + if (j->text(2) == i18n("Always Allow")) { + al << j->text(1); + } + } + _cfg->writeEntry(i->text(0), al); + } + + _cfg->setGroup("Auto Deny"); + for (QListViewItem *i = _wcw->_accessList->firstChild(); i; i = i->nextSibling()) { + QStringList al; + for (QListViewItem *j = i->firstChild(); j; j = j->nextSibling()) { + if (j->text(2) == i18n("Always Deny")) { + al << j->text(1); + } + } + _cfg->writeEntry(i->text(0), al); + } + + _cfg->sync(); + DCOPRef("kded", "kwalletd").call("reconfigure()"); + + emit changed(false); +} + + +void KWalletConfig::defaults() { + load( true ); +} + + +QString KWalletConfig::quickHelp() const { + return i18n("This configuration module allows you to configure the KDE wallet system."); +} + + +void KWalletConfig::contextMenuRequested(QListViewItem *item, const QPoint& pos, int col) { + Q_UNUSED(col) + if (item && item->parent()) { + KPopupMenu *m = new KPopupMenu(this); + m->insertTitle(item->parent()->text(0)); + m->insertItem(i18n("&Delete"), this, SLOT(deleteEntry()), Key_Delete); + m->popup(pos); + } +} + + +void KWalletConfig::deleteEntry() { + QListViewItem *item = _wcw->_accessList->selectedItem(); + if (item) { + delete item; + emit changed(true); + } +} + +#include "konfigurator.moc" + diff --git a/kwallet/konfigurator/konfigurator.h b/kwallet/konfigurator/konfigurator.h new file mode 100644 index 0000000..e12ebfc --- /dev/null +++ b/kwallet/konfigurator/konfigurator.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2003 George Staikos + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef _KWALLETKONFIGURATOR_H +#define _KWALLETKONFIGURATOR_H + +#include + +class KConfig; +class WalletConfigWidget; +class QListViewItem; + +class KWalletConfig : public KCModule { + Q_OBJECT + public: + KWalletConfig(QWidget *parent = 0L, const char *name = 0L, const QStringList& = QStringList()); + virtual ~KWalletConfig(); + + void load(); + void load( bool useDefaults ); + void save(); + void defaults(); + + QString quickHelp() const; + + public slots: + void configChanged(); + void launchManager(); + void newLocalWallet(); + void newNetworkWallet(); + void updateWalletLists(); + QString newWallet(); + void deleteEntry(); + void contextMenuRequested(QListViewItem *item, const QPoint& pos, int col); + + private: + WalletConfigWidget *_wcw; + KConfig *_cfg; +}; + +#endif diff --git a/kwallet/konfigurator/kwallet_config.desktop b/kwallet/konfigurator/kwallet_config.desktop new file mode 100644 index 0000000..d8c59ba --- /dev/null +++ b/kwallet/konfigurator/kwallet_config.desktop @@ -0,0 +1,47 @@ +[Desktop Entry] +Type=Service +Exec=kcmshell --caption %c kwalletconfig +Icon=kwalletmanager +DocPath=kwallet/index.html +Name=KDE Wallet +Name[ar]=محفظة كدى +Name[bg]=Портфейл +Name[br]=Doug-paperoù KDE +Name[bs]=KDE novčanik +Name[cs]=Úschovna KDE +Name[cy]=Waled KDE +Name[da]=KDE's tegnebog +Name[de]=Digitale Brieftasche +Name[el]=Πορτοφόλι του KDE +Name[es]=Cartera de KDE +Name[et]=KDE turvalaegas +Name[eu]=KDE Kartera +Name[fi]=Lompakko +Name[fr]=Gestionnaire de comptes de KDE +Name[hi]=केडीई वॉलेट +Name[hu]=Digitális noteszek +Name[is]=KDE veskið +Name[it]=Portafogli di KDE +Name[ja]=KDE ウォレット +Name[kk]=KDE әмияні +Name[km]=កាបូប KDE +Name[lt]=KDE slaptažodinės +Name[mk]=KDE Паричник +Name[nds]=KDE-Knipp +Name[ne]=KDE वालेट +Name[pa]=KDE ਵਾਲਿਟ +Name[pl]=Portfel KDE +Name[pt]=Carteira KDE +Name[pt_BR]=Carteira do KDE +Name[ro]=Portofel KDE +Name[ru]=Бумажник +Name[sl]=Listnica za KDE +Name[sv]=KDE-plånbok +Name[ta]= கேடிஇ வாலட் +Name[tg]=KDE Ҳамён +Name[tr]=KDE Cüzdan +Name[uk]=Торбинки KDE +Name[uz]=KDE qopchiq +Name[uz@cyrillic]=KDE қопчиқ +Name[zh_CN]=KDE 钱包 +Name[zh_TW]=KDE 錢包 diff --git a/kwallet/konfigurator/kwalletconfig.desktop b/kwallet/konfigurator/kwalletconfig.desktop new file mode 100644 index 0000000..0c60eef --- /dev/null +++ b/kwallet/konfigurator/kwalletconfig.desktop @@ -0,0 +1,152 @@ +[Desktop Entry] +Icon=kwalletmanager +Type=Application +Exec=kcmshell kwalletconfig +DocPath=kwallet/index.html +X-KDE-ModuleType=Library +X-KDE-Library=kwallet +X-KDE-ParentApp=kcontrol + +Name=KDE Wallet +Name[ar]=محفظة كدى +Name[bg]=Портфейл +Name[br]=Doug-paperoù KDE +Name[bs]=KDE novčanik +Name[cs]=Úschovna KDE +Name[cy]=Waled KDE +Name[da]=KDE's tegnebog +Name[de]=Digitale Brieftasche +Name[el]=Πορτοφόλι του KDE +Name[es]=Cartera de KDE +Name[et]=KDE turvalaegas +Name[eu]=KDE Kartera +Name[fi]=Lompakko +Name[fr]=Gestionnaire de comptes de KDE +Name[hi]=केडीई वॉलेट +Name[hu]=Digitális noteszek +Name[is]=KDE veskið +Name[it]=Portafogli di KDE +Name[ja]=KDE ウォレット +Name[kk]=KDE әмияні +Name[km]=កាបូប KDE +Name[lt]=KDE slaptažodinės +Name[mk]=KDE Паричник +Name[nds]=KDE-Knipp +Name[ne]=KDE वालेट +Name[pa]=KDE ਵਾਲਿਟ +Name[pl]=Portfel KDE +Name[pt]=Carteira KDE +Name[pt_BR]=Carteira do KDE +Name[ro]=Portofel KDE +Name[ru]=Бумажник +Name[sl]=Listnica za KDE +Name[sv]=KDE-plånbok +Name[ta]= கேடிஇ வாலட் +Name[tg]=KDE Ҳамён +Name[tr]=KDE Cüzdan +Name[uk]=Торбинки KDE +Name[uz]=KDE qopchiq +Name[uz@cyrillic]=KDE қопчиқ +Name[zh_CN]=KDE 钱包 +Name[zh_TW]=KDE 錢包 +Comment=KDE Wallet Configuration +Comment[ar]=إعداد محفظة كدى +Comment[bg]=Настройване на системата Портфейл +Comment[br]=Kefluniadur Doug-paperoù KDE +Comment[bs]=Podešavanje KDE novčanika +Comment[ca]=Configuració de carteres KDE +Comment[cs]=Nastavení úschovny KDE +Comment[cy]=Ffurfweddiad Waled KDE +Comment[da]=KDE's indstilling af tegnebog +Comment[de]=Einrichten der "digitalen Brieftasche" (KWallet) +Comment[el]=Ρύθμιση του πορτοφολιού του KDE +Comment[es]=Configuración de la cartera de KDE +Comment[et]=KDE turvalaeka seadistamine +Comment[eu]=KDE Karteraren Konfigurazioa +Comment[fa]=KDE Wallet پیکربندی +Comment[fi]=KDE-lompakon asetukset +Comment[fr]=Configuration du gestionnaire de comptes de KDE +Comment[ga]=Cumraíocht KDE Wallet +Comment[he]=KDE Wallet הגדרות +Comment[hi]=केडीई वॉलेट कॉन्फ़िगरेशन +Comment[hu]=A KDE digitális noteszeinek beállításai +Comment[is]=Stillingar veskisins +Comment[it]=Configurazione portafogli di KDE +Comment[ja]=KDE ウォレットの設定 +Comment[ka]=KDE Wallet-ის კონფიგურაცია +Comment[kk]=KDE әмияннің баптауы +Comment[km]=ការកំណត់​រចនា​សម្ព័ន្ធ​កាបូប KDE +Comment[lt]=KDE slaptažodinių konfigūravimas +Comment[mk]=Конфигурација на паричник во KDE +Comment[nb]=Oppsett av KDE Wallet +Comment[nds]=KDE-Knipp instellen +Comment[ne]=KDE वालेट कन्फिगरेसन +Comment[nl]=KDE portefeuille-instellingen +Comment[nn]=Oppsett av KDE Wallet +Comment[pa]=KDE ਵਾਲਿਟ ਸੰਰਚਨਾ +Comment[pl]=Konfiguracja Portfela KDE +Comment[pt]=Configuração da Carteira do KDE +Comment[pt_BR]=Configuração da Carteira do KDE +Comment[ro]=Configurează portofelul KDE +Comment[ru]=Параметры бумажника +Comment[sk]=Konfigurácia KDE Wallet +Comment[sl]=Nastavitve Listnice za KDE +Comment[sr]=Подешавање KDE Wallet-а +Comment[sr@Latn]=Podešavanje KDE Wallet-a +Comment[sv]=Inställning av KDE-plånbok +Comment[ta]=கேடிஇ வாலட் வடிவமைப்பு +Comment[tg]=KDE Танзими Ҳамён +Comment[tr]=KDE Cüzdan Ayarı +Comment[uk]=Налаштування KWallet +Comment[uz]=KDE qopchiq xizmatini moslash +Comment[uz@cyrillic]=KDE қопчиқ хизматини мослаш +Comment[zh_CN]=KDE 钱包配置 +Comment[zh_TW]=KDE 錢包設定 +Keywords=Wallet,Form Fill,Passwords,Form Data +Keywords[ar]=محفظة،ملأ نموذج،كلمات السرّ،بيانات نموذج +Keywords[bg]=портфейл, форми, форма, попълване, данни, парола, пароли, Wallet, Form Fill, Passwords, Form Data +Keywords[bs]=Wallet,Form Fill,Passwords,Form Data,novčanik,formulari,popunjavanje formulara,šifre +Keywords[ca]=Cartera,Ompliment de formularis,Contrasentes,Dades de formularis +Keywords[cs]=úschovna,vyplnění formuláře,hesla,data formuláře +Keywords[cy]=Waled,Llenwi Ffurflen,Cyfrineiriau,Data Ffurflenni +Keywords[da]=Tegnebog,Formularudfyldning,Kodeord,Formular-data +Keywords[de]=Geheimfach,Formular,Passwort,Brieftasche,digitale Brieftasche +Keywords[el]=Πορτοφόλι,Συμπλήρωση φόρμας,Κωδικοί πρόσβασης,Δεδομένα φόρμας +Keywords[es]=Cartera,Rellenar formulario,Contraseña,Datos de formulario +Keywords[et]=Turvalaegas,Vormi täitmine,Paroolid,Vormiandmed +Keywords[eu]=Kartera,Formularioa Bete,Pasahitzak,Formulario Datuak +Keywords[fa]=Wallet، پر کردن برگه، اسم رمزها، دادۀ برگه +Keywords[fi]=Lompakko,Lomakkeen täyttö,Salasanat,Lomaketiedot +Keywords[fr]=gestionnaire de comptes,remplissage de formulaire,Mots de passe,Données de formulaire +Keywords[ga]=Wallet,Líonadh Foirmeacha,Focal Faire,Sonraí foirme +Keywords[hi]=बटुआ,फ़ॉर्म फिल,पासवर्ड,फ़ॉर्म डाटा +Keywords[hu]=digitális notesz,űrlapkitöltés,jelszavak,űrlapadatok +Keywords[it]=portafogli,wallet,riempimento moduli,moduli,form,password,dati moduli +Keywords[ja]=ウォレット,フォームフィル,パスワード,フォームデータ +Keywords[ka]=Wallet,ფორმის შევსება,პაროლები,ფორმათა მონაცემები +Keywords[km]=កាបូប,ការបំពេញ​សំណុំ​បែបបទ,ពាក្យ​សម្ងាត់,ទិន្នន័យ​សំណុំ​បែបបទ +Keywords[lt]=Wallet, slaptažodinė,Form Fill,Passwords,Form Data,formų pildymas,slaptažodžiai,formų duomenys +Keywords[mk]=Wallet,Form Fill,Passwords,Form Data, Паричник, формулар, лозинки +Keywords[nb]=Wallet,Skjemautfylling,Passord,Skjema +Keywords[nds]=Knipp,Formulor,Passwöör,Formulordaten +Keywords[ne]=वालेट,फारम भराइ,पासवर्ड,फारम डेटा +Keywords[nl]=Wallet,gegevens,portefeuille,wachtwoorden,veilig bewaren van wachtwoorden,invulgegevens,formulieren +Keywords[nn]=wallet,skjemautfylling,passord,skjema +Keywords[pa]=Wallet,Form Fill,ਗੁਪਤ-ਕੋਡ,ਫਾਰਮ ਡਾਟਾ +Keywords[pl]=portfel,wypełnianie formularzy,uzupełnianie formularzy, hasła, hasło,dane formularzy, formularze +Keywords[pt]=Carteira,Preenchimento de Formulários,Senhas,Dados do Formulário +Keywords[pt_BR]=carteira,preenchimento de formulário,senhas,dados de formulário +Keywords[ro]=portofel,completare formulare,parole,date formular,formular +Keywords[ru]=Wallet,Form Fill,Passwords,Form Data,Бумажник,Пароли,Формы +Keywords[sk]=wallet,formuláre,heslá,dáta z formulárov,schránka,peňaženka +Keywords[sl]=waller,denarnica,gesla,obrazec,podatki,geslo,listnica +Keywords[sr]=Wallet,Form Fill,Passwords,Form Data,лозинке,новчаник +Keywords[sr@Latn]=Wallet,Form Fill,Passwords,Form Data,lozinke,novčanik +Keywords[sv]=Plånbok,fyll i formulär,lösenord,formulärdata +Keywords[ta]=வாலட், படிவ நிரப்பு, கடவுச் சொற்கள், படிவ தகவல் +Keywords[tg]=Ҳамён,Пуркунии Варақа,Гузарвожаҳо,Варақаи Додаҳо +Keywords[tr]=Cüzdan,Form Doldur,Şifreler,Form Verisi +Keywords[uk]=Торбинка,Заповнення форм,Паролі,Дані форм +Keywords[zh_CN]=Wallet,Form Fill,Passwords,Form Data,钱包,填充表单,密码,表单数据 + +Categories=Qt;KDE;X-KDE-settings-security; diff --git a/kwallet/konfigurator/kwalletmanager_show.desktop b/kwallet/konfigurator/kwalletmanager_show.desktop new file mode 100644 index 0000000..91b7368 --- /dev/null +++ b/kwallet/konfigurator/kwalletmanager_show.desktop @@ -0,0 +1,60 @@ +[Desktop Entry] +Name=Wallet Management Tool +Name[ar]=أداة إدارة المحفظة +Name[bg]=Портфейл +Name[br]=Merour an doug-paperoù +Name[bs]=Alat za upravljanje novčanikom +Name[ca]=Eina de gestió de carteres +Name[cs]=Nástroj pro správu úschovny +Name[cy]=Erfyn Rheoli Waled +Name[da]=Håndteringsværktøj for tegnebog +Name[de]=Verwaltung für digitale Brieftasche +Name[el]=Εργαλείο διαχείρισης πορτοφολιού +Name[es]=Herramienta de gestión de cartera +Name[et]=Turvalaeka haldur +Name[eu]=Kartera Kudeatzeko Tresna +Name[fa]=ابزار مدیریت Wallet +Name[fi]=Lompakon hallintatyökalu +Name[fr]=Outil de gestion de comptes +Name[ga]=Uirlis Bhainisteoireachta Wallet +Name[he]=כלי לניהול הארנק של KDE +Name[hi]= बटुआ प्रबंधन औज़ार +Name[hu]=Kezelőprogram a KDE digitális noteszeihez +Name[is]=Tól til að stýra eiginleikum veskisins +Name[it]=Strumento per la gestione dei portafogli +Name[ja]=ウォレット管理ツール +Name[ka]=Wallet-ის მმართველი მოწყობილობა +Name[kk]=Әмиянін басқару құралы +Name[km]=ឧបករណ៍​គ្រប់គ្រង​កាបូប +Name[lt]=Spatažodinių tvarkymo įrankis +Name[mk]=Алатка за менаџирање на паричници +Name[nb]=Wallet administrasjonsverktøy +Name[nds]=Knipp-Pleger +Name[ne]=वालेट व्यवस्थापन उपकरण +Name[nl]=Portefeuillebeheer +Name[nn]=Wallet-administrasjonsverktøy +Name[pa]=ਵਾਲਿਟ ਪਰਬੰਧਨ ਸੰਦ +Name[pl]=Narzędzie do zarządzania Portfelem +Name[pt]=Ferramenta de Gestão da Carteira +Name[pt_BR]=Ferramenta de Gerenciamento da Carteira +Name[ro]=Administrare portofel +Name[ru]=Управление паролями +Name[sk]=Nástroj na správu KWallet +Name[sl]=Orodje za upravljanje z listnicami +Name[sr]=Алат за управљање новчаником +Name[sr@Latn]=Alat za upravljanje novčanikom +Name[sv]=Hanteringsverktyg för plånbok +Name[ta]=வாலட் மேலாண்மை கருவி +Name[tg]=Асбоби Идоракунии Ҳамён +Name[tr]=Cüzdan Yönetim Aracı +Name[uk]=Засіб керування торбинками +Name[uz]=Qopchiq boshqarish vositasi +Name[uz@cyrillic]=Қопчиқ бошқариш воситаси +Name[zh_CN]=钱包管理工具 +Name[zh_TW]=錢包管理工具 +Exec=kwalletmanager --show %u +MimeType=application/x-kde-wallet +InitialPreference=6 +Icon=kwalletmanager +Type=Service +X-KDE-StartupNotify=true diff --git a/kwallet/konfigurator/walletconfigwidget.ui b/kwallet/konfigurator/walletconfigwidget.ui new file mode 100644 index 0000000..797d569 --- /dev/null +++ b/kwallet/konfigurator/walletconfigwidget.ui @@ -0,0 +1,499 @@ + +WalletConfigWidget + + + WalletConfigWidget + + + + 0 + 0 + 585 + 450 + + + + + unnamed + + + 0 + + + + tabWidget2 + + + + tab + + + Wallet Preferences + + + + unnamed + + + + _enabled + + + &Enable the KDE wallet subsystem + + + true + + + <p>The wallet subsytem allows a convenient and secure way to manage all your passwords. You can decide if you want to use this system with this option.</p> + + + + + groupBox2 + + + Close Wallet + + + It is best to close your wallets when you are not using them to prevent others from viewing or using them. + + + + unnamed + + + + layout1 + + + + unnamed + + + + _closeIdle + + + + 1 + 0 + 2 + 0 + + + + Close when unused for: + + + <p><b>Close wallet after a period of inactivity</b><br>When a wallet is closed the password is needed to access it again.</p> + + + + + _idleTime + + + false + + + + 1 + 0 + 0 + 0 + + + + min + + + 999 + + + 1 + + + 5 + + + 10 + + + <p><b>Close wallet after a period of inactivity</b><br>When a wallet is closed the password is needed to access it again.</p> + + + + + spacer12 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + + + _screensaverLock + + + Close when screensaver starts + + + <p><b>Close wallet as soon as the screensaver starts.</b><br>When a wallet is closed the password is needed to access it again.</p> + + + + + _autoclose + + + Close when last application stops using it + + + <p><b>Close wallet as soon as applications that use it have stopped.</b><br>Note that your wallets will only be closed when all applications that use it have stopped.<br>When a wallet is closed the password is needed to access it again.</p> + + + + + + + groupBox4 + + + Automatic Wallet Selection + + + + unnamed + + + + spacer7 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + textLabel1_2 + + + Select wallet to use as default: + + + + + _localWalletSelected + + + Different wallet for local passwords: + + + + + _defaultWallet + + + + 1 + 0 + 1 + 0 + + + + + + _localWallet + + + false + + + + 1 + 0 + 1 + 0 + + + + + + _newLocalWallet + + + false + + + New... + + + + + _newWallet + + + New... + + + + + + + groupBox3 + + + Wallet Manager + + + + unnamed + + + + spacer6 + + + Horizontal + + + Fixed + + + + 20 + 20 + + + + + + _launchManager + + + Show manager in system tray + + + true + + + + + _autocloseManager + + + Hide system tray icon when last wallet closes + + + + + + + spacer4 + + + Vertical + + + Expanding + + + + 31 + 16 + + + + + + + + tab + + + Access Control + + + + unnamed + + + + _openPrompt + + + &Prompt when an application accesses an open wallet + + + true + + + + + + Wallet + + + true + + + true + + + true + + + + + Application + + + true + + + true + + + + + Policy + + + true + + + true + + + + _accessList + + + true + + + + + + + + _launch + + + &Launch Wallet Manager + + + + + spacer2 + + + Horizontal + + + Expanding + + + + 369 + 21 + + + + + + + + _localWalletSelected + toggled(bool) + _newLocalWallet + setEnabled(bool) + + + _localWalletSelected + toggled(bool) + _localWallet + setEnabled(bool) + + + _closeIdle + toggled(bool) + _idleTime + setEnabled(bool) + + + _enabled + toggled(bool) + groupBox2 + setEnabled(bool) + + + _enabled + toggled(bool) + groupBox4 + setEnabled(bool) + + + _enabled + toggled(bool) + groupBox3 + setEnabled(bool) + + + _closeIdle + toggled(bool) + _idleTime + setEnabled(bool) + + + _launchManager + toggled(bool) + _autocloseManager + setEnabled(bool) + + + + _enabled + _closeIdle + _idleTime + _screensaverLock + _autoclose + _defaultWallet + _newWallet + _localWalletSelected + _localWallet + _newLocalWallet + _launchManager + _autocloseManager + tabWidget2 + _openPrompt + _accessList + _launch + + + _storeTogether_toggled(bool) + + + diff --git a/kwallet/kwalleteditor.cpp b/kwallet/kwalleteditor.cpp new file mode 100644 index 0000000..d9e49d0 --- /dev/null +++ b/kwallet/kwalleteditor.cpp @@ -0,0 +1,1143 @@ +/* + Copyright (C) 2003-2005 George Staikos + Copyright (C) 2005 Isaac Clerencia + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include "kbetterthankdialogbase.h" +#include "kwalleteditor.h" +#include "kwmapeditor.h" +#include "allyourbase.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +KWalletEditor::KWalletEditor(const QString& wallet, bool isPath, QWidget *parent, const char *name) +: KMainWindow(parent, name), _walletName(wallet), _nonLocal(isPath) { + _newWallet = false; + _ww = new WalletWidget(this, "Wallet Widget"); + _copyPassAction = KStdAction::copy(this, SLOT(copyPassword()), actionCollection()); + + QVBoxLayout *box = new QVBoxLayout(_ww->_entryListFrame); + box->setSpacing( KDialog::spacingHint() ); + box->setMargin( KDialog::marginHint() ); + _entryList = new KWalletEntryList(_ww->_entryListFrame, "Wallet Entry List"); + box->addWidget(new KListViewSearchLineWidget(_entryList, _ww->_entryListFrame)); + box->addWidget(_entryList); + + _ww->_entryStack->setEnabled(true); + + box = new QVBoxLayout(_ww->_entryStack->widget(2)); + _mapEditorShowHide = new QCheckBox(i18n("&Show values"), _ww->_entryStack->widget(2)); + connect(_mapEditorShowHide, SIGNAL(toggled(bool)), this, SLOT(showHideMapEditorValue(bool))); + _mapEditor = new KWMapEditor(_currentMap, _ww->_entryStack->widget(2)); + box->addWidget(_mapEditorShowHide); + box->addWidget(_mapEditor); + + setCentralWidget(_ww); + + resize(600, 400); + + connect(_entryList, SIGNAL(selectionChanged(QListViewItem*)), + this, SLOT(entrySelectionChanged(QListViewItem*))); + connect(_entryList, + SIGNAL(contextMenuRequested(QListViewItem*,const QPoint&,int)), + this, + SLOT(listContextMenuRequested(QListViewItem*,const QPoint&,int))); + connect(_entryList, + SIGNAL(itemRenamed(QListViewItem*, int, const QString&)), + this, + SLOT(listItemRenamed(QListViewItem*, int, const QString&))); + + connect(_ww->_passwordValue, SIGNAL(textChanged()), + this, SLOT(entryEditted())); + connect(_mapEditor, SIGNAL(dirty()), + this, SLOT(entryEditted())); + + connect(_ww->_undoChanges, SIGNAL(clicked()), + this, SLOT(restoreEntry())); + connect(_ww->_saveChanges, SIGNAL(clicked()), + this, SLOT(saveEntry())); + + connect(_ww->_showContents, SIGNAL(clicked()), + this, SLOT(showPasswordContents())); + connect(_ww->_hideContents, SIGNAL(clicked()), + this, SLOT(hidePasswordContents())); + + _walletIsOpen = false; + + _w = KWallet::Wallet::openWallet(wallet, winId(), isPath ? KWallet::Wallet::Path : KWallet::Wallet::Asynchronous); + if (_w) { + connect(_w, SIGNAL(walletOpened(bool)), this, SLOT(walletOpened(bool))); + connect(_w, SIGNAL(walletClosed()), this, SLOT(walletClosed())); + connect(_w, SIGNAL(folderUpdated(const QString&)), this, SLOT(updateEntries(const QString&))); + connect(_w, SIGNAL(folderListUpdated()), this, SLOT(updateFolderList())); + updateFolderList(); + } else { + kdDebug(2300) << "Wallet open failed!" << endl; + } + + createActions(); + createGUI("kwalleteditor.rc"); + delete toolBar(); + + setCaption(wallet); + + QTimer::singleShot(0, this, SLOT(layout())); +} + +KWalletEditor::~KWalletEditor() { + emit editorClosed(this); + delete _newFolderAction; + _newFolderAction = 0L; + delete _deleteFolderAction; + _deleteFolderAction = 0L; + delete _w; + _w = 0L; + if (_nonLocal) { + KWallet::Wallet::closeWallet(_walletName, true); + } +} + +void KWalletEditor::layout() { + QValueList sz = _ww->_splitter->sizes(); + int sum = sz[0] + sz[1]; + sz[0] = sum/2; + sz[1] = sum/2; + _ww->_splitter->setSizes(sz); +} + +void KWalletEditor::createActions() { + _newFolderAction = new KAction(i18n("&New Folder..."), "folder_new", + 0, this, SLOT(createFolder()), actionCollection(), + "create_folder"); + connect(this, SIGNAL(enableFolderActions(bool)), + _newFolderAction, SLOT(setEnabled(bool))); + + _deleteFolderAction = new KAction(i18n("&Delete Folder"), 0, 0, + this, SLOT(deleteFolder()), actionCollection(), + "delete_folder"); + connect(this, SIGNAL(enableContextFolderActions(bool)), + _deleteFolderAction, SLOT(setEnabled(bool))); + connect(this, SIGNAL(enableFolderActions(bool)), + _deleteFolderAction, SLOT(setEnabled(bool))); + + _passwordAction = new KAction(i18n("Change &Password..."), 0, 0, this, + SLOT(changePassword()), actionCollection(), + "change_password"); + connect(this, SIGNAL(enableWalletActions(bool)), + _passwordAction, SLOT(setEnabled(bool))); + + _mergeAction = new KAction(i18n("&Merge Wallet..."), 0, 0, this, + SLOT(importWallet()), actionCollection(), + "merge"); + connect(this, SIGNAL(enableWalletActions(bool)), + _mergeAction, SLOT(setEnabled(bool))); + + _importAction = new KAction(i18n("&Import XML..."), 0, 0, this, + SLOT(importXML()), actionCollection(), + "import"); + connect(this, SIGNAL(enableWalletActions(bool)), + _importAction, SLOT(setEnabled(bool))); + + _exportAction = new KAction(i18n("&Export..."), 0, 0, this, + SLOT(exportXML()), actionCollection(), + "export"); + connect(this, SIGNAL(enableWalletActions(bool)), + _exportAction, SLOT(setEnabled(bool))); + + _saveAsAction = KStdAction::saveAs(this, SLOT(saveAs()), actionCollection()); + connect(this, SIGNAL(enableWalletActions(bool)), + _saveAsAction, SLOT(setEnabled(bool))); + + KStdAction::quit(this, SLOT(close()), actionCollection()); + KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), +actionCollection()); + emit enableWalletActions(false); + emit enableFolderActions(false); + emit enableContextFolderActions(false); +} + + +void KWalletEditor::walletClosed() { + delete _w; + _walletIsOpen = false; + _w = 0L; + _ww->setEnabled(false); + emit enableWalletActions(false); + emit enableFolderActions(false); + KMessageBox::sorry(this, i18n("This wallet was forced closed. You must reopen it to continue working with it.")); + deleteLater(); +} + + +void KWalletEditor::updateFolderList(bool checkEntries) { + QStringList fl = _w->folderList(); + QPtrStack trash; + + for (QListViewItem *i = _entryList->firstChild(); i; i = i->nextSibling()) { + KWalletFolderItem *fi = dynamic_cast(i); + if (!fi) { + continue; + } + if (!fl.contains(fi->name())) { + trash.push(i); + } + } + + trash.setAutoDelete(true); + trash.clear(); + + for (QStringList::Iterator i = fl.begin(); i != fl.end(); ++i) { + if (_entryList->existsFolder(*i)) { + if (checkEntries) { + updateEntries(*i); + } + continue; + } + + _w->setFolder(*i); + QStringList entries = _w->entryList(); + KWalletFolderItem *item = new KWalletFolderItem(_w,_entryList, + *i, entries.count()); + + KWalletContainerItem *pi = new KWalletContainerItem(item, i18n("Passwords"),KWallet::Wallet::Password); + KWalletContainerItem *mi = new KWalletContainerItem(item, i18n("Maps"),KWallet::Wallet::Map); + KWalletContainerItem *bi = new KWalletContainerItem(item, i18n("Binary Data"),KWallet::Wallet::Stream); + KWalletContainerItem *ui = new KWalletContainerItem(item, i18n("Unknown"),KWallet::Wallet::Unknown); + + for (QStringList::Iterator j = entries.begin(); j != entries.end(); ++j) { + switch (_w->entryType(*j)) { + case KWallet::Wallet::Password: + new KWalletEntryItem(_w, pi, *j); + break; + case KWallet::Wallet::Stream: + new KWalletEntryItem(_w, bi, *j); + break; + case KWallet::Wallet::Map: + new KWalletEntryItem(_w, mi, *j); + break; + case KWallet::Wallet::Unknown: + default: + new QListViewItem(ui, *j); + break; + } + } + _entryList->setEnabled(true); + } + + //check if the current folder has been removed + if (!fl.contains(_currentFolder)) { + _currentFolder = ""; + _ww->_entryTitle->clear(); + _ww->_iconTitle->clear(); + } +} + +void KWalletEditor::deleteFolder() { + if (_w) { + QListViewItem *i = _entryList->currentItem(); + if (i) { + KWalletFolderItem *fi = dynamic_cast(i); + if (!fi) { + return; + } + + int rc = KMessageBox::warningContinueCancel(this, i18n("Are you sure you wish to delete the folder '%1' from the wallet?").arg(fi->name()),"",KStdGuiItem::del()); + if (rc == KMessageBox::Continue) { + bool rc = _w->removeFolder(fi->name()); + if (!rc) { + KMessageBox::sorry(this, i18n("Error deleting folder.")); + return; + } + _currentFolder = ""; + _ww->_entryTitle->clear(); + _ww->_iconTitle->clear(); + updateFolderList(); + } + } + } +} + + +void KWalletEditor::createFolder() { + if (_w) { + QString n; + bool ok; + + do { + n = KInputDialog::getText(i18n("New Folder"), + i18n("Please choose a name for the new folder:"), + QString::null, + &ok, + this); + + if (!ok) { + return; + } + + if (_entryList->existsFolder(n)) { + int rc = KMessageBox::questionYesNo(this, i18n("Sorry, that folder name is in use. Try again?"), QString::null, i18n("Try Again"), i18n("Do Not Try")); + if (rc == KMessageBox::Yes) { + continue; + } + n = QString::null; + } + break; + } while (true); + + _w->createFolder(n); + updateFolderList(); + } +} + + +void KWalletEditor::saveEntry() { + int rc = 1; + QListViewItem *item = _entryList->currentItem(); + _ww->_saveChanges->setEnabled(false); + _ww->_undoChanges->setEnabled(false); + + if (item && _w && item->parent()) { + KWalletContainerItem *ci = dynamic_cast(item->parent()); + if (ci) { + if (ci->type() == KWallet::Wallet::Password) { + rc = _w->writePassword(item->text(0), _ww->_passwordValue->text()); + } else if (ci->type() == KWallet::Wallet::Map) { + _mapEditor->saveMap(); + rc = _w->writeMap(item->text(0), _currentMap); + } else { + return; + } + + if (rc == 0) { + return; + } + } + } + + KMessageBox::sorry(this, i18n("Error saving entry. Error code: %1").arg(rc)); +} + + +void KWalletEditor::restoreEntry() { + entrySelectionChanged(_entryList->currentItem()); +} + + +void KWalletEditor::entryEditted() { + _ww->_saveChanges->setEnabled(true); + _ww->_undoChanges->setEnabled(true); +} + + +void KWalletEditor::entrySelectionChanged(QListViewItem *item) { + KWalletContainerItem *ci = 0L; + KWalletFolderItem *fi = 0L; + + switch (item->rtti()) { + case KWalletEntryItemClass: + ci = dynamic_cast(item->parent()); + if (!ci) { + return; + } + fi = dynamic_cast(ci->parent()); + if (!fi) { + return; + } + _w->setFolder(fi->name()); + _deleteFolderAction->setEnabled(false); + if (ci->type() == KWallet::Wallet::Password) { + QString pass; + if (_w->readPassword(item->text(0), pass) == 0) { + _ww->_entryStack->raiseWidget(int(4)); + _ww->_entryName->setText(i18n("Password: %1") + .arg(item->text(0))); + _ww->_passwordValue->setText(pass); + _ww->_saveChanges->setEnabled(false); + _ww->_undoChanges->setEnabled(false); + } + } else if (ci->type() == KWallet::Wallet::Map) { + _ww->_entryStack->raiseWidget(int(2)); + _mapEditorShowHide->setChecked(false); + showHideMapEditorValue(false); + if (_w->readMap(item->text(0), _currentMap) == 0) { + _mapEditor->reload(); + _ww->_entryName->setText(i18n("Name-Value Map: %1").arg(item->text(0))); + _ww->_saveChanges->setEnabled(false); + _ww->_undoChanges->setEnabled(false); + } + } else if (ci->type() == KWallet::Wallet::Stream) { + _ww->_entryStack->raiseWidget(int(3)); + QByteArray ba; + if (_w->readEntry(item->text(0), ba) == 0) { + _ww->_entryName->setText(i18n("Binary Data: %1") + .arg(item->text(0))); + _ww->_saveChanges->setEnabled(false); + _ww->_undoChanges->setEnabled(false); + } + } + break; + + case KWalletContainerItemClass: + fi = dynamic_cast(item->parent()); + if (!fi) { + return; + } + _w->setFolder(fi->name()); + _deleteFolderAction->setEnabled(false); + _ww->_entryName->clear(); + _ww->_entryStack->raiseWidget(int(0)); + break; + + case KWalletFolderItemClass: + fi = dynamic_cast(item); + if (!fi) { + return; + } + _w->setFolder(fi->name()); + _deleteFolderAction->setEnabled(true); + _ww->_entryName->clear(); + _ww->_entryStack->raiseWidget(int(0)); + break; + } + + if (fi) { + _currentFolder = fi->name(); + _ww->_entryTitle->setText(QString("%1").arg(fi->text(0))); + _ww->_iconTitle->setPixmap(fi->getFolderIcon(KIcon::Toolbar)); + } +} + +void KWalletEditor::updateEntries(const QString& folder) { + QPtrStack trash; + + _w->setFolder(folder); + QStringList entries = _w->entryList(); + + KWalletFolderItem *fi = _entryList->getFolder(folder); + + if (!fi) { + return; + } + + KWalletContainerItem *pi = fi->getContainer(KWallet::Wallet::Password); + KWalletContainerItem *mi = fi->getContainer(KWallet::Wallet::Map); + KWalletContainerItem *bi = fi->getContainer(KWallet::Wallet::Stream); + KWalletContainerItem *ui = fi->getContainer(KWallet::Wallet::Unknown); + + // Remove deleted entries + for (QListViewItem *i = pi->firstChild(); i; i = i->nextSibling()) { + if (!entries.contains(i->text(0))) { + if (i == _entryList->currentItem()) { + entrySelectionChanged(0L); + } + trash.push(i); + } + } + + for (QListViewItem *i = mi->firstChild(); i; i = i->nextSibling()) { + if (!entries.contains(i->text(0))) { + if (i == _entryList->currentItem()) { + entrySelectionChanged(0L); + } + trash.push(i); + } + } + + for (QListViewItem *i = bi->firstChild(); i; i = i->nextSibling()) { + if (!entries.contains(i->text(0))) { + if (i == _entryList->currentItem()) { + entrySelectionChanged(0L); + } + trash.push(i); + } + } + + for (QListViewItem *i = ui->firstChild(); i; i = i->nextSibling()) { + if (!entries.contains(i->text(0))) { + if (i == _entryList->currentItem()) { + entrySelectionChanged(0L); + } + trash.push(i); + } + } + + trash.setAutoDelete(true); + trash.clear(); + + // Add new entries + for (QStringList::Iterator i = entries.begin(); i != entries.end(); ++i) { + if (fi->contains(*i)){ + continue; + } + + switch (_w->entryType(*i)) { + case KWallet::Wallet::Password: + new KWalletEntryItem(_w, pi, *i); + break; + case KWallet::Wallet::Stream: + new KWalletEntryItem(_w, bi, *i); + break; + case KWallet::Wallet::Map: + new KWalletEntryItem(_w, mi, *i); + break; + case KWallet::Wallet::Unknown: + default: + new QListViewItem(ui, *i); + break; + } + } + fi->refresh(); + if (fi->name() == _currentFolder) { + _ww->_entryTitle->setText(QString("%1").arg(fi->text(0))); + } + if (!_entryList->selectedItem()) { + _ww->_entryName->clear(); + _ww->_entryStack->raiseWidget(int(0)); + } +} + +void KWalletEditor::listContextMenuRequested(QListViewItem *item, const QPoint& pos, int col) { + Q_UNUSED(col) + + if (!_walletIsOpen) { + return; + } + + KWalletListItemClasses menuClass = KWalletUnknownClass; + KWalletContainerItem *ci = 0L; + + if (item) { + if (item->rtti() == KWalletEntryItemClass) { + ci = dynamic_cast(item->parent()); + if (!ci) { + return; + } + } else if (item->rtti() == KWalletContainerItemClass) { + ci = dynamic_cast(item); + if (!ci) { + return; + } + } + + if (ci && ci->type() == KWallet::Wallet::Unknown) { + return; + } + menuClass = static_cast(item->rtti()); + } + + KPopupMenu *m = new KPopupMenu(this); + if (item) { + QString title = item->text(0); + // I think 200 pixels is wide enough for a title + title = KStringHandler::cPixelSqueeze(title, m->fontMetrics(), 200); + m->insertTitle(title); + switch (menuClass) { + case KWalletEntryItemClass: + m->insertItem(i18n("&New..." ), this, SLOT(newEntry()), Key_Insert); + m->insertItem(i18n( "&Rename" ), this, SLOT(renameEntry()), Key_F2); + m->insertItem(i18n( "&Delete" ), this, SLOT(deleteEntry()), Key_Delete); + if (ci && ci->type() == KWallet::Wallet::Password) { + m->insertSeparator(); + _copyPassAction->plug(m); + } + break; + + case KWalletContainerItemClass: + m->insertItem(i18n( "&New..." ), this, SLOT(newEntry()), Key_Insert); + break; + + case KWalletFolderItemClass: + _newFolderAction->plug(m); + _deleteFolderAction->plug(m); + break; + default: + abort(); + } + } else { + _newFolderAction->plug(m); + } + m->popup(pos); +} + + +void KWalletEditor::copyPassword() { + QListViewItem *item = _entryList->selectedItem(); + if (_w && item) { + QString pass; + if (_w->readPassword(item->text(0), pass) == 0) { + QApplication::clipboard()->setText(pass); + } + } +} + + +void KWalletEditor::newEntry() { + QListViewItem *item = _entryList->selectedItem(); + QString n; + bool ok; + + QListViewItem *p; + KWalletFolderItem *fi; + + //set the folder where we're trying to create the new entry + if (_w && item) { + p = item; + if (p->rtti() == KWalletEntryItemClass) { + p = item->parent(); + } + fi = dynamic_cast(p->parent()); + if (!fi) { + return; + } + _w->setFolder(fi->name()); + } else { + return; + } + + do { + n = KInputDialog::getText(i18n("New Entry"), + i18n("Please choose a name for the new entry:"), + QString::null, + &ok, + this); + + if (!ok) { + return; + } + + // FIXME: prohibits the use of the subheadings + if (fi->contains(n)) { + int rc = KMessageBox::questionYesNo(this, i18n("Sorry, that entry already exists. Try again?"), QString::null, i18n("Try Again"), i18n("Do Not Try")); + if (rc == KMessageBox::Yes) { + continue; + } + n = QString::null; + } + break; + } while (true); + + if (_w && item && !n.isEmpty()) { + QListViewItem *p = item; + if (p->rtti() == KWalletEntryItemClass) { + p = item->parent(); + } + + KWalletFolderItem *fi = dynamic_cast(p->parent()); + if (!fi) { + KMessageBox::error(this, i18n("An unexpected error occurred trying to add the new entry")); + return; + } + _w->setFolder(fi->name()); + + KWalletEntryItem *ni = new KWalletEntryItem(_w, p, n); + _entryList->setSelected(ni,true); + _entryList->ensureItemVisible(ni); + + KWalletContainerItem *ci = dynamic_cast(p); + if (!ci) { + KMessageBox::error(this, i18n("An unexpected error occurred trying to add the new entry")); + return; + } + if (ci->type() == KWallet::Wallet::Password) { + _w->writePassword(n, QString::null); + } else if (ci->type() == KWallet::Wallet::Map) { + _w->writeMap(n, QMap()); + } else if (ci->type() == KWallet::Wallet::Stream) { + _w->writeEntry(n, QByteArray()); + } else { + abort(); + } + fi->refresh(); + _ww->_entryTitle->setText(QString("%1").arg(fi->text(0))); + } +} + + +void KWalletEditor::renameEntry() { + QListViewItem *item = _entryList->selectedItem(); + if (_w && item) { + item->startRename(0); + } +} + + +// Only supports renaming of KWalletEntryItem derived classes. +void KWalletEditor::listItemRenamed(QListViewItem* item, int, const QString& t) { + if (item) { + KWalletEntryItem *i = dynamic_cast(item); + if (!i) { + return; + } + + if (!_w || t.isEmpty()) { + i->setText(0, i->oldName()); + return; + } + + if (_w->renameEntry(i->oldName(), t) == 0) { + i->clearOldName(); + KWalletContainerItem *ci = dynamic_cast(item->parent()); + if (!ci) { + KMessageBox::error(this, i18n("An unexpected error occurred trying to rename the entry")); + return; + } + if (ci->type() == KWallet::Wallet::Password) { + _ww->_entryName->setText(i18n("Password: %1").arg(item->text(0))); + } else if (ci->type() == KWallet::Wallet::Map) { + _ww->_entryName->setText(i18n("Name-Value Map: %1").arg(item->text(0))); + } else if (ci->type() == KWallet::Wallet::Stream) { + _ww->_entryName->setText(i18n("Binary Data: %1").arg(item->text(0))); + } + } else { + i->setText(0, i->oldName()); + } + } +} + + +void KWalletEditor::deleteEntry() { + QListViewItem *item = _entryList->selectedItem(); + if (_w && item) { + int rc = KMessageBox::warningContinueCancel(this, i18n("Are you sure you wish to delete the item '%1'?").arg(item->text(0)),"",KStdGuiItem::del()); + if (rc == KMessageBox::Continue) { + KWalletFolderItem *fi = dynamic_cast(item->parent()->parent()); + if (!fi) { + KMessageBox::error(this, i18n("An unexpected error occurred trying to delete the entry")); + return; + } + _w->removeEntry(item->text(0)); + delete item; + entrySelectionChanged(_entryList->currentItem()); + fi->refresh(); + _ww->_entryTitle->setText(QString("%1").arg(fi->text(0))); + } + } +} + +void KWalletEditor::changePassword() { + KWallet::Wallet::changePassword(_walletName); +} + + +void KWalletEditor::walletOpened(bool success) { + if (success) { + emit enableFolderActions(true); + emit enableContextFolderActions(false); + emit enableWalletActions(true); + updateFolderList(); + show(); + _entryList->setWallet(_w); + _walletIsOpen = true; + } else { + if (!_newWallet) { + KMessageBox::sorry(this, i18n("Unable to open the requested wallet.")); + } + close(); + } +} + + +void KWalletEditor::hidePasswordContents() { + _ww->_entryStack->raiseWidget(int(4)); +} + + +void KWalletEditor::showPasswordContents() { + _ww->_entryStack->raiseWidget(int(1)); +} + + +void KWalletEditor::showHideMapEditorValue(bool show) { + if (show) { + _mapEditor->showColumn(2); + } else { + _mapEditor->hideColumn(2); + } +} + + +enum MergePlan { Prompt = 0, Always = 1, Never = 2, Yes = 3, No = 4 }; + +void KWalletEditor::importWallet() { + KURL url = KFileDialog::getOpenURL(QString::null, "*.kwl", this); + if (url.isEmpty()) { + return; + } + + QString tmpFile; + if (!KIO::NetAccess::download(url, tmpFile, this)) { + KMessageBox::sorry(this, i18n("Unable to access wallet '%1'.").arg(url.prettyURL())); + return; + } + + KWallet::Wallet *w = KWallet::Wallet::openWallet(tmpFile, winId(), KWallet::Wallet::Path); + if (w && w->isOpen()) { + MergePlan mp = Prompt; + QStringList fl = w->folderList(); + for (QStringList::ConstIterator f = fl.constBegin(); f != fl.constEnd(); ++f) { + if (!w->setFolder(*f)) { + continue; + } + + if (!_w->hasFolder(*f)) { + _w->createFolder(*f); + } + + _w->setFolder(*f); + + QMap > map; + int rc; + rc = w->readMapList("*", map); + if (rc == 0) { + QMap >::ConstIterator me; + for (me = map.constBegin(); me != map.constEnd(); ++me) { + bool hasEntry = _w->hasEntry(me.key()); + if (hasEntry && mp == Prompt) { + KBetterThanKDialogBase *bd; + bd = new KBetterThanKDialogBase(this); + bd->setLabel(i18n("Folder '%1' already contains an entry '%2'. Do you wish to replace it?").arg(QStyleSheet::escape(*f)).arg(QStyleSheet::escape(me.key()))); + mp = (MergePlan)bd->exec(); + delete bd; + bool ok = false; + if (mp == Always || mp == Yes) { + ok = true; + } + if (mp == Yes || mp == No) { + // reset mp + mp = Prompt; + } + if (!ok) { + continue; + } + } else if (hasEntry && mp == Never) { + continue; + } + _w->writeMap(me.key(), me.data()); + } + } + + QMap pwd; + rc = w->readPasswordList("*", pwd); + if (rc == 0) { + QMap::ConstIterator pe; + for (pe = pwd.constBegin(); pe != pwd.constEnd(); ++pe) { + bool hasEntry = _w->hasEntry(pe.key()); + if (hasEntry && mp == Prompt) { + KBetterThanKDialogBase *bd; + bd = new KBetterThanKDialogBase(this); + bd->setLabel(i18n("Folder '%1' already contains an entry '%2'. Do you wish to replace it?").arg(QStyleSheet::escape(*f)).arg(QStyleSheet::escape(pe.key()))); + mp = (MergePlan)bd->exec(); + delete bd; + bool ok = false; + if (mp == Always || mp == Yes) { + ok = true; + } + if (mp == Yes || mp == No) { + // reset mp + mp = Prompt; + } + if (!ok) { + continue; + } + } else if (hasEntry && mp == Never) { + continue; + } + _w->writePassword(pe.key(), pe.data()); + } + } + + QMap ent; + rc = w->readEntryList("*", ent); + if (rc == 0) { + QMap::ConstIterator ee; + for (ee = ent.constBegin(); ee != ent.constEnd(); ++ee) { + bool hasEntry = _w->hasEntry(ee.key()); + if (hasEntry && mp == Prompt) { + KBetterThanKDialogBase *bd; + bd = new KBetterThanKDialogBase(this); + bd->setLabel(i18n("Folder '%1' already contains an entry '%2'. Do you wish to replace it?").arg(QStyleSheet::escape(*f)).arg(QStyleSheet::escape(ee.key()))); + mp = (MergePlan)bd->exec(); + delete bd; + bool ok = false; + if (mp == Always || mp == Yes) { + ok = true; + } + if (mp == Yes || mp == No) { + // reset mp + mp = Prompt; + } + if (!ok) { + continue; + } + } else if (hasEntry && mp == Never) { + continue; + } + _w->writeEntry(ee.key(), ee.data()); + } + } + } + } + + delete w; + + KIO::NetAccess::removeTempFile(tmpFile); + updateFolderList(true); + restoreEntry(); +} + + +void KWalletEditor::importXML() { + KURL url = KFileDialog::getOpenURL(QString::null, "*.xml", this); + if (url.isEmpty()) { + return; + } + + QString tmpFile; + if (!KIO::NetAccess::download(url, tmpFile, this)) { + KMessageBox::sorry(this, i18n("Unable to access XML file '%1'.").arg(url.prettyURL())); + return; + } + + QFile qf(tmpFile); + if (!qf.open(IO_ReadOnly)) { + KMessageBox::sorry(this, i18n("Error opening XML file '%1' for input.").arg(url.prettyURL())); + KIO::NetAccess::removeTempFile(tmpFile); + return; + } + + QDomDocument doc(tmpFile); + if (!doc.setContent(&qf)) { + KMessageBox::sorry(this, i18n("Error reading XML file '%1' for input.").arg(url.prettyURL())); + KIO::NetAccess::removeTempFile(tmpFile); + return; + } + + QDomElement top = doc.documentElement(); + if (top.tagName().lower() != "wallet") { + KMessageBox::sorry(this, i18n("Error: XML file does not contain a wallet.")); + KIO::NetAccess::removeTempFile(tmpFile); + return; + } + + QDomNode n = top.firstChild(); + MergePlan mp = Prompt; + while (!n.isNull()) { + QDomElement e = n.toElement(); + if (e.tagName().lower() != "folder") { + n = n.nextSibling(); + continue; + } + + QString fname = e.attribute("name"); + if (fname.isEmpty()) { + n = n.nextSibling(); + continue; + } + if (!_w->hasFolder(fname)) { + _w->createFolder(fname); + } + _w->setFolder(fname); + QDomNode enode = e.firstChild(); + while (!enode.isNull()) { + e = enode.toElement(); + QString type = e.tagName().lower(); + QString ename = e.attribute("name"); + bool hasEntry = _w->hasEntry(ename); + if (hasEntry && mp == Prompt) { + KBetterThanKDialogBase *bd; + bd = new KBetterThanKDialogBase(this); + bd->setLabel(i18n("Folder '%1' already contains an entry '%2'. Do you wish to replace it?").arg(QStyleSheet::escape(fname)).arg(QStyleSheet::escape(ename))); + mp = (MergePlan)bd->exec(); + delete bd; + bool ok = false; + if (mp == Always || mp == Yes) { + ok = true; + } + if (mp == Yes || mp == No) { // reset mp + mp = Prompt; + } + if (!ok) { + enode = enode.nextSibling(); + continue; + } + } else if (hasEntry && mp == Never) { + enode = enode.nextSibling(); + continue; + } + + if (type == "password") { + _w->writePassword(ename, e.text()); + } else if (type == "stream") { + _w->writeEntry(ename, KCodecs::base64Decode(e.text().latin1())); + } else if (type == "map") { + QMap map; + QDomNode mapNode = e.firstChild(); + while (!mapNode.isNull()) { + QDomElement mape = mapNode.toElement(); + if (mape.tagName().lower() == "mapentry") { + map[mape.attribute("name")] = mape.text(); + } + mapNode = mapNode.nextSibling(); + } + _w->writeMap(ename, map); + } + enode = enode.nextSibling(); + } + n = n.nextSibling(); + } + + KIO::NetAccess::removeTempFile(tmpFile); + updateFolderList(true); + restoreEntry(); +} + + +void KWalletEditor::exportXML() { + KTempFile tf; + tf.setAutoDelete(true); + QTextStream& ts(*tf.textStream()); + QStringList fl = _w->folderList(); + + ts << "" << endl; + for (QStringList::Iterator i = fl.begin(); i != fl.end(); ++i) { + ts << " " << endl; + _w->setFolder(*i); + QStringList entries = _w->entryList(); + for (QStringList::Iterator j = entries.begin(); j != entries.end(); ++j) { + switch (_w->entryType(*j)) { + case KWallet::Wallet::Password: + { + QString pass; + if (_w->readPassword(*j, pass) == 0) { + ts << " "; + ts << QStyleSheet::escape(pass); + ts << "" << endl; + } + break; + } + case KWallet::Wallet::Stream: + { + QByteArray ba; + if (_w->readEntry(*j, ba) == 0) { + ts << " "; + ts << KCodecs::base64Encode(ba); + + ts << "" << endl; + } + break; + } + case KWallet::Wallet::Map: + { + QMap map; + if (_w->readMap(*j, map) == 0) { + ts << " " << endl; + for (QMap::ConstIterator k = map.begin(); k != map.end(); ++k) { + ts << " " << QStyleSheet::escape(k.data()) << "" << endl; + } + ts << " " << endl; + } + break; + } + case KWallet::Wallet::Unknown: + default: + break; + } + } + ts << " " << endl; + } + + ts << "" << endl; + tf.close(); + + KURL url = KFileDialog::getSaveURL(QString::null, "*.xml", this); + + if (!url.isEmpty()) { + bool ok = true; + if (KIO::NetAccess::exists(url, false, this)) { + int rc = KMessageBox::warningContinueCancel(this, i18n("The file '%1' already exists. Would you like to overwrite this file?").arg(url.prettyURL()), i18n("Overwrite")); + if (rc == KMessageBox::Cancel) { + ok = false; + } + } + if (ok) { + KURL tfURL; tfURL.setPath(tf.name()); + KIO::NetAccess::file_copy(tfURL, url, 0600, true, false, this); + } + } +} + + +void KWalletEditor::setNewWallet(bool x) { + _newWallet = x; +} + + +void KWalletEditor::saveAs() { + KURL url = KFileDialog::getSaveURL(QString::null, "*.kwl", this); + if (!url.isEmpty()) { + // Sync() kwalletd + if (_nonLocal) { + KIO::NetAccess::file_copy(KURL(_walletName), url, 0600, false, false, this); + } else { + QString path = KGlobal::dirs()->saveLocation("kwallet") + "/" + _walletName + ".kwl"; + KURL destURL; destURL.setPath(path); + KIO::NetAccess::file_copy(destURL, url, 0600, false, false, this); + } + } +} + + +#include "kwalleteditor.moc" + diff --git a/kwallet/kwalleteditor.h b/kwallet/kwalleteditor.h new file mode 100644 index 0000000..2a3c9ef --- /dev/null +++ b/kwallet/kwalleteditor.h @@ -0,0 +1,110 @@ +/* + Copyright (C) 2003-2005 George Staikos + Copyright (C) 2005 Isaac Clerencia + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KWALLETEDITOR_H +#define KWALLETEDITOR_H + +#include "walletwidget.h" +#include +#include +#include + +class KAction; +class QIconViewItem; +class QListViewItem; +class QCheckBox; +class KWalletFolderIconView; +class KWalletEntryList; +class KWMapEditor; + +class KWalletEditor : public KMainWindow { + Q_OBJECT + + public: + KWalletEditor(const QString& wallet, bool isPath, QWidget *parent = 0, const char* name = 0); + virtual ~KWalletEditor(); + + bool isOpen() const { return _w != 0L; } + + void setNewWallet(bool newWallet); + + public slots: + void walletClosed(); + void createFolder(); + void deleteFolder(); + + private slots: + void layout(); + void updateFolderList(bool checkEntries = false); + void entrySelectionChanged(QListViewItem *item); + void listItemRenamed(QListViewItem *, int, const QString&); + void listContextMenuRequested(QListViewItem *item, const QPoint& pos, int col); + void updateEntries(const QString& folder); + + void newEntry(); + void renameEntry(); + void deleteEntry(); + void entryEditted(); + void restoreEntry(); + void saveEntry(); + + void changePassword(); + + void walletOpened(bool success); + void hidePasswordContents(); + void showPasswordContents(); + void showHideMapEditorValue(bool show); + + void saveAs(); + void exportXML(); + void importXML(); + void importWallet(); + + void copyPassword(); + + signals: + void enableWalletActions(bool enable); + void enableFolderActions(bool enable); + void enableContextFolderActions(bool enable); + void editorClosed(KMainWindow*); + + public: + QString _walletName; + + private: + void createActions(); + bool _nonLocal; + KWallet::Wallet *_w; + WalletWidget *_ww; + KWalletEntryList *_entryList; + bool _walletIsOpen; + KAction *_newFolderAction, *_deleteFolderAction; + KAction *_passwordAction, *_exportAction, *_saveAsAction, *_mergeAction, *_importAction; + KAction *_copyPassAction; + QLabel*_details; + QString _currentFolder; + QMap _currentMap; // save memory by storing + // only the most recent map. + KWMapEditor *_mapEditor; + QCheckBox *_mapEditorShowHide; + bool _newWallet; +}; + +#endif diff --git a/kwallet/kwalleteditor.rc b/kwallet/kwalleteditor.rc new file mode 100644 index 0000000..9c4faf5 --- /dev/null +++ b/kwallet/kwalleteditor.rc @@ -0,0 +1,17 @@ + + + + &File + + + + + + + + + + &Help + + + diff --git a/kwallet/kwalletmanager-kwalletd.desktop b/kwallet/kwalletmanager-kwalletd.desktop new file mode 100644 index 0000000..e9d38ac --- /dev/null +++ b/kwallet/kwalletmanager-kwalletd.desktop @@ -0,0 +1,60 @@ +[Desktop Entry] +Name=Wallet Management Tool +Name[ar]=أداة إدارة المحفظة +Name[bg]=Портфейл +Name[br]=Merour an doug-paperoù +Name[bs]=Alat za upravljanje novčanikom +Name[ca]=Eina de gestió de carteres +Name[cs]=Nástroj pro správu úschovny +Name[cy]=Erfyn Rheoli Waled +Name[da]=Håndteringsværktøj for tegnebog +Name[de]=Verwaltung für digitale Brieftasche +Name[el]=Εργαλείο διαχείρισης πορτοφολιού +Name[es]=Herramienta de gestión de cartera +Name[et]=Turvalaeka haldur +Name[eu]=Kartera Kudeatzeko Tresna +Name[fa]=ابزار مدیریت Wallet +Name[fi]=Lompakon hallintatyökalu +Name[fr]=Outil de gestion de comptes +Name[ga]=Uirlis Bhainisteoireachta Wallet +Name[he]=כלי לניהול הארנק של KDE +Name[hi]= बटुआ प्रबंधन औज़ार +Name[hu]=Kezelőprogram a KDE digitális noteszeihez +Name[is]=Tól til að stýra eiginleikum veskisins +Name[it]=Strumento per la gestione dei portafogli +Name[ja]=ウォレット管理ツール +Name[ka]=Wallet-ის მმართველი მოწყობილობა +Name[kk]=Әмиянін басқару құралы +Name[km]=ឧបករណ៍​គ្រប់គ្រង​កាបូប +Name[lt]=Spatažodinių tvarkymo įrankis +Name[mk]=Алатка за менаџирање на паричници +Name[nb]=Wallet administrasjonsverktøy +Name[nds]=Knipp-Pleger +Name[ne]=वालेट व्यवस्थापन उपकरण +Name[nl]=Portefeuillebeheer +Name[nn]=Wallet-administrasjonsverktøy +Name[pa]=ਵਾਲਿਟ ਪਰਬੰਧਨ ਸੰਦ +Name[pl]=Narzędzie do zarządzania Portfelem +Name[pt]=Ferramenta de Gestão da Carteira +Name[pt_BR]=Ferramenta de Gerenciamento da Carteira +Name[ro]=Administrare portofel +Name[ru]=Управление паролями +Name[sk]=Nástroj na správu KWallet +Name[sl]=Orodje za upravljanje z listnicami +Name[sr]=Алат за управљање новчаником +Name[sr@Latn]=Alat za upravljanje novčanikom +Name[sv]=Hanteringsverktyg för plånbok +Name[ta]=வாலட் மேலாண்மை கருவி +Name[tg]=Асбоби Идоракунии Ҳамён +Name[tr]=Cüzdan Yönetim Aracı +Name[uk]=Засіб керування торбинками +Name[uz]=Qopchiq boshqarish vositasi +Name[uz@cyrillic]=Қопчиқ бошқариш воситаси +Name[zh_CN]=钱包管理工具 +Name[zh_TW]=錢包管理工具 +Exec=kwalletmanager --kwalletd +Icon=kwalletmanager +Type=Application +Terminal=false +X-KDE-StartupNotify=false +NoDisplay=true diff --git a/kwallet/kwalletmanager.cpp b/kwallet/kwalletmanager.cpp new file mode 100644 index 0000000..a4fe6cf --- /dev/null +++ b/kwallet/kwalletmanager.cpp @@ -0,0 +1,423 @@ +/* + Copyright (C) 2003,2004 George Staikos + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include "kwalletmanager.h" +#include "kwalletpopup.h" +#include "kwalleteditor.h" +#include "allyourbase.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +KWalletManager::KWalletManager(QWidget *parent, const char *name, WFlags f) +: KMainWindow(parent, name, f), DCOPObject("KWalletManager") { + KGlobal::dirs()->addResourceType("kwallet", "share/apps/kwallet"); + _kwalletdLaunch = false; + QAccel *accel = new QAccel(this, "kwalletmanager"); + + KApplication::dcopClient()->setQtBridgeEnabled(false); + _shuttingDown = false; + KConfig cfg("kwalletrc"); // not sure why this setting isn't in kwalletmanagerrc... + KConfigGroup walletConfigGroup(&cfg, "Wallet"); + _dcopRef = 0L; + if (walletConfigGroup.readBoolEntry("Launch Manager", true)) { + _tray = new KSystemTray(this, "kwalletmanager tray"); + _tray->setPixmap(loadSystemTrayIcon("wallet_closed")); + QToolTip::add(_tray, i18n("KDE Wallet: No wallets open.")); + connect(_tray, SIGNAL(quitSelected()), SLOT(shuttingDown())); + QStringList wl = KWallet::Wallet::walletList(); + bool isOpen = false; + for (QStringList::Iterator it = wl.begin(); it != wl.end(); ++it) { + if (KWallet::Wallet::isOpen(*it)) { + _tray->setPixmap(loadSystemTrayIcon("wallet_open")); + QToolTip::remove(_tray); + QToolTip::add(_tray, i18n("KDE Wallet: A wallet is open.")); + isOpen = true; + break; + } + } + if (!isOpen && kapp->isRestored()) { + delete _tray; + _tray = 0L; + QTimer::singleShot( 0, kapp, SLOT( quit())); + return; + } + } else { + _tray = 0L; + } + + _iconView = new KWalletIconView(this, "kwalletmanager icon view"); + connect(_iconView, SIGNAL(executed(QIconViewItem*)), this, SLOT(openWallet(QIconViewItem*))); + connect(_iconView, SIGNAL(contextMenuRequested(QIconViewItem*, const QPoint&)), this, SLOT(contextMenu(QIconViewItem*, const QPoint&))); + + updateWalletDisplay(); + setCentralWidget(_iconView); + _iconView->setMinimumSize(320, 200); + + _dcopRef = new DCOPRef("kded", "kwalletd"); + _dcopRef->dcopClient()->setNotifications(true); + connect(_dcopRef->dcopClient(), + SIGNAL(applicationRemoved(const QCString&)), + this, + SLOT(possiblyRescan(const QCString&))); + connect(_dcopRef->dcopClient(), + SIGNAL(applicationRegistered(const QCString&)), + this, + SLOT(possiblyRescan(const QCString&))); + + connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "allWalletsClosed()", "allWalletsClosed()", false); + connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "walletClosed(QString)", "updateWalletDisplay()", false); + connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "walletOpened(QString)", "aWalletWasOpened()", false); + connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "walletDeleted(QString)", "updateWalletDisplay()", false); + connectDCOPSignal(_dcopRef->app(), _dcopRef->obj(), "walletListDirty()", "updateWalletDisplay()", false); + + // FIXME: slight race - a wallet can open, then we get launched, but the + // wallet closes before we are done opening. We will then stay + // open. Must check that a wallet is still open here. + + new KAction(i18n("&New Wallet..."), "kwalletmanager", 0, this, + SLOT(createWallet()), actionCollection(), + "wallet_create"); + KAction *act = new KAction(i18n("Configure &Wallet..."), "configure", + 0, this, SLOT(setupWallet()), actionCollection(), + "wallet_settings"); + if (_tray) { + act->plug(_tray->contextMenu()); + } + act = new KAction(i18n("Close &All Wallets"), 0, 0, this, + SLOT(closeAllWallets()), actionCollection(), + "close_all_wallets"); + if (_tray) { + act->plug(_tray->contextMenu()); + } + KStdAction::quit(this, SLOT(shuttingDown()), actionCollection()); + KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), +actionCollection()); + + createGUI("kwalletmanager.rc"); + accel->connectItem(accel->insertItem(Key_Return), this, SLOT(openWallet())); + accel->connectItem(accel->insertItem(Key_Delete), this, SLOT(deleteWallet())); + + if (_tray) { + _tray->show(); + } else { + show(); + } + + kapp->setName("kwallet"); // hack to fix docs +} + + +KWalletManager::~KWalletManager() { + _tray = 0L; + delete _dcopRef; + _dcopRef = 0L; +} + + +void KWalletManager::kwalletdLaunch() { + _kwalletdLaunch = true; +} + + +bool KWalletManager::queryClose() { + if (!_shuttingDown && !kapp->sessionSaving()) { + if (!_tray) { + kapp->quit(); + } else { + hide(); + } + return false; + } + return true; +} + + +void KWalletManager::aWalletWasOpened() { + if (_tray) { + _tray->setPixmap(loadSystemTrayIcon("wallet_open")); + QToolTip::remove(_tray); + QToolTip::add(_tray, i18n("KDE Wallet: A wallet is open.")); + } + updateWalletDisplay(); +} + + +void KWalletManager::updateWalletDisplay() { +QStringList wl = KWallet::Wallet::walletList(); +QPtrStack trash; + + for (QIconViewItem *item = _iconView->firstItem(); item; item = item->nextItem()) { + if (!wl.contains(item->text())) { + trash.push(item); + } + } + + trash.setAutoDelete(true); + trash.clear(); + + for (QStringList::Iterator i = wl.begin(); i != wl.end(); ++i) { + if (!_iconView->findItem(*i)) { + // FIXME: if KWallet::Wallet::isOpen(*i) then show + // a different icon! + new KWalletItem(_iconView, *i); + } else { + // FIXME: See if icon needs to be updated + } + } +} + + +void KWalletManager::contextMenu(QIconViewItem *item, const QPoint& pos) { + if (item) { + QGuardedPtr popupMenu = new KWalletPopup(item->text(), this); + connect(popupMenu, SIGNAL(walletOpened(const QString&)), this, SLOT(openWallet(const QString&))); + connect(popupMenu, SIGNAL(walletClosed(const QString&)), this, SLOT(closeWallet(const QString&))); + connect(popupMenu, SIGNAL(walletDeleted(const QString&)), this, SLOT(deleteWallet(const QString&))); + connect(popupMenu, SIGNAL(walletChangePassword(const QString&)), this, SLOT(changeWalletPassword(const QString&))); + connect(popupMenu, SIGNAL(walletCreated()), this, SLOT(createWallet())); + popupMenu->exec(pos); + delete popupMenu; + } +} + + +void KWalletManager::deleteWallet(const QString& walletName) { + int rc = KMessageBox::warningContinueCancel(this, i18n("Are you sure you wish to delete the wallet '%1'?").arg(walletName),"",KStdGuiItem::del()); + if (rc != KMessageBox::Continue) { + return; + } + rc = KWallet::Wallet::deleteWallet(walletName); + if (rc != 0) { + KMessageBox::sorry(this, i18n("Unable to delete the wallet. Error code was %1.").arg(rc)); + } + updateWalletDisplay(); +} + + +void KWalletManager::closeWallet(const QString& walletName) { + int rc = KWallet::Wallet::closeWallet(walletName, false); + if (rc != 0) { + rc = KMessageBox::warningYesNo(this, i18n("Unable to close wallet cleanly. It is probably in use by other applications. Do you wish to force it closed?"), QString::null, i18n("Force Closure"), i18n("Do Not Force")); + if (rc == KMessageBox::Yes) { + rc = KWallet::Wallet::closeWallet(walletName, true); + if (rc != 0) { + KMessageBox::sorry(this, i18n("Unable to force the wallet closed. Error code was %1.").arg(rc)); + } + } + } + + updateWalletDisplay(); +} + + +void KWalletManager::changeWalletPassword(const QString& walletName) { + KWallet::Wallet::changePassword(walletName); +} + + +void KWalletManager::openWalletFile(const QString& path) { + KWalletEditor *we = new KWalletEditor(path, true, this, "Wallet Editor"); + if (we->isOpen()) { + connect(we, SIGNAL(editorClosed(KMainWindow*)), + this, SLOT(editorClosed(KMainWindow*))); + we->show(); + } else { + KMessageBox::sorry(this, i18n("Error opening wallet %1.").arg(path)); + delete we; + } +} + + +void KWalletManager::openWallet() { + QIconViewItem *item = _iconView->currentItem(); + openWallet(item); +} + +void KWalletManager::deleteWallet() { + QIconViewItem *item = _iconView->currentItem(); + if (item) { + deleteWallet(item->text()); + } +} + + +void KWalletManager::openWallet(const QString& walletName) { + openWallet(walletName, false); +} + + +void KWalletManager::openWallet(const QString& walletName, bool newWallet) { + // Don't allow a wallet to open in two windows + for (KMainWindow *w = _windows.first(); w; w = _windows.next()) { + KWalletEditor *e = static_cast(w); + if (e->isOpen() && e->_walletName == walletName) { + w->raise(); + return; + } + } + + KWalletEditor *we = new KWalletEditor(walletName, false, this, "Wallet Editor"); + we->setNewWallet(newWallet); + if (we->isOpen()) { + connect(we, SIGNAL(editorClosed(KMainWindow*)), + this, SLOT(editorClosed(KMainWindow*))); + we->show(); + _windows.append(we); + } else if (!newWallet) { + KMessageBox::sorry(this, i18n("Error opening wallet %1.").arg(walletName)); + delete we; + } +} + + +void KWalletManager::openWallet(QIconViewItem *item) { + if (item) { + openWallet(item->text()); + } +} + + +void KWalletManager::allWalletsClosed() { + if (_tray) { + _tray->setPixmap(loadSystemTrayIcon("wallet_closed")); + QToolTip::remove(_tray); + QToolTip::add(_tray, i18n("KDE Wallet: No wallets open.")); + } + possiblyQuit(); +} + + +void KWalletManager::possiblyQuit() { + KConfig cfg("kwalletrc"); + cfg.setGroup("Wallet"); + if (_windows.isEmpty() && + !isVisible() && + !cfg.readBoolEntry("Leave Manager Open", false) && + _kwalletdLaunch) { + kapp->quit(); + } +} + + +void KWalletManager::editorClosed(KMainWindow* e) { + _windows.remove(e); +} + + +void KWalletManager::possiblyRescan(const QCString& app) { + if (app == "kded") { + updateWalletDisplay(); + } +} + + +void KWalletManager::createWallet() { + QString n; + bool ok; + // FIXME: support international names + QRegExp regexp("^[A-Za-z0-9]+[A-Za-z0-9_\\s\\-]*$"); + QString txt = i18n("Please choose a name for the new wallet:"); + + if (!KWallet::Wallet::isEnabled()) { + // FIXME: KMessageBox::warningYesNo(this, i1_8n("KWallet is not enabled. Do you want to enable it?"), QString::null, i18n("Enable"), i18n("Keep Disabled")); + return; + } + + do { + n = KInputDialog::getText(i18n("New Wallet"), + txt, + QString::null, + &ok, + this); + + if (!ok) { + return; + } + + if (_iconView->findItem(n)) { + int rc = KMessageBox::questionYesNo(this, i18n("Sorry, that wallet already exists. Try a new name?"), QString::null, i18n("Try New"), i18n("Do Not Try")); + if (rc == KMessageBox::Yes) { + continue; + } + n = QString::null; + } else if (regexp.exactMatch(n)) { + break; + } else { + txt = i18n("Please choose a name that contains only alphanumeric characters:"); + } + } while (true); + + // Small race here - the wallet could be created on us already. + if (!n.isEmpty()) { + openWallet(n, true); + } +} + + +void KWalletManager::shuttingDown() { + _shuttingDown = true; + kapp->quit(); +} + + +void KWalletManager::setupWallet() { + KApplication::startServiceByDesktopName("kwallet_config"); +} + + +void KWalletManager::closeAllWallets() { + _dcopRef->call("closeAllWallets"); +} + + +QPixmap KWalletManager::loadSystemTrayIcon(const QString &icon) { +#if KDE_IS_VERSION(3, 1, 90) + return KSystemTray::loadIcon(icon); +#else + KConfig *appCfg = kapp->config(); + KConfigGroupSaver configSaver(appCfg, "System Tray"); + int iconWidth = appCfg->readNumEntry("systrayIconWidth", 22); + return kapp->iconLoader()->loadIcon( icon, KIcon::Panel, iconWidth ); +#endif +} + + +#include "kwalletmanager.moc" diff --git a/kwallet/kwalletmanager.desktop b/kwallet/kwalletmanager.desktop new file mode 100644 index 0000000..7884977 --- /dev/null +++ b/kwallet/kwalletmanager.desktop @@ -0,0 +1,63 @@ +[Desktop Entry] +Name=Wallet Management Tool +Name[ar]=أداة إدارة المحفظة +Name[bg]=Портфейл +Name[br]=Merour an doug-paperoù +Name[bs]=Alat za upravljanje novčanikom +Name[ca]=Eina de gestió de carteres +Name[cs]=Nástroj pro správu úschovny +Name[cy]=Erfyn Rheoli Waled +Name[da]=Håndteringsværktøj for tegnebog +Name[de]=Verwaltung für digitale Brieftasche +Name[el]=Εργαλείο διαχείρισης πορτοφολιού +Name[es]=Herramienta de gestión de cartera +Name[et]=Turvalaeka haldur +Name[eu]=Kartera Kudeatzeko Tresna +Name[fa]=ابزار مدیریت Wallet +Name[fi]=Lompakon hallintatyökalu +Name[fr]=Outil de gestion de comptes +Name[ga]=Uirlis Bhainisteoireachta Wallet +Name[he]=כלי לניהול הארנק של KDE +Name[hi]= बटुआ प्रबंधन औज़ार +Name[hu]=Kezelőprogram a KDE digitális noteszeihez +Name[is]=Tól til að stýra eiginleikum veskisins +Name[it]=Strumento per la gestione dei portafogli +Name[ja]=ウォレット管理ツール +Name[ka]=Wallet-ის მმართველი მოწყობილობა +Name[kk]=Әмиянін басқару құралы +Name[km]=ឧបករណ៍​គ្រប់គ្រង​កាបូប +Name[lt]=Spatažodinių tvarkymo įrankis +Name[mk]=Алатка за менаџирање на паричници +Name[nb]=Wallet administrasjonsverktøy +Name[nds]=Knipp-Pleger +Name[ne]=वालेट व्यवस्थापन उपकरण +Name[nl]=Portefeuillebeheer +Name[nn]=Wallet-administrasjonsverktøy +Name[pa]=ਵਾਲਿਟ ਪਰਬੰਧਨ ਸੰਦ +Name[pl]=Narzędzie do zarządzania Portfelem +Name[pt]=Ferramenta de Gestão da Carteira +Name[pt_BR]=Ferramenta de Gerenciamento da Carteira +Name[ro]=Administrare portofel +Name[ru]=Управление паролями +Name[sk]=Nástroj na správu KWallet +Name[sl]=Orodje za upravljanje z listnicami +Name[sr]=Алат за управљање новчаником +Name[sr@Latn]=Alat za upravljanje novčanikom +Name[sv]=Hanteringsverktyg för plånbok +Name[ta]=வாலட் மேலாண்மை கருவி +Name[tg]=Асбоби Идоракунии Ҳамён +Name[tr]=Cüzdan Yönetim Aracı +Name[uk]=Засіб керування торбинками +Name[uz]=Qopchiq boshqarish vositasi +Name[uz@cyrillic]=Қопчиқ бошқариш воситаси +Name[zh_CN]=钱包管理工具 +Name[zh_TW]=錢包管理工具 +Exec=kwalletmanager %u +MimeType=application/x-kde-wallet; +InitialPreference=6 +Icon=kwalletmanager +Type=Application +Terminal=false +X-KDE-StartupNotify=false +Categories=Qt;KDE;Settings; +DocPath=kwallet/index.html diff --git a/kwallet/kwalletmanager.h b/kwallet/kwalletmanager.h new file mode 100644 index 0000000..0c28839 --- /dev/null +++ b/kwallet/kwalletmanager.h @@ -0,0 +1,84 @@ +/* + Copyright (C) 2003,2004 George Staikos + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KWALLETMANAGER_H +#define KWALLETMANAGER_H + +#include +#include +#include + +class KSystemTray; +class KWalletIconView; +class QIconViewItem; +class DCOPRef; + + +class KWalletManager : public KMainWindow, public DCOPObject { + Q_OBJECT + K_DCOP + + public: + KWalletManager(QWidget *parent = 0, const char* name = 0, WFlags f = 0); + virtual ~KWalletManager(); + + QPixmap loadSystemTrayIcon(const QString &icon); + + void kwalletdLaunch(); + + public slots: + void createWallet(); + void deleteWallet(const QString& walletName); + void closeWallet(const QString& walletName); + void changeWalletPassword(const QString& walletName); + void openWallet(const QString& walletName); + void openWallet(const QString& walletName, bool newWallet); + void openWalletFile(const QString& path); + void openWallet(QIconViewItem *item); + void contextMenu(QIconViewItem *item, const QPoint& pos); + + protected: + virtual bool queryClose(); + + private: + k_dcop: + ASYNC allWalletsClosed(); + ASYNC updateWalletDisplay(); + ASYNC aWalletWasOpened(); + + private slots: + void shuttingDown(); + void possiblyQuit(); + void editorClosed(KMainWindow* e); + void possiblyRescan(const QCString& app); + void setupWallet(); + void openWallet(); + void deleteWallet(); + void closeAllWallets(); + + private: + KSystemTray *_tray; + bool _shuttingDown; + KWalletIconView *_iconView; + DCOPRef *_dcopRef; + QPtrList _windows; + bool _kwalletdLaunch; +}; + +#endif diff --git a/kwallet/kwalletmanager.rc b/kwallet/kwalletmanager.rc new file mode 100644 index 0000000..a1fd2c8 --- /dev/null +++ b/kwallet/kwalletmanager.rc @@ -0,0 +1,14 @@ + + + + &File + + + + &Settings + + + &Help + + + diff --git a/kwallet/kwalletpopup.cpp b/kwallet/kwalletpopup.cpp new file mode 100644 index 0000000..3f2082e --- /dev/null +++ b/kwallet/kwalletpopup.cpp @@ -0,0 +1,110 @@ +/* + Copyright (C) 2003 George Staikos + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include "kwalletpopup.h" + +#include +#include +#include +#include +#include +#include +#include + +KWalletPopup::KWalletPopup(const QString& wallet, QWidget *parent, const char *name) +: KPopupMenu(parent, name), _walletName(wallet) { + insertTitle(wallet); + KActionCollection *ac = new KActionCollection(this, "kwallet context actions"); + KAction *act; + + act = new KAction(i18n("&New Wallet..."), 0, 0, this, + SLOT(createWallet()), ac, "wallet_create"); + act->plug(this); + + act = new KAction(i18n("&Open..."), 0, Key_Return, this, + SLOT(openWallet()), ac, "wallet_open"); + act->plug(this); + + act = new KAction(i18n("Change &Password..."), 0, 0, this, + SLOT(changeWalletPassword()), ac, "wallet_password"); + act->plug(this); + + QStringList ul = KWallet::Wallet::users(wallet); + if (!ul.isEmpty()) { + KPopupMenu *pm = new KPopupMenu(this, "Disconnect Apps"); + int id = 7000; + for (QStringList::Iterator it = ul.begin(); it != ul.end(); ++it) { + _appMap[id] = *it; + pm->insertItem(*it, this, SLOT(disconnectApp(int)), 0, id); + pm->setItemParameter(id, id); + id++; + } + + insertItem(i18n("Disconnec&t"), pm); + } + + act = KStdAction::close( this, + SLOT(closeWallet()), ac, "wallet_close"); + // FIXME: let's track this inside the manager so we don't need a dcop + // roundtrip here. + act->setEnabled(KWallet::Wallet::isOpen(wallet)); + act->plug(this); + + act = new KAction(i18n("&Delete"), 0, Key_Delete, this, + SLOT(deleteWallet()), ac, "wallet_delete"); + act->plug(this); +} + + +KWalletPopup::~KWalletPopup() { +} + + +void KWalletPopup::openWallet() { + emit walletOpened(_walletName); +} + + +void KWalletPopup::deleteWallet() { + emit walletDeleted(_walletName); +} + + +void KWalletPopup::closeWallet() { + emit walletClosed(_walletName); +} + + +void KWalletPopup::changeWalletPassword() { + emit walletChangePassword(_walletName); +} + + +void KWalletPopup::createWallet() { + emit walletCreated(); +} + + +void KWalletPopup::disconnectApp(int id) { + KWallet::Wallet::disconnectApplication(_walletName, _appMap[id].latin1()); +} + +#include "kwalletpopup.moc" + diff --git a/kwallet/kwalletpopup.h b/kwallet/kwalletpopup.h new file mode 100644 index 0000000..c704d69 --- /dev/null +++ b/kwallet/kwalletpopup.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2003 George Staikos + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KWALLETPOPUP_H +#define KWALLETPOPUP_H + +#include +#include +#include + +class KWalletPopup : public KPopupMenu { + Q_OBJECT + + public: + KWalletPopup(const QString& wallet, QWidget *parent = 0, const char* name = 0); + virtual ~KWalletPopup(); + + public slots: + void openWallet(); + void deleteWallet(); + void closeWallet(); + void createWallet(); + void changeWalletPassword(); + void disconnectApp(int); + + signals: + void walletOpened(const QString& walletName); + void walletClosed(const QString& walletName); + void walletDeleted(const QString& walletName); + void walletCreated(); + void walletChangePassword(const QString& walletName); + + private: + QString _walletName; + QMap _appMap; +}; + +#endif diff --git a/kwallet/kwmapeditor.cpp b/kwallet/kwmapeditor.cpp new file mode 100644 index 0000000..a15b9c9 --- /dev/null +++ b/kwallet/kwmapeditor.cpp @@ -0,0 +1,187 @@ +/* + Copyright (C) 2003,2004 George Staikos + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kwmapeditor.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +KWMapEditor::KWMapEditor(QMap& map, QWidget *parent, const char *name) +: QTable(0, 3, parent, name), _map(map) { + _ac = new KActionCollection(this); + _copyAct = KStdAction::copy(this, SLOT(copy()), _ac); + connect(this, SIGNAL(valueChanged(int,int)), this, SIGNAL(dirty())); + connect(this, SIGNAL(contextMenuRequested(int,int,const QPoint&)), + this, SLOT(contextMenu(int,int,const QPoint&))); + setSelectionMode(QTable::NoSelection); + horizontalHeader()->setLabel(0, QString::null); + horizontalHeader()->setLabel(1, i18n("Key")); + horizontalHeader()->setLabel(2, i18n("Value")); + setColumnWidth(0, 20); // FIXME: this is arbitrary + reload(); +} + +void KWMapEditor::reload() { + unsigned row = 0; + + while ((row = numRows()) > _map.count()) { + removeRow(row - 1); + } + + if ((row = numRows()) < _map.count()) { + insertRows(row, _map.count() - row); + for (int x = row; x < numRows(); ++x) { + QPushButton *b = new QPushButton("X", this); + connect(b, SIGNAL(clicked()), this, SLOT(erase())); + setCellWidget(x, 0, b); + } + } + + row = 0; + for (QMap::Iterator it = _map.begin(); it != _map.end(); ++it) { + setText(row, 1, it.key()); + setText(row, 2, it.data()); + row++; + } +} + + +KWMapEditor::~KWMapEditor() { +} + + +void KWMapEditor::erase() { + const QObject *o = sender(); + for (int i = 0; i < numRows(); i++) { + if (cellWidget(i, 0) == o) { + removeRow(i); + break; + } + } + + emit dirty(); +} + + +void KWMapEditor::saveMap() { + _map.clear(); + + for (int i = 0; i < numRows(); i++) { + _map[text(i, 1)] = text(i, 2); + } +} + + +void KWMapEditor::addEntry() { + int x = numRows(); + insertRows(x, 1); + QPushButton *b = new QPushButton("X", this); + connect(b, SIGNAL(clicked()), this, SLOT(erase())); + setCellWidget(x, 0, b); + ensureCellVisible(x, 1); + setCurrentCell(x, 1); + emit dirty(); +} + + +void KWMapEditor::emitDirty() { + emit dirty(); +} + + +void KWMapEditor::contextMenu(int row, int col, const QPoint& pos) { + _contextRow = row; + _contextCol = col; + KPopupMenu *m = new KPopupMenu(this); + m->insertItem(i18n("&New Entry"), this, SLOT(addEntry())); + _copyAct->plug(m); + m->popup(pos); +} + + +void KWMapEditor::copy() { + QApplication::clipboard()->setText(text(_contextRow, 2)); +} + + +class InlineEditor : public QTextEdit { + public: + InlineEditor(KWMapEditor *p, int row, int col) + : QTextEdit(), _p(p), row(row), col(col) { + setWFlags(WStyle_NoBorder | WDestructiveClose); + KWin::setType(winId(), NET::Override); + connect(p, SIGNAL(destroyed()), SLOT(close())); + } + virtual ~InlineEditor() { if (!_p) return; _p->setText(row, col, text()); _p->emitDirty(); } + + protected: + virtual void focusOutEvent(QFocusEvent*) { + if (QFocusEvent::reason() == QFocusEvent::Popup) { + QWidget *focusW = qApp->focusWidget(); + if (focusW && focusW == popup) { + return; + } + } + close(); + } + virtual void keyPressEvent(QKeyEvent *e) { + if (e->key() == Qt::Key_Escape) { + e->accept(); + close(); + } else { + e->ignore(); + QTextEdit::keyPressEvent(e); + } + } + virtual QPopupMenu *createPopupMenu(const QPoint &p) { + popup = QTextEdit::createPopupMenu(p); + return popup; + } + QGuardedPtr _p; + int row, col; + QGuardedPtr popup; +}; + + +QWidget *KWMapEditor::beginEdit(int row, int col, bool replace) { + //kdDebug(2300) << "EDIT COLUMN " << col << endl; + if (col != 2) { + return QTable::beginEdit(row, col, replace); + } + + QRect geo = cellGeometry(row, col); + QTextEdit *e = new InlineEditor(this, row, col); + e->setText(text(row, col)); + e->move(mapToGlobal(geo.topLeft())); + e->resize(geo.width() * 2, geo.height() * 3); + e->show(); + return e; +} + + +#include "kwmapeditor.moc" diff --git a/kwallet/kwmapeditor.h b/kwallet/kwmapeditor.h new file mode 100644 index 0000000..8322a91 --- /dev/null +++ b/kwallet/kwmapeditor.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2003,2004 George Staikos + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KWMAPEDITOR_H +#define KWMAPEDITOR_H + +#include +#include +#include + +class KAction; +class KActionCollection; + +class KWMapEditor : public QTable { + Q_OBJECT + + public: + KWMapEditor(QMap& map, QWidget *parent = 0, const char *name = 0); + virtual ~KWMapEditor(); + + public slots: + void reload(); + void saveMap(); + void erase(); + void contextMenu(int row, int col, const QPoint& pos); + void addEntry(); + void emitDirty(); + + private slots: + void copy(); + + protected: + virtual QWidget *beginEdit(int row, int col, bool replace); + + signals: + void dirty(); + + private: + QMap& _map; + int _contextRow, _contextCol; + KActionCollection *_ac; + KAction *_copyAct; +}; + +#endif diff --git a/kwallet/main.cpp b/kwallet/main.cpp new file mode 100644 index 0000000..08f5b74 --- /dev/null +++ b/kwallet/main.cpp @@ -0,0 +1,100 @@ +/* + Copyright (C) 2003-2005 George Staikos + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "kwalletmanager.h" + + +class MyApp : public KUniqueApplication { + public: + MyApp() : KUniqueApplication() { ref(); } + virtual ~MyApp() {} + + virtual int newInstance() { return 0; } +}; + +int main(int argc, char **argv) { + static KCmdLineOptions options[] = { + {"show", I18N_NOOP("Show window on startup"), 0}, + {"kwalletd", I18N_NOOP("For use by kwalletd only"), 0}, + {"+name", I18N_NOOP("A wallet name"), 0}, + KCmdLineLastOption + }; + + KAboutData about("kwalletmanager", I18N_NOOP("KDE Wallet Manager"), "1.1", + I18N_NOOP("KDE Wallet Management Tool"), + KAboutData::License_GPL, + I18N_NOOP("(c) 2003,2004 George Staikos"), 0, + "http://www.kde.org/"); + + about.addAuthor("George Staikos", I18N_NOOP("Primary author and maintainer"), "staikos@kde.org"); + about.addAuthor("Isaac Clerencia", I18N_NOOP("Developer"), "isaac@warp.es"); + + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions(options); + + if (!KUniqueApplication::start()) { + return 0; + } + + MyApp a; + + KWalletManager wm; + wm.setCaption(i18n("KDE Wallet Manager")); + + a.setMainWidget(&wm); + + KGlobal::dirs()->addResourceType("kwallet", "share/apps/kwallet"); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + if (args->isSet("show")) { + wm.show(); + } + + if (args->isSet("kwalletd")) { + wm.kwalletdLaunch(); + } + + for (int i = 0; i < args->count(); ++i) { + QString fn = QFileInfo(args->arg(i)).absFilePath(); + KMimeType::Ptr ptr; + if (QFile::exists(fn) && + (ptr = KMimeType::findByFileContent(fn)) && + ptr->is("application/x-kde-wallet")) { + wm.openWalletFile(fn); + } else { + wm.openWallet(args->arg(i)); + } + } + args->clear(); + return a.exec(); +} + diff --git a/kwallet/walletwidget.ui b/kwallet/walletwidget.ui new file mode 100644 index 0000000..13c6f71 --- /dev/null +++ b/kwallet/walletwidget.ui @@ -0,0 +1,416 @@ + +WalletWidget + + + WalletWidget + + + + 0 + 0 + 614 + 507 + + + + + unnamed + + + 0 + + + + _splitter + + + Horizontal + + + + _entryListFrame + + + + 5 + 5 + 0 + 0 + + + + NoFrame + + + Plain + + + + + layout3 + + + + unnamed + + + + _entryName + + + + 5 + 1 + 0 + 0 + + + + + + + PlainText + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 227 + 21 + + + + + + _undoChanges + + + false + + + &Undo + + + "undo" + + + + + layout2 + + + + unnamed + + + + _iconTitle + + + + 1 + 1 + 0 + 0 + + + + + + + + + _entryTitle + + + + 7 + 1 + 0 + 0 + + + + + 1 + + + + + + + RichText + + + AlignVCenter + + + + + + + _saveChanges + + + false + + + &Save + + + "filesave" + + + + + _entryStack + + + + 5 + 5 + 0 + 1 + + + + + page + + + 0 + + + + + page + + + 1 + + + + unnamed + + + 0 + + + + _passwordValue + + + PlainText + + + + + spacer8 + + + Horizontal + + + Expanding + + + + 271 + 20 + + + + + + _hideContents + + + Hide &Contents + + + + + + + page + + + 2 + + + + + page + + + 3 + + + + unnamed + + + 0 + + + + textLabel1_2 + + + This is a binary data entry. It cannot be editted as its format is unknown and application specific. + + + WordBreak|AlignVCenter + + + + + spacer3 + + + Vertical + + + Expanding + + + + 31 + 41 + + + + + + spacer4 + + + Vertical + + + Expanding + + + + 31 + 41 + + + + + + spacer5 + + + Horizontal + + + Expanding + + + + 61 + 41 + + + + + + spacer6 + + + Horizontal + + + Expanding + + + + 41 + 21 + + + + + + + + page + + + 4 + + + + unnamed + + + 0 + + + + spacer7 + + + Horizontal + + + Expanding + + + + 236 + 21 + + + + + + spacer6_2 + + + Vertical + + + Expanding + + + + 31 + 358 + + + + + + _showContents + + + Show &Contents + + + + + + + + + + + + kdialog.h + kiconloader.h + +SmallIconSet + + + diff --git a/superkaramba/AUTHORS b/superkaramba/AUTHORS new file mode 100644 index 0000000..bb78990 --- /dev/null +++ b/superkaramba/AUTHORS @@ -0,0 +1,49 @@ +AUTHORS: + +Adam Geitgey + - SuperKaramba + +Hans Karlsson + - Original Karamba + +MAJOR CONTRIBUTORS: + +Wilfried Huss + - Lots and lots of Python API Functions + - Various patches + +Ralph Churchill + - RSS Sensor (easy headline display): + - Various patches + +Ryan Nickell + +Petri Damstn + +Ivica Ico Bukvic +http://meowing.ccm.uc.edu/~ico/ + - Various additions/fixes + +Sarah Elan + +Luke Kenneth Casson Leighton + - Python API functions, theme inter-communication + - Karamba "object"-style auto-wrapper to OO-itise python interface + - drag-drop receives x,y coordinates of mouse at drop time. + +HELP, PATCHES, AND EXISTING CODE: + +Matthias Elter + - used his awesome TaskManager class for SuperKaramba task support + +Vova Kuznetsov + +Alexander Wiedenbruch - Patches and Testing + +Scott Grayban - Mandriva RPM Packager + +THANKS: + +The graphics in the welcome dialog are derived from crystalsvg icons by +everaldo + diff --git a/superkaramba/COPYING b/superkaramba/COPYING new file mode 100644 index 0000000..5b44d80 --- /dev/null +++ b/superkaramba/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/superkaramba/ChangeLog b/superkaramba/ChangeLog new file mode 100644 index 0000000..d337f3b --- /dev/null +++ b/superkaramba/ChangeLog @@ -0,0 +1,710 @@ +------------------------------------------------------------------------ +r417080 | nickell | 2005-05-22 15:17:29 -0400 (Sun, 22 May 2005) | 2 lines + +Initial upload of SuperKaramba to kdereview. + +------------------------------------------------------------------------ +r417089 | nickell | 2005-05-22 15:38:16 -0400 (Sun, 22 May 2005) | 2 lines + +Removal of some generated files. + +------------------------------------------------------------------------ +r417105 | nickell | 2005-05-22 16:11:26 -0400 (Sun, 22 May 2005) | 2 lines + +Update/correct license information. + +------------------------------------------------------------------------ +r417170 | thiago | 2005-05-22 19:03:33 -0400 (Sun, 22 May 2005) | 7 lines + +Get it to compile. +1) $(TOPSRCDIRS) is lot allowed anymore +2) since the generated files were removed, the .ui file names have to be + listed + +CCMAIL:p0z3r@earthlink.net + +------------------------------------------------------------------------ +r417171 | thiago | 2005-05-22 19:04:17 -0400 (Sun, 22 May 2005) | 1 line + +Adding proper svn:ignores +------------------------------------------------------------------------ +r417220 | mattr | 2005-05-22 23:17:34 -0400 (Sun, 22 May 2005) | 7 lines + +use $(XMMS_LDFLAGS) and $(XMMS_LDADD) instead of $(XMMS_LIBS) so that +unsermake doesn't give an error about -rdynamic in LDADD. + +Also remove all the .h files from the SOURCES line. + + + +------------------------------------------------------------------------ +r417373 | pdamsten | 2005-05-23 10:17:19 -0400 (Mon, 23 May 2005) | 1 line + +ui files should compile now. +------------------------------------------------------------------------ +r417531 | pdamsten | 2005-05-23 17:13:15 -0400 (Mon, 23 May 2005) | 1 line + +more compatible with svn dir structure +------------------------------------------------------------------------ +r417533 | pdamsten | 2005-05-23 17:13:38 -0400 (Mon, 23 May 2005) | 1 line + +XMMS_LDADD fix +------------------------------------------------------------------------ +r417545 | pdamsten | 2005-05-23 17:38:27 -0400 (Mon, 23 May 2005) | 1 line + +Should work now +------------------------------------------------------------------------ +r417548 | pdamsten | 2005-05-23 17:44:25 -0400 (Mon, 23 May 2005) | 1 line + +ThemeListWindow -> ThemeListWindowLayout +------------------------------------------------------------------------ +r417640 | nickell | 2005-05-24 00:10:04 -0400 (Tue, 24 May 2005) | 2 lines + +Include xpm.h from X11 instead of redistributing it in our source. + +------------------------------------------------------------------------ +r417648 | pdamsten | 2005-05-24 02:24:03 -0400 (Tue, 24 May 2005) | 1 line + +more compatible with svn dir structure +------------------------------------------------------------------------ +r417649 | binner | 2005-05-24 02:25:28 -0400 (Tue, 24 May 2005) | 2 lines + +Add GenericName + +------------------------------------------------------------------------ +r417650 | binner | 2005-05-24 02:28:33 -0400 (Tue, 24 May 2005) | 2 lines + +Fix layout (or better: give it one), style guide fixes + +------------------------------------------------------------------------ +r417653 | binner | 2005-05-24 02:32:14 -0400 (Tue, 24 May 2005) | 2 lines + +SVN_SILENT includemocs + +------------------------------------------------------------------------ +r417654 | binner | 2005-05-24 02:33:22 -0400 (Tue, 24 May 2005) | 2 lines + +missing i18n, style guide fixes + +------------------------------------------------------------------------ +r417655 | binner | 2005-05-24 02:35:22 -0400 (Tue, 24 May 2005) | 2 lines + +SVN_SILENT silence + +------------------------------------------------------------------------ +r417677 | pdamsten | 2005-05-24 05:02:26 -0400 (Tue, 24 May 2005) | 1 line + +Added LineParser class +------------------------------------------------------------------------ +r417681 | pdamsten | 2005-05-24 05:16:42 -0400 (Tue, 24 May 2005) | 1 line + +Added LineParser class +------------------------------------------------------------------------ +r417948 | nickell | 2005-05-24 21:46:18 -0400 (Tue, 24 May 2005) | 2 lines + +Making it clear what this example does and showing it exists in README. + +------------------------------------------------------------------------ +r417952 | nickell | 2005-05-24 22:10:22 -0400 (Tue, 24 May 2005) | 2 lines + +Get rid of the rectangle around the latest themes. + +------------------------------------------------------------------------ +r418293 | pdamsten | 2005-05-26 02:07:40 -0400 (Thu, 26 May 2005) | 1 line + +commandFinished callback added +------------------------------------------------------------------------ +r418956 | pdamsten | 2005-05-28 04:13:01 -0400 (Sat, 28 May 2005) | 1 line + +ThemeFile class added +------------------------------------------------------------------------ +r418972 | pdamsten | 2005-05-28 04:57:14 -0400 (Sat, 28 May 2005) | 1 line + +Old unneeded files +------------------------------------------------------------------------ +r418973 | pdamsten | 2005-05-28 04:58:04 -0400 (Sat, 28 May 2005) | 1 line + +xml index file support to skz themes +------------------------------------------------------------------------ +r419386 | pdamsten | 2005-05-29 06:24:45 -0400 (Sun, 29 May 2005) | 1 line + +KIO::NetAccess support for themes. +------------------------------------------------------------------------ +r419557 | pdamsten | 2005-05-29 16:19:15 -0400 (Sun, 29 May 2005) | 1 line + +Use much simpler locateLocal to get local dir for themes. +------------------------------------------------------------------------ +------------------------------------------------------------------------ +r421058 | nickell | 2005-06-01 22:39:54 -0400 (Wed, 01 Jun 2005) | 7 lines + +Adding options to display kilobytes and kilobits. +network sensor kilobits example: +FORMAT="%inkb" +disk sensor kilobits and then kilobytes example: +FORMAT="%fkb" +FORMAT="%fk" + +------------------------------------------------------------------------ +r421194 | coles | 2005-06-02 09:02:06 -0400 (Thu, 02 Jun 2005) | 5 lines + +SVN_SILENT + +Corrected typo (missing question mark). + + +------------------------------------------------------------------------ +r421446 | pdamsten | 2005-06-03 01:54:22 -0400 (Fri, 03 Jun 2005) | 1 line + +New theme list dialog. +------------------------------------------------------------------------ +r421447 | pdamsten | 2005-06-03 01:55:32 -0400 (Fri, 03 Jun 2005) | 1 line + +icon support for skz files. +------------------------------------------------------------------------ +r421448 | pdamsten | 2005-06-03 01:56:08 -0400 (Fri, 03 Jun 2005) | 1 line + +New theme list dialog. +------------------------------------------------------------------------ +r421449 | pdamsten | 2005-06-03 01:56:44 -0400 (Fri, 03 Jun 2005) | 1 line + +These are not needed anymore because of the new theme list dialog. +------------------------------------------------------------------------ +r421450 | pdamsten | 2005-06-03 01:57:49 -0400 (Fri, 03 Jun 2005) | 1 line + +New widget listbox class for the theme list window. +------------------------------------------------------------------------ +r421457 | pdamsten | 2005-06-03 03:01:44 -0400 (Fri, 03 Jun 2005) | 1 line + +Save user added themes to config file. +------------------------------------------------------------------------ +r421472 | pdamsten | 2005-06-03 03:58:55 -0400 (Fri, 03 Jun 2005) | 1 line + +KConfigXT files. +------------------------------------------------------------------------ +r421480 | pdamsten | 2005-06-03 04:27:04 -0400 (Fri, 03 Jun 2005) | 1 line + +useless debug message removed. +------------------------------------------------------------------------ +r421494 | pdamsten | 2005-06-03 05:16:17 -0400 (Fri, 03 Jun 2005) | 1 line + +fileExists function added. +------------------------------------------------------------------------ +r421495 | pdamsten | 2005-06-03 05:17:04 -0400 (Fri, 03 Jun 2005) | 1 line + +Don't import python module unless it exists. +------------------------------------------------------------------------ +r421518 | pdamsten | 2005-06-03 06:11:06 -0400 (Fri, 03 Jun 2005) | 1 line + +use id for config file name instead of name +------------------------------------------------------------------------ +r421534 | pdamsten | 2005-06-03 06:58:50 -0400 (Fri, 03 Jun 2005) | 1 line + +minimum width for icon +------------------------------------------------------------------------ +r421535 | pdamsten | 2005-06-03 07:01:09 -0400 (Fri, 03 Jun 2005) | 1 line + +Use canonical file paths. +------------------------------------------------------------------------ +r421553 | pdamsten | 2005-06-03 08:17:39 -0400 (Fri, 03 Jun 2005) | 1 line + +more compatible with svn dir structure +------------------------------------------------------------------------ +r421554 | markusb | 2005-06-03 08:19:10 -0400 (Fri, 03 Jun 2005) | 2 lines + +Fix "underquoted definition" warning + +------------------------------------------------------------------------ +r421590 | mlaurent | 2005-06-03 10:15:30 -0400 (Fri, 03 Jun 2005) | 2 lines + +Add const + +------------------------------------------------------------------------ +r421988 | pdamsten | 2005-06-04 04:20:02 -0400 (Sat, 04 Jun 2005) | 1 line + +showItems function added. +------------------------------------------------------------------------ +r421989 | pdamsten | 2005-06-04 04:21:39 -0400 (Sat, 04 Jun 2005) | 1 line + +Search added to theme dialog. +------------------------------------------------------------------------ +r422015 | pdamsten | 2005-06-04 06:20:47 -0400 (Sat, 04 Jun 2005) | 1 line + +insertItem returns index +------------------------------------------------------------------------ +r422017 | pdamsten | 2005-06-04 06:21:56 -0400 (Sat, 04 Jun 2005) | 1 line + +handle file with no path better. +------------------------------------------------------------------------ +r422018 | pdamsten | 2005-06-04 06:23:57 -0400 (Sat, 04 Jun 2005) | 1 line + +Support for running multiple instances of theme. +------------------------------------------------------------------------ +r422064 | pdamsten | 2005-06-04 08:51:27 -0400 (Sat, 04 Jun 2005) | 1 line + +more compatible with svn dir structure +------------------------------------------------------------------------ +r422071 | pdamsten | 2005-06-04 09:13:12 -0400 (Sat, 04 Jun 2005) | 1 line + +All & Running items to show combo box in themes dialog. +------------------------------------------------------------------------ +r422086 | pdamsten | 2005-06-04 09:43:58 -0400 (Sat, 04 Jun 2005) | 1 line + +Running indicator to the theme list. +------------------------------------------------------------------------ +r422259 | nickell | 2005-06-04 18:05:33 -0400 (Sat, 04 Jun 2005) | 3 lines + +Fix the path returned for karamba.getThemePath() when using a zipped +theme. + +------------------------------------------------------------------------ +r422283 | nickell | 2005-06-04 19:25:15 -0400 (Sat, 04 Jun 2005) | 3 lines + +Removing this fix, as this is not the solution to getThemePath not +functioning in zipped themes. + +------------------------------------------------------------------------ +r422519 | pdamsten | 2005-06-05 14:09:40 -0400 (Sun, 05 Jun 2005) | 1 line + +readThemeFile added to python api. +------------------------------------------------------------------------ +r422675 | nickell | 2005-06-06 00:57:45 -0400 (Mon, 06 Jun 2005) | 2 lines + +Initial support for KNewStuff. Install code has not been completed yet. + +------------------------------------------------------------------------ +r422865 | pdamsten | 2005-06-06 14:54:37 -0400 (Mon, 06 Jun 2005) | 1 line + +Add warning when running non local theme. +------------------------------------------------------------------------ +r422947 | nickell | 2005-06-06 20:14:17 -0400 (Mon, 06 Jun 2005) | 4 lines + +More knewstuff. Install is now working, but it's limited to non-zipped +themes and they get installed into: +~/.kde/share/apps/superkaramba/themes/ + +------------------------------------------------------------------------ +r423033 | pdamsten | 2005-06-07 05:22:49 -0400 (Tue, 07 Jun 2005) | 1 line + +Auto reload patch added and reload bug fixed. +------------------------------------------------------------------------ +r423702 | pdamsten | 2005-06-09 08:22:20 -0400 (Thu, 09 Jun 2005) | 1 line + +i18n support for skz themes and .theme files +------------------------------------------------------------------------ +r423703 | pdamsten | 2005-06-09 08:22:37 -0400 (Thu, 09 Jun 2005) | 1 line + +i18n support for skz themes and .theme files +------------------------------------------------------------------------ +r423704 | pdamsten | 2005-06-09 08:22:58 -0400 (Thu, 09 Jun 2005) | 1 line + +i18n support for skz themes and .theme files +------------------------------------------------------------------------ +r423706 | pdamsten | 2005-06-09 08:26:21 -0400 (Thu, 09 Jun 2005) | 1 line + +Show theme version +------------------------------------------------------------------------ +r423941 | mlaurent | 2005-06-10 04:26:49 -0400 (Fri, 10 Jun 2005) | 2 lines + +Fixuifiles + +------------------------------------------------------------------------ +r424268 | pdamsten | 2005-06-11 06:18:25 -0400 (Sat, 11 Jun 2005) | 1 line + +Handle execute parameters as QString instead of char* to handle unicode chars correctly. +------------------------------------------------------------------------ +r424540 | mlaurent | 2005-06-12 05:23:36 -0400 (Sun, 12 Jun 2005) | 2 lines + +Don't compile superkaramba when python header was not installed + +------------------------------------------------------------------------ +r425963 | nickell | 2005-06-15 20:52:40 -0400 (Wed, 15 Jun 2005) | 8 lines + +Now we can download and install .skz files into the install directory: +$KDEHOME/share/apps/superkaramba/themes +We also unpack any other type of archive into it's own directory in the +install directory. +TODO: add the install directory to the theme dialog browser +TODO: verify that a zipped archive is truly a .skz file by detecting +the inventory xml file. + +------------------------------------------------------------------------ +r426202 | binner | 2005-06-16 13:41:03 -0400 (Thu, 16 Jun 2005) | 2 lines + +SVN_SILENT i18n style guide fixes, all sighted on planetkde.org :-| + +------------------------------------------------------------------------ +r426365 | scripty | 2005-06-17 00:14:17 -0400 (Fri, 17 Jun 2005) | 1 line + +SVN_SILENT made messages (.desktop file) +------------------------------------------------------------------------ +r426378 | pdamsten | 2005-06-17 01:33:48 -0400 (Fri, 17 Jun 2005) | 1 line + +Add themes to the theme list after Get New Stuff download. +------------------------------------------------------------------------ +r426385 | pdamsten | 2005-06-17 02:37:25 -0400 (Fri, 17 Jun 2005) | 1 line + +Fixed bug in saveUserAddedThemes +------------------------------------------------------------------------ +r426496 | pdamsten | 2005-06-17 09:38:15 -0400 (Fri, 17 Jun 2005) | 1 line + +Removed debug messages. +------------------------------------------------------------------------ +r426497 | pdamsten | 2005-06-17 09:39:35 -0400 (Fri, 17 Jun 2005) | 1 line + +Select downloaded theme from list to find it more easily. +------------------------------------------------------------------------ +r426677 | scripty | 2005-06-18 00:10:29 -0400 (Sat, 18 Jun 2005) | 1 line + +SVN_SILENT made messages (.desktop file) +------------------------------------------------------------------------ +r427009 | pdamsten | 2005-06-19 02:25:49 -0400 (Sun, 19 Jun 2005) | 1 line + +New InputBox meter. +------------------------------------------------------------------------ +------------------------------------------------------------------------ +r427283 | pdamsten | 2005-06-20 04:42:47 -0400 (Mon, 20 Jun 2005) | 1 line + +Use python as basename for mo files instead of skz file. +------------------------------------------------------------------------ +r427558 | nickell | 2005-06-20 20:49:24 -0400 (Mon, 20 Jun 2005) | 3 lines + +Implicitly show the qlineedit box upon creation. +createInputBox() now works. + +------------------------------------------------------------------------ +r427600 | pdamsten | 2005-06-21 03:35:21 -0400 (Tue, 21 Jun 2005) | 1 line + +Update thems list on show (fixes unvisible buttons). +------------------------------------------------------------------------ +r427617 | mlaurent | 2005-06-21 05:21:48 -0400 (Tue, 21 Jun 2005) | 2 lines + +karamba.pot is into l10n directory + +------------------------------------------------------------------------ +r427783 | pdamsten | 2005-06-21 16:17:34 -0400 (Tue, 21 Jun 2005) | 1 line + +Make 'keyPressed' working with input box. +------------------------------------------------------------------------ +r427868 | pdamsten | 2005-06-22 04:15:57 -0400 (Wed, 22 Jun 2005) | 1 line + +Make richtext obey the user set width and height. +------------------------------------------------------------------------ +r428035 | pdamsten | 2005-06-22 15:46:41 -0400 (Wed, 22 Jun 2005) | 1 line + +Support for license in maindata.xml +------------------------------------------------------------------------ +r428039 | pdamsten | 2005-06-22 15:55:14 -0400 (Wed, 22 Jun 2005) | 1 line + +Trying to fix key press event problems. +------------------------------------------------------------------------ +r428109 | pdamsten | 2005-06-23 02:00:34 -0400 (Thu, 23 Jun 2005) | 1 line + +Get input box test properties from theme. +------------------------------------------------------------------------ +r428431 | scripty | 2005-06-24 00:19:17 -0400 (Fri, 24 Jun 2005) | 1 line + +SVN_SILENT made messages (.desktop file) +------------------------------------------------------------------------ +r429260 | nickell | 2005-06-26 22:04:12 -0400 (Sun, 26 Jun 2005) | 6 lines + +Thanks to Alex Wiedenbruch, we can now hide the systray icon. +There is a dcop function hideSystemTray(bool) that can be called, +a theme's right click menu or by clicking on the systray icon +itself will allow you to hide the system tray icon. + + +------------------------------------------------------------------------ +r429276 | scripty | 2005-06-27 00:03:59 -0400 (Mon, 27 Jun 2005) | 1 line + +SVN_SILENT made messages (.desktop file) +------------------------------------------------------------------------ +r429448 | pdamsten | 2005-06-27 14:17:22 -0400 (Mon, 27 Jun 2005) | 1 line + +Patch from A. Wiedenbruch to show non-theme specific menu items in theme menu only when sytray icon hidden. +------------------------------------------------------------------------ +r429492 | mueller | 2005-06-27 17:20:33 -0400 (Mon, 27 Jun 2005) | 2 lines + +unbreak compilation. does anyone review apps that don't compile? + +------------------------------------------------------------------------ +r429581 | pdamsten | 2005-06-28 03:13:58 -0400 (Tue, 28 Jun 2005) | 1 line + +Start themes by double clicking them. +------------------------------------------------------------------------ +r429585 | pdamsten | 2005-06-28 03:43:02 -0400 (Tue, 28 Jun 2005) | 1 line + +Show scrollbar only when enough lines. +------------------------------------------------------------------------ +r429605 | pdamsten | 2005-06-28 05:06:43 -0400 (Tue, 28 Jun 2005) | 1 line + +New icons +------------------------------------------------------------------------ +r429606 | pdamsten | 2005-06-28 05:07:11 -0400 (Tue, 28 Jun 2005) | 1 line + +mimetype +------------------------------------------------------------------------ +r429610 | pdamsten | 2005-06-28 05:16:13 -0400 (Tue, 28 Jun 2005) | 1 line + +Renamed some files: karamba -> superkaramba +------------------------------------------------------------------------ +r429611 | pdamsten | 2005-06-28 05:17:08 -0400 (Tue, 28 Jun 2005) | 1 line + +Icons now in icon directory. +------------------------------------------------------------------------ +r429612 | pdamsten | 2005-06-28 05:19:41 -0400 (Tue, 28 Jun 2005) | 1 line + +icons and mimetype dirs. +------------------------------------------------------------------------ +r429614 | pdamsten | 2005-06-28 05:28:43 -0400 (Tue, 28 Jun 2005) | 1 line + +Removed skicon icon. +------------------------------------------------------------------------ +r429616 | pdamsten | 2005-06-28 05:37:03 -0400 (Tue, 28 Jun 2005) | 1 line + +Oops, wrong name... +------------------------------------------------------------------------ +r429851 | scripty | 2005-06-29 00:36:37 -0400 (Wed, 29 Jun 2005) | 1 line + +SVN_SILENT made messages (.desktop file) +------------------------------------------------------------------------ +r429924 | pdamsten | 2005-06-29 08:35:12 -0400 (Wed, 29 Jun 2005) | 1 line + +Patch from A. Wiedenbruch that fixes the not shown menu when starting from a session. Also added: Loading themes from relative path and not only from absolute path when using command line arguments. +------------------------------------------------------------------------ +r429962 | coles | 2005-06-29 10:57:23 -0400 (Wed, 29 Jun 2005) | 5 lines + +SVN_SILENT + +Corrected typo (runningin -> running in). + + +------------------------------------------------------------------------ +r430073 | nickell | 2005-06-29 21:16:59 -0400 (Wed, 29 Jun 2005) | 2 lines + +Make the icons install. It at least fixed it for me. + +------------------------------------------------------------------------ +r430082 | nickell | 2005-06-29 22:28:11 -0400 (Wed, 29 Jun 2005) | 3 lines + +Finally get rid of tooltips when an image has been deleted. +Now we'll no longer have phantom tooltips! + +------------------------------------------------------------------------ +r430088 | nickell | 2005-06-29 23:47:48 -0400 (Wed, 29 Jun 2005) | 2 lines + +Update template for keyPressed callback. + +------------------------------------------------------------------------ +r430095 | scripty | 2005-06-30 00:16:41 -0400 (Thu, 30 Jun 2005) | 1 line + +SVN_SILENT made messages (.desktop file) +------------------------------------------------------------------------ +r430112 | pdamsten | 2005-06-30 02:06:19 -0400 (Thu, 30 Jun 2005) | 1 line + +add mimetype to SUBDIRS +------------------------------------------------------------------------ +r430113 | pdamsten | 2005-06-30 02:16:00 -0400 (Thu, 30 Jun 2005) | 1 line + +Oops typo... +------------------------------------------------------------------------ +r430122 | pdamsten | 2005-06-30 03:05:02 -0400 (Thu, 30 Jun 2005) | 1 line + +Use SuperKaramba instead of Superkaramba +------------------------------------------------------------------------ +r430124 | pdamsten | 2005-06-30 03:18:41 -0400 (Thu, 30 Jun 2005) | 1 line + +Trying to fix hideMenuExtension crash +------------------------------------------------------------------------ +r430219 | pdamsten | 2005-06-30 10:43:49 -0400 (Thu, 30 Jun 2005) | 1 line + +Save ShowSystrayIcon to configure file. +------------------------------------------------------------------------ +r430351 | nickell | 2005-06-30 21:37:45 -0400 (Thu, 30 Jun 2005) | 4 lines + +Added new examples for the input box. +Cleaned up the test_all.sh so it would work. + + +------------------------------------------------------------------------ +r430374 | scripty | 2005-06-30 23:59:45 -0400 (Thu, 30 Jun 2005) | 1 line + +SVN_SILENT made messages (.desktop file) +------------------------------------------------------------------------ +r430653 | scripty | 2005-07-02 00:06:13 -0400 (Sat, 02 Jul 2005) | 1 line + +SVN_SILENT made messages (.desktop file) +------------------------------------------------------------------------ +r430988 | nickell | 2005-07-02 18:16:38 -0400 (Sat, 02 Jul 2005) | 2 lines + +Unbreak MANAGED mode for themes. Alex's theme didn't check for !managed. + +------------------------------------------------------------------------ +r431197 | nickell | 2005-07-03 11:19:32 -0400 (Sun, 03 Jul 2005) | 3 lines + +Now clicking on .theme's and .skz's causes them to open with +SuperKaramba. + +------------------------------------------------------------------------ +r431381 | nickell | 2005-07-04 02:13:15 -0400 (Mon, 04 Jul 2005) | 4 lines + +Add a tooltip to the system tray icon. +TODO: add some useful information such as the number of running themes. + + +------------------------------------------------------------------------ +r431391 | nickell | 2005-07-04 04:06:59 -0400 (Mon, 04 Jul 2005) | 2 lines + +Forgot the i18n for the systray tooltip text. + +------------------------------------------------------------------------ +r431753 | pdamsten | 2005-07-05 02:43:16 -0400 (Tue, 05 Jul 2005) | 1 line + +Reloading bug fixed. +------------------------------------------------------------------------ +r431758 | pdamsten | 2005-07-05 03:01:14 -0400 (Tue, 05 Jul 2005) | 1 line + +Xpm lib not needed anymore. +------------------------------------------------------------------------ +r431759 | pdamsten | 2005-07-05 03:01:49 -0400 (Tue, 05 Jul 2005) | 1 line + +Updated name and version. +------------------------------------------------------------------------ +r432054 | nickell | 2005-07-05 20:44:02 -0400 (Tue, 05 Jul 2005) | 3 lines + +In all of it's glory I present to you release 0.37! + + +------------------------------------------------------------------------ +r432566 | binner | 2005-07-07 16:42:18 -0400 (Thu, 07 Jul 2005) | 2 lines + +SVN_SILENT i18n style guide fix + +------------------------------------------------------------------------ +r432567 | binner | 2005-07-07 16:42:35 -0400 (Thu, 07 Jul 2005) | 2 lines + +kdereview reviewed for Yes/No buttons + +------------------------------------------------------------------------ +r432643 | nickell | 2005-07-07 22:33:56 -0400 (Thu, 07 Jul 2005) | 2 lines + +This is really the first release candiate before 0.37 final. + +------------------------------------------------------------------------ +SuperKaramba v0.36 + +2005-04-19 22:19 p0z3r + + * doc/python_api/api_html.rc: Fixed a bug that was preventing all + the api functions being generated into html. + +2005-04-19 01:01 p0z3r + + * admin/cvs.sh: Update so that automake up through version 1.9.x + can generate configure/Makefile scripts. + +2005-04-15 15:25 kodaaja + + * src/: meter.h, textlabel.h: getTextValue fix. + +2005-02-14 18:26 p0z3r + + * src/karamba.cpp: moved the move() call to be after the theme file + arguments for LEFT/RIGHT/TOP/BOTTOM were read in. It seems + though that once the theme is loaded, the ~/.superkaramba/*.rc + options of widgetPosX and widgetPosY override those options. We + may want to consider a change in that behavior. + +2005-02-02 16:32 kodaaja + + * src/meter_python.cpp: Convert from UCS4 to UCS2 if python uses 4 + byte unicode chars. + +2005-02-02 13:46 kodaaja + + * examples/richtext/rtext.py: Removed unneeded getThemeRichText + calls. + +2005-01-19 19:20 p0z3r + + * src/karamba.cpp: Some themes have trailing '/'s that cause + problems when report disk usage through a DiskSensor mntMap + key/value pair. This removes the trailing '/' so that it can get + the match it needs for a mountpoint. + +2005-01-18 19:05 p0z3r + + * src/karamba.cpp: There is no need to call step() in + mouseReleaseEvent(). It was causing widgetUpdated to be called + in themes. + +2005-01-07 19:31 p0z3r + + * admin/acinclude.m4.in: Update superkaramba to check for the + recently release Python2.4. + +2004-11-28 07:47 kodaaja + + * src/misc_python.h: Documentation fix + +2004-11-23 10:16 kodaaja + + * src/: imagelabel_python.cpp, main.cpp, menu_python.cpp, + misc_python.cpp, task_python.cpp, widget_python.cpp: AMD 64 + compile warning fixes. + +2004-11-18 01:46 kodaaja + + * admin/acinclude.m4.in: QT 3.2 => QT 3.1 + +2004-11-17 15:26 kodaaja + + * src/showdesktop.cpp: More warning fixes + +2004-11-17 13:56 kodaaja + + * src/: imagelabel.cpp, karambainterface.cpp, taskmanager.cpp: More + compile warning removals. + +2004-11-17 05:16 kodaaja + + * admin/Doxyfile.am, admin/Doxyfile.global, admin/Makefile.common, + admin/acinclude.m4.in, admin/am_edit, admin/bcheck.pl, + admin/conf.change.pl, admin/config.pl, admin/cvs-clean.pl, + admin/cvs.sh, admin/debianrules, admin/depcomp, + admin/detect-autoconf.sh, admin/install-sh, admin/libtool.m4.in, + admin/ltmain.sh, admin/nmcheck, src/bar_python.cpp, + src/bar_python.h, src/config_python.cpp, src/config_python.h, + src/graph_python.cpp, src/graph_python.h, src/imagelabel.cpp, + src/imagelabel.h, src/imagelabel_python.cpp, + src/imagelabel_python.h, src/karamba.cpp, src/karamba.h, + src/karamba_python.cpp, src/karamba_python.h, src/karambaapp.cpp, + src/karambaapp.h, src/karambarootpixmap.cpp, + src/karambasessionmanaged.cpp, src/karambasessionmanaged.h, + src/main.cpp, src/memsensor.cpp, src/menu_python.cpp, + src/menu_python.h, src/meter_python.cpp, src/meter_python.h, + src/misc_python.cpp, src/misc_python.h, src/networksensor.cpp, + src/pyapi_templates.h, src/richtextlabel.cpp, + src/richtextlabel.h, src/richtextlabel_python.cpp, + src/richtextlabel_python.h, src/rsssensor.cpp, + src/showdesktop.cpp, src/skicon.xpm, src/systemtray.cpp, + src/systray_python.cpp, src/systray_python.h, + src/task_python.cpp, src/task_python.h, src/taskmanager.cpp, + src/taskmanager.h, src/textlabel.cpp, src/textlabel_python.cpp, + src/textlabel_python.h, src/themelistwindow.cpp, + src/welcomeform.cpp, src/widget_python.cpp, src/widget_python.h, + src/xmmssensor.cpp: Removed all the compile warnings. + +SuperKaramba v0.35 + +* many new APIs +* new callbacks +* DCOP interface for superkaramba +* multiple superkarambas / one systray support +* added Fahrenheit support +* fixed the "moving themes" problem +* fixed the "always on top" problem +* fixed bug in setMenuConfigOption(). ATTENTION DEVELOPERS: please see api.html for the new syntax. +* asyncronous image loading. karamba.setImagePath should now work with net files. +* fixed bug in meterClicked() +* fixed bug in setRichTextWidth() / getRichTextSize() +* much more code cleanup, bug fixes, and internal documentation \ No newline at end of file diff --git a/superkaramba/Doxyfile b/superkaramba/Doxyfile new file mode 100644 index 0000000..e69de29 diff --git a/superkaramba/INSTALL b/superkaramba/INSTALL new file mode 100644 index 0000000..02a4a07 --- /dev/null +++ b/superkaramba/INSTALL @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/superkaramba/Makefile.am b/superkaramba/Makefile.am new file mode 100644 index 0000000..e45d776 --- /dev/null +++ b/superkaramba/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = src icons mimetypes + +include $(top_srcdir)/admin/Doxyfile.am + diff --git a/superkaramba/NEWS b/superkaramba/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/superkaramba/README b/superkaramba/README new file mode 100644 index 0000000..51caad6 --- /dev/null +++ b/superkaramba/README @@ -0,0 +1,42 @@ +This is SuperKaramba, a version of Karamba with python scripting! +http://netdragon.sourceforge.net + + +All the info for programmers is in examples/api.html. + + + +TO COMPILE: +---------- + +Optional: + +make -f Makefile.cvs + +Required: + +./configure +make +make install + + + +SuperKaramba is written by more than one person. + +The "super" part was created by: + +Adam Geitgey +adam@rootnode.org + + +The most recent super-karamba info can be found here: +http://netdragon.sourceforge.net + + +The "karamba" part was created by: + +Hans Karlsson +karlsson.h@home.se + +The most recent information about non-super Karamba can be found here: +http://www.efd.lth.se/~d98hk/karamba diff --git a/superkaramba/TODO b/superkaramba/TODO new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/superkaramba/TODO @@ -0,0 +1 @@ + diff --git a/superkaramba/configure.in.bot b/superkaramba/configure.in.bot new file mode 100644 index 0000000..6818a14 --- /dev/null +++ b/superkaramba/configure.in.bot @@ -0,0 +1,7 @@ +if test -z "$PYTHONINC"; then + echo "" + echo "Superkaramba can't be compiled" + echo "because of missing Python libraries/headers." + echo "" + all_tests=bad +fi diff --git a/superkaramba/configure.in.in b/superkaramba/configure.in.in new file mode 100644 index 0000000..4ff9f27 --- /dev/null +++ b/superkaramba/configure.in.in @@ -0,0 +1,77 @@ +#MIN_CONFIG + +AM_INIT_AUTOMAKE(superkaramba, 0.38) +AC_C_BIGENDIAN +AC_CHECK_KDEMAXPATHLEN + +dnl AM_PATH_XMMS([1.0.0]) +dnl AC_PATH_PROG(XMMS_CONFIG, xmms-config, no) +dnl AM_PATH_XMMS(1.0.0,,AC_MSG_ERROR([*** XMMS >= 1.0.0 not installed - please install first ***])) + +KDE_CHECK_PYTHON +AC_DEFUN([AC_CHECK_XMMS], +[ + AC_MSG_CHECKING([for libxmms]) + AC_CACHE_VAL(ac_cv_have_xmms, + [ + ac_save_libs="$LIBS" + LIBS="`xmms-config --libs`" + ac_CPPFLAGS_save="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $all_includes `xmms-config --cflags`" + ac_LDFLAGS_save="$LDFLAGS" + LDFLAGS="$LDFLAGS $all_libraries" + AC_TRY_LINK( + [#include ], + [xmms_remote_stop(0);], + [ac_cv_have_xmms="yes"], + [ac_cv_have_xmms="no"] + ) + LIBS="$ac_save_libs" + LDFLAGS="$ac_LDFLAGS_save" + CPPFLAGS="$ac_CPPFLAGS_save" + ]) + AC_MSG_RESULT($ac_cv_have_xmms) + if test "$ac_cv_have_xmms" = "yes"; then + XMMS_INCLUDES="`xmms-config --cflags`" + + for arg in `xmms-config --libs`; do + case $arg in + -[[lL]]*) + XMMS_LIBS="$XMMS_LIBS $arg" + ;; + *) + XMMS_LDFLAGS="$XMMS_LDFLAGS $arg" + esac + done + AC_DEFINE(HAVE_XMMS, 1, [Define if you have xmms libraries and header files.]) + fi +]) + +AC_ARG_WITH(xmms, + [AC_HELP_STRING(--with-xmms, + [enable support for XMMS @<:@default=check@:>@])], + [], with_xmms=check) + +if test "x$with_xmms" != xno; then + AC_CHECK_XMMS + + if test "x$with_xmms" != xcheck && test "x$ac_cv_have_xmms" = xno; then + AC_MSG_ERROR([--with-xmms was given, but test for XMMS failed]) + fi +fi +AC_SUBST(XMMS_LIBS) +AC_SUBST(XMMS_LDFLAGS) +AC_SUBST(XMMS_INCLUDES) + +kde_have_knewstuff=yes +KDE_CHECK_LIB(knewstuff, main, [MY_LIBKNEWSTUFF="-lknewstuff"], kde_have_knewstuff=no) +if test "$kde_have_knewstuff" = "yes"; then + AC_DEFINE(HAVE_KNEWSTUFF, 1, [Define if you have knewstuff]) + AC_SUBST(MY_LIBKNEWSTUFF) +fi + +AC_CHECK_LIB(kvm, main, [LIBKVM="-lkvm"]) +AC_SUBST(LIBKVM) +if test -z "$PYTHONINC" ; then + DO_NOT_COMPILE="$DO_NOT_COMPILE superkaramba" +fi diff --git a/superkaramba/doc/Makefile.am b/superkaramba/doc/Makefile.am new file mode 100644 index 0000000..a7fea2f --- /dev/null +++ b/superkaramba/doc/Makefile.am @@ -0,0 +1,6 @@ +# the SUBDIRS is filled automatically by am_edit. If files are +# in this directory they are installed into the english dir + +KDE_LANG = en +KDE_DOCS = karamba +SUBDIRS = $(AUTODIRS) diff --git a/superkaramba/doc/faq/faq.css b/superkaramba/doc/faq/faq.css new file mode 100644 index 0000000..3a2ec59 --- /dev/null +++ b/superkaramba/doc/faq/faq.css @@ -0,0 +1,36 @@ +h1 { padding-top: 0.25in; + padding-bottom: 0.25in; + color: black; + font-size: 24pt; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-weight: bold; + text-align: center; + } + +h2 { font-size: 18pt; + } +h3 { font-size: 12pt; + } + +p { + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 10pt; + } + +pre { + font-family: Courier, serif; + background-color: #dddddd; + } + + + +code { + font-family: Courier, serif; + } + +tt { + font-family: Courier, serif; + } + + + diff --git a/superkaramba/doc/faq/faq.dat b/superkaramba/doc/faq/faq.dat new file mode 100644 index 0000000..c54194d --- /dev/null +++ b/superkaramba/doc/faq/faq.dat @@ -0,0 +1,75 @@ +Installation +Where can I find SuperKaramba RPMs? +The SuperKaramba web site (http://netdragon.sourceforge.net) has a list of user-submitted RPMs for several distributions. Other user-submitted RPMs have been posted to kde-look.org and to the SuperKaramba Help forum. + +Installation +When I try to compile, I get this error: "Python.h: No such file or directory" +You will need to install the python-devel package. Once that package is installed you can ./configure and make again. + +Installation +When I try to compile, I get this error: "cannot find -lselinux" +You will need to install the libselinux-devel package. Once that package is installed you can ./configure and make again. + +Installation +After running ./configure,make, and make install, the superkaramba executable is not where I expected it to be. When I try to run superkaramba from the command line it says "command not found". +In some distributions ./configure points to different path than you might expect. For example, in Mandrake the default ./configure prefix is /usr/local/kde and the executable is installed in /usr/local/kde/bin. There are a few things you can do to fix this. You could run ./configure --prefix=/usr to specify the prefix that you prefer and then try make and make install again. Or you could create a symbolic link in your preferred directory that links to the executable. Or you could add the install directory to your $PATH. + +General +How do I get rid of the KDE taskbar? Do I have to keep kicker running? +Many themes depend on kicker and will not work well without it. If you don't want kicker to show on your desktop, you can set it to auto-hide. Another solution is to change the auto-hide setting in a ~/.kde file. For more information see http://wiki.kdenews.org/tiki-print.php?page=Secret+Config+Settings. + +General +Can I run a systray theme while the kicker systray is running? +It's better not to. If you run a theme with a SysTray on it while a regular kicker systray is running, the theme will "steal" all the icons from the first systray. This is because in KDE and Gnome, the systray icons are really little windows and there is only one copy of each running. If you want to run a systray theme, you can remove the systray from kicker. + +General +How do I set up my themes to run automatically on startup? +Turn on KDE session support in the KDE control panel. When session support is enabled, any theme that is left running when you logout will automatically start on startup. For some themes you will also need to right-click and reload the theme at least once after running it so that the config file will get written to your home directory. Another solution is to create a desktop config file in the KDE autostart directory. +To create a desktop config file, open KWrite and enter the following:
    +            [Desktop Entry]
    +            Exec=superkaramba {location of theme file}.theme
    +            Name={theme name}
    +            Type=Application
    +            X-KDE-StartupNotify=false
    +
    Then save it as {theme}.desktop into /home/{user}/.kde/Autostart/. + +Troubleshooting +All of my themes are "always on top" of the other windows. +
    This problem should be fixed in the most recent release. + +Troubleshooting +My themes start up in different locations when I start KDE. +Close all superkaramba themes and then delete any session files in ~/.kde/share/config/session/ that begin with superkaramba. Restart KDE and start your themes again. Now they will stay in the right place. + +Troubleshooting +The backgrounds of my themes are black instead of transparent. +In KDE, transparency only works when the desktop background is a wallpaper image that is centered or scaled. If the background is a plain color or a tiled image then superkaramba themes will not be transparent. In Gnome, there is a known issue that themes will have a black background even when a wallpaper is set. Unfortunately there is no current solution. Your theme should work fine otherwise. + +General +Why is the Edit Script option disabled when I right-click on a theme? +Some karamba themes don't include a python script. This is normal and those themes will still work fine without one. However, if the theme does use a python script, superkaramba may have not been able to load the script. This is usually due to python errors. Run the theme from the command line to find out the specific error message. + +General +Why is the Configure Theme menu disabled when I right-click on a theme? +The Configure Theme menu is only enabled if the theme has added options to it. Some themes do not have any configuration options or use a different configuration method. + +Installation Guides +Suse 9.1 Personal +To install on SuSE 9.1 Personal, ensure the following packages are installed, which you verify via YaST:
    +qt3-devel
    +kdelibs3-devel
    +python-devel

    +Once the above are installed, unzip your SuperKaramba tarball to its own folder. Now, via terminal, login as root and cd (change directory) to the unzipped SuperKaramba folder. Install with following commands:
    +./configure --prefix=/opt/kde3/
    +make
    +make install
    +make clean

    +You're done! To start SuperKaramba, you should now be able to find SuperKaramba in your "Utilities" folder in the main Menu.

    +* This has not been tested on SuSE 9.1 Professional or previous versions of SuSE. However, the need to use the ./configure --prefix=/opt/kde3/ command has been needed in previous versions by some people. + +Installation Guides +Mandrake (9.0 and up) +
    Unzip your SuperKaramba tarball to its own folder. Now, via terminal, cd (change directory) to the unzipped SuperKaramba folder. Install with following commands:
    +./configure --prefix=/usr
    +make
    +(login as root) make install \ No newline at end of file diff --git a/superkaramba/doc/faq/faq.html b/superkaramba/doc/faq/faq.html new file mode 100644 index 0000000..1e68240 --- /dev/null +++ b/superkaramba/doc/faq/faq.html @@ -0,0 +1,111 @@ + + +SuperKaramba Frequently Asked Questions + + + +

    +SuperKaramba Frequently Asked Questions +

    +

    This FAQ is current to SuperKaramba 0.35. For more information about this FAQ, please visit the SuperKaramba Help forum or contact selan at users dot sf dot net. + +


    +

    FAQ Revised: Tuesday 09 November 2004 21:31:53

    +

    Table of Contents

    +
    +
    1. Installation
    +
    +
    2. General
    +
    +
    3. Troubleshooting
    +
    +
    4. Installation Guides
    +
    +
    +

    1. Installation

    +
    +
    1.1. Where can I find SuperKaramba RPMs?
    +
    The SuperKaramba web site (http://netdragon.sourceforge.net) has a list of user-submitted RPMs for several distributions. Other user-submitted RPMs have been posted to kde-look.org and to the SuperKaramba Help forum.

    +
    1.2. When I try to compile, I get this error: "Python.h: No such file or directory"
    +
    You will need to install the python-devel package. Once that package is installed you can ./configure and make again.

    +
    1.3. When I try to compile, I get this error: "cannot find -lselinux"
    +
    You will need to install the libselinux-devel package. Once that package is installed you can ./configure and make again.

    +
    1.4. After running ./configure,make, and make install, the superkaramba executable is not where I expected it to be. When I try to run superkaramba from the command line it says "command not found".
    +
    In some distributions ./configure points to different path than you might expect. For example, in Mandrake the default ./configure prefix is /usr/local/kde and the executable is installed in /usr/local/kde/bin. There are a few things you can do to fix this. You could run ./configure --prefix=/usr to specify the prefix that you prefer and then try make and make install again. Or you could create a symbolic link in your preferred directory that links to the executable. Or you could add the install directory to your $PATH.

    +
    +

    2. General

    +
    +
    2.1. How do I get rid of the KDE taskbar? Do I have to keep kicker running?
    +
    Many themes depend on kicker and will not work well without it. If you don't want kicker to show on your desktop, you can set it to auto-hide. Another solution is to change the auto-hide setting in a ~/.kde file. For more information see http://wiki.kdenews.org/tiki-print.php?page=Secret+Config+Settings.

    +
    2.2. Can I run a systray theme while the kicker systray is running?
    +
    It's better not to. If you run a theme with a SysTray on it while a regular kicker systray is running, the theme will "steal" all the icons from the first systray. This is because in KDE and Gnome, the systray icons are really little windows and there is only one copy of each running. If you want to run a systray theme, you can remove the systray from kicker.

    +
    2.3. How do I set up my themes to run automatically on startup?
    +
    Turn on KDE session support in the KDE control panel. When session support is enabled, any theme that is left running when you logout will automatically start on startup. For some themes you will also need to right-click and reload the theme at least once after running it so that the config file will get written to your home directory. Another solution is to create a desktop config file in the KDE autostart directory. +To create a desktop config file, open KWrite and enter the following:
    +            [Desktop Entry]
    +            Exec=superkaramba {location of theme file}.theme
    +            Name={theme name}
    +            Type=Application
    +            X-KDE-StartupNotify=false
    +
    Then save it as {theme}.desktop into /home/{user}/.kde/Autostart/.

    +
    2.4. Why is the Edit Script option disabled when I right-click on a theme?
    +
    Some karamba themes don't include a python script. This is normal and those themes will still work fine without one. However, if the theme does use a python script, superkaramba may have not been able to load the script. This is usually due to python errors. Run the theme from the command line to find out the specific error message.

    +
    2.5. Why is the Configure Theme menu disabled when I right-click on a theme?
    +
    The Configure Theme menu is only enabled if the theme has added options to it. Some themes do not have any configuration options or use a different configuration method.

    +
    +

    3. Troubleshooting

    +
    +
    3.1. All of my themes are "always on top" of the other windows.
    +
    This problem should be fixed in the most recent release.

    +
    3.2. My themes start up in different locations when I start KDE.
    +
    Close all superkaramba themes and then delete any session files in ~/.kde/share/config/session/ that begin with superkaramba. Restart KDE and start your themes again. Now they will stay in the right place.

    +
    3.3. The backgrounds of my themes are black instead of transparent.
    +
    In KDE, transparency only works when the desktop background is a wallpaper image that is centered or scaled. If the background is a plain color or a tiled image then superkaramba themes will not be transparent. In Gnome, there is a known issue that themes will have a black background even when a wallpaper is set. Unfortunately there is no current solution. Your theme should work fine otherwise.

    +
    +

    4. Installation Guides

    +
    +
    4.1. Suse 9.1 Personal
    +
    To install on SuSE 9.1 Personal, ensure the following packages are installed, which you verify via YaST:
    +qt3-devel
    +kdelibs3-devel
    +python-devel

    +Once the above are installed, unzip your SuperKaramba tarball to its own folder. Now, via terminal, login as root and cd (change directory) to the unzipped SuperKaramba folder. Install with following commands:
    +./configure --prefix=/opt/kde3/
    +make
    +make install
    +make clean

    +You're done! To start SuperKaramba, you should now be able to find SuperKaramba in your "Utilities" folder in the main Menu.

    +* This has not been tested on SuSE 9.1 Professional or previous versions of SuSE. However, the need to use the ./configure --prefix=/opt/kde3/ command has been needed in previous versions by some people.

    +
    4.2. Mandrake (9.0 and up)
    +
    Unzip your SuperKaramba tarball to its own folder. Now, via terminal, cd (change directory) to the unzipped SuperKaramba folder. Install with following commands:
    +./configure --prefix=/usr
    +make
    +(login as root) make install

    +
    +
    + +

    Copyright (c) 2004 Sarah Elan, Adam Geitgey, Rory in Toronto, Ryan Nickell and many others who contribute to the SuperKaramba Help forum.

    + +

    This list of questions and answers was generated by +makefaq. + + + diff --git a/superkaramba/doc/faq/faq.txt b/superkaramba/doc/faq/faq.txt new file mode 100644 index 0000000..9de445e --- /dev/null +++ b/superkaramba/doc/faq/faq.txt @@ -0,0 +1,159 @@ +SuperKaramba Frequently Asked Questions + +This FAQ is current to SuperKaramba 0.35. For more information about this FAQ, please visit the SuperKaramba Help forum (http://sourceforge.net/forum/forum.php?forum_id=67470) or contact selan at users dot sf dot net. +______________________________________________________________________ + +FAQ Revised: Tuesday 09 November 2004 21:31:57 + + +Table of Contents + + +1. Installation + +1.1. Where can I find SuperKaramba RPMs? +1.2. When I try to compile, I get this error: "Python.h: No such file or directory" +1.3. When I try to compile, I get this error: "cannot find -lselinux" +1.4. After running ./configure,make, and make install, the superkaramba executable is not where I expected it to be. When I try to run superkaramba from the command line it says "command not found". + + +2. General + +2.1. How do I get rid of the KDE taskbar? Do I have to keep kicker running? +2.2. Can I run a systray theme while the kicker systray is running? +2.3. How do I set up my themes to run automatically on startup? +2.4. Why is the Edit Script option disabled when I right-click on a theme? +2.5. Why is the Configure Theme menu disabled when I right-click on a theme? + + +3. Troubleshooting + +3.1. All of my themes are "always on top" of the other windows. +3.2. My themes start up in different locations when I start KDE. +3.3. The backgrounds of my themes are black instead of transparent. + + +4. Installation Guides + +4.1. Suse 9.1 Personal +4.2. Mandrake (9.0 and up) + + + +1. Installation + + +1.1. Where can I find SuperKaramba RPMs? + +The SuperKaramba web site (http://netdragon.sourceforge.net) has a list of user-submitted RPMs for several distributions. Other user-submitted RPMs have been posted to kde-look.org and to the SuperKaramba Help forum. + +1.2. When I try to compile, I get this error: "Python.h: No such file or directory" + +You will need to install the python-devel package. Once that package is installed you can ./configure and make again. + +1.3. When I try to compile, I get this error: "cannot find -lselinux" + +You will need to install the libselinux-devel package. Once that package is installed you can ./configure and make again. + +1.4. After running ./configure,make, and make install, the superkaramba executable is not where I expected it to be. When I try to run superkaramba from the command line it says "command not found". + +In some distributions ./configure points to different path than you might expect. For example, in Mandrake the default ./configure prefix is /usr/local/kde and the executable is installed in /usr/local/kde/bin. There are a few things you can do to fix this. You could run ./configure --prefix=/usr to specify the prefix that you prefer and then try make and make install again. Or you could create a symbolic link in your preferred directory that links to the executable. Or you could add the install directory to your $PATH. + + +2. General + + +2.1. How do I get rid of the KDE taskbar? Do I have to keep kicker running? + +Many themes depend on kicker and will not work well without it. If you don't want kicker to show on your desktop, you can set it to auto-hide. Another solution is to change the auto-hide setting in a ~/.kde file. For more information see http://wiki.kdenews.org/tiki-print.php?page=Secret+Config+Settings. + +2.2. Can I run a systray theme while the kicker systray is running? + +It's better not to. If you run a theme with a SysTray on it while a regular kicker systray is running, the theme will "steal" all the icons from the first systray. This is because in KDE and Gnome, the systray icons are really little windows and there is only one copy of each running. If you want to run a systray theme, you can remove the systray from kicker. + +2.3. How do I set up my themes to run automatically on startup? + +Turn on KDE session support in the KDE control panel. When session support is enabled, any theme that is left running when you logout will automatically start on startup. For some themes you will also need to right-click and reload the theme at least once after running it so that the config file will get written to your home directory. Another solution is to create a desktop config file in the KDE autostart directory. +To create a desktop config file, open KWrite and enter the following: + [Desktop Entry] + Exec=superkaramba {location of theme file}.theme + Name={theme name} + Type=Application + X-KDE-StartupNotify=false +Then save it as {theme}.desktop into /home/{user}/.kde/Autostart/. + +2.4. Why is the Edit Script option disabled when I right-click on a theme? + +Some karamba themes don't include a python script. This is normal and those themes will still work fine without one. However, if the theme does use a python script, superkaramba may have not been able to load the script. This is usually due to python errors. Run the theme from the command line to find out the specific error message. + +2.5. Why is the Configure Theme menu disabled when I right-click on a theme? + +The Configure Theme menu is only enabled if the theme has added options to it. Some themes do not have any configuration options or use a different configuration method. + + +3. Troubleshooting + + +3.1. All of my themes are "always on top" of the other windows. + +This problem should be fixed in the most recent release. + +3.2. My themes start up in different locations when I start KDE. + +Close all superkaramba themes and then delete any session files in ~/.kde/share/config/session/ that begin with superkaramba. Restart KDE and start your themes again. Now they will stay in the right place. + +3.3. The backgrounds of my themes are black instead of transparent. + +In KDE, transparency only works when the desktop background is a wallpaper image that is centered or scaled. If the background is a plain color or a tiled image then superkaramba themes will not be transparent. In Gnome, there is a known issue that themes will have a black background even when a wallpaper is set. Unfortunately there is no current solution. Your theme should work fine otherwise. + + +4. Installation Guides + + +4.1. Suse 9.1 Personal + +To install on SuSE 9.1 Personal, ensure the following packages are installed, which you verify via YaST: + +qt3-devel + +kdelibs3-devel + +python-devel + + +Once the above are installed, unzip your SuperKaramba tarball to its own folder. Now, via terminal, login as root and cd (change directory) to the unzipped SuperKaramba folder. Install with following commands: + +./configure --prefix=/opt/kde3/ + +make + +make install + +make clean + + +You're done! To start SuperKaramba, you should now be able to find SuperKaramba in your "Utilities" folder in the main Menu. + + +* This has not been tested on SuSE 9.1 Professional or previous versions of SuSE. However, the need to use the ./configure --prefix=/opt/kde3/ command has been needed in previous versions by some people. + +4.2. Mandrake (9.0 and up) + +Unzip your SuperKaramba tarball to its own folder. Now, via terminal, cd (change directory) to the unzipped SuperKaramba folder. Install with following commands: + +./configure --prefix=/usr + +make + +(login as root) make install + + + +______________________________________________________________________ +Copyright (C) 2004 Sarah Elan, Adam Geitgey, Rory in Toronto, Ryan Nickell +and many others who contribute to the SuperKaramba Help forum. + +This FAQ was generated by makefaq. +http://www.makefaq.org/ +______________________________________________________________________ + diff --git a/superkaramba/doc/faq/faqfooter.html b/superkaramba/doc/faq/faqfooter.html new file mode 100644 index 0000000..4e30319 --- /dev/null +++ b/superkaramba/doc/faq/faqfooter.html @@ -0,0 +1,9 @@ +


    + +

    Copyright (c) 2004 Sarah Elan, Adam Geitgey, Rory in Toronto, Ryan Nickell and many others who contribute to the SuperKaramba Help forum.

    + +

    This list of questions and answers was generated by +makefaq. + + + diff --git a/superkaramba/doc/faq/faqfooter.txt b/superkaramba/doc/faq/faqfooter.txt new file mode 100644 index 0000000..6daf8ca --- /dev/null +++ b/superkaramba/doc/faq/faqfooter.txt @@ -0,0 +1,9 @@ + +______________________________________________________________________ +Copyright (C) 2004 Sarah Elan, Adam Geitgey, Rory in Toronto, Ryan Nickell +and many others who contribute to the SuperKaramba Help forum. + +This FAQ was generated by makefaq. +http://www.makefaq.org/ +______________________________________________________________________ + diff --git a/superkaramba/doc/faq/faqheader.html b/superkaramba/doc/faq/faqheader.html new file mode 100644 index 0000000..a777fa7 --- /dev/null +++ b/superkaramba/doc/faq/faqheader.html @@ -0,0 +1,12 @@ + + +SuperKaramba Frequently Asked Questions + + + +

    +SuperKaramba Frequently Asked Questions +

    +

    This FAQ is current to SuperKaramba 0.35. For more information about this FAQ, please visit the SuperKaramba Help forum or contact selan at users dot sf dot net. + +


    diff --git a/superkaramba/doc/faq/faqheader.txt b/superkaramba/doc/faq/faqheader.txt new file mode 100644 index 0000000..c923a1f --- /dev/null +++ b/superkaramba/doc/faq/faqheader.txt @@ -0,0 +1,4 @@ +SuperKaramba Frequently Asked Questions + +This FAQ is current to SuperKaramba 0.35. For more information about this FAQ, please visit the SuperKaramba Help forum (http://sourceforge.net/forum/forum.php?forum_id=67470) or contact selan at users dot sf dot net. +______________________________________________________________________ diff --git a/superkaramba/doc/python_api/api.css b/superkaramba/doc/python_api/api.css new file mode 100644 index 0000000..d788da0 --- /dev/null +++ b/superkaramba/doc/python_api/api.css @@ -0,0 +1,40 @@ +body +{ + background-color: #ffffff; + color: #000000; + font-family: "Bitstream Vera Sans", verdana, lucida, arial, + helvetica, sans-serif; + font-size: 11pt; + margin: 2% 5%; +} +h1, h2, h3, h4, h5, h6, h7 +{ + background-color: #b2d599; + color: #000000; + text-align: left; + font-size: 11pt; + padding: 5px; +} +td.even, td.uneven +{ + color: #000000; + font-size: 10pt; +} +li +{ + font-size: 10pt; +} +td.even +{ + background-color: #eeeeee; +} +span.SOURCE +{ + white-space: pre; +} +pre +{ + background-color: #ffffff; + color: #000000; + font-size: 10pt; +} diff --git a/superkaramba/doc/python_api/api_html.rc b/superkaramba/doc/python_api/api_html.rc new file mode 100644 index 0000000..18c6cbb --- /dev/null +++ b/superkaramba/doc/python_api/api_html.rc @@ -0,0 +1,36 @@ +# Superkaramba python api html documentation config for ROBODOc +# +items: + SYNOPSIS + DESCRIPTION + ARGUMENTS + RETURN VALUE +ignore items: +options: + --singledoc + --src .apiHeaders + --doc python_api + --html + #--tell + --nopre + #--lock + #--index + --toc + --nodesc + --css api.css +headertypes: + p "Python API" karamba_python_api +ignore files: + README + CVS + *.bak + *~ + *.cpp + Makefile* + *.rc +header markers: + //**** +remark markers: + // +end markers: + //*** diff --git a/superkaramba/doc/python_api/make_api_doc.sh b/superkaramba/doc/python_api/make_api_doc.sh new file mode 100755 index 0000000..866c534 --- /dev/null +++ b/superkaramba/doc/python_api/make_api_doc.sh @@ -0,0 +1,42 @@ +#!/bin/bash +#This script grabs the current *_python.h headers, +# converts them to robodoc format, and then generates +# the api documentation +########################################################## +SRCDIR=../../src/ +TEMPDIR=".apiHeaders" + +if [[ -d $TEMPDIR ]]; then + echo "Cleaning out existing $TEMPDIR directory" + rm -rf $TEMPDIR/* +else + echo "Creating $TEMPDIR directory" + mkdir -p $TEMPDIR +fi + +function replaceComments() +{ + echo "Converting file $1" + TEMPFILE="temp.h" + cat $1 | sed -e 's/^\/\*\*/\/\/\*\*\*\*p\*/' -e 's/^\*\//\/\/\*\*\*/' -e 's/^\*/\/\//' > $TEMPFILE + if [[ -s $TEMPFILE ]] ; then + mv $TEMPFILE $1 + fi +} + + +FOO=`find $SRCDIR -type f -name "*_python.h"` + +for FILE in $FOO +do + cp $FILE $TEMPDIR/ +done + +BAR=`ls $TEMPDIR` +for FILE in $BAR +do + replaceComments $TEMPDIR/$FILE +done + +echo "Creating api documentation in output file: python_api.html" +robodoc --rc api_html.rc diff --git a/superkaramba/examples/API b/superkaramba/examples/API new file mode 100644 index 0000000..897e4d2 --- /dev/null +++ b/superkaramba/examples/API @@ -0,0 +1,6 @@ +All of the programmers reference material has been moved to the web site. + +It is at: + +http://netdragon.sourceforge.net/index.php?page=Information+for+Theme+Creators + diff --git a/superkaramba/examples/README b/superkaramba/examples/README new file mode 100644 index 0000000..712cf0e --- /dev/null +++ b/superkaramba/examples/README @@ -0,0 +1,62 @@ +All of the information for programmers is in the file called "API". + +Here are some examples of themes with matching python addons: + +autoHide/ + + This is the main.theme from kde-look.org with a simple + example python script that makes it "auto-hide". + Move the mouse over it to pop it back out. + +globalMouse/ + + This shows how to get the mouse cursor position anyway on + the screen but using the xcursor python module. + (This is Karamba Eyes by Wilfried.Huss@gmx.at) + +input_api/ + + This shows some of the different things you can do to an input box + once you have one created. + +input_example/ + + This is a functional example of how you grab text entered into an + input box and use it to do something. In this example, the text + is used to search for the entered word on dict.leo.org. + (This sample was contributed by Alex Wiedenbruch ) + +mouseDrag/ + + This shows how to use mouse dragging in the callback widgetMouseMoved + in your themes. + (This is karmix by Tian and rewritten by Ryan Nickell) + +openCloseTheme/ + + This shows how you can open a new theme from within an existing theme, + and how you can close themes. + +popupMenu/ + + This shows up to create popup menus, display them, and then + do something with the user input from them. + (This is a sample by MrDobalina ) + +richtext/ + + This is a simple example of how to use rich text (text with HTML + tags) in your themes. + (This is by Wilfried.Huss@gmx.at) + +taskBar/ + + This shows how to use the task management API to create a + simple taskbar. + (This is cleanbar by Adam Geitgey) + +unicode/ + + This is a simple example of how to display unicode characters in your + theme. + (This is by Wilfried.Huss@gmx.at) diff --git a/superkaramba/examples/api.html b/superkaramba/examples/api.html new file mode 100644 index 0000000..132544a --- /dev/null +++ b/superkaramba/examples/api.html @@ -0,0 +1,4016 @@ + + + + +./python_api + + + + + +Generated with ROBODoc v4.99.6 on Mon Nov 15 21:51:28 2004 +
    +

    TABLE OF CONTENTS

    + +
    + +

    +Widget/createWidgetMask

    + +

    [top]

    +

    SYNOPSIS

    +

    long createWidgetMask(widget, mask) +

    +

    DESCRIPTION

    +

    This function doesn't work currently due to a bug in KDE. Please use + MASK= in your .theme file for the time being. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string mask -- The name of the widget mask file. +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Widget/getWidgetPosition

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getWidgetPosition(widget) +

    +

    DESCRIPTION

    +

    Returns a Python Tuple containing the x and y position of you widget. + widget is a reference to the current widget. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    position of the widget +

    +
    +
    + +

    +Widget/moveWidget

    + +

    [top]

    +

    SYNOPSIS

    +

    long moveWidget(widget, x, y) +

    +

    DESCRIPTION

    +

    Moves your karamba widget to a new screen location +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Widget/redrawWidget

    + +

    [top]

    +

    SYNOPSIS

    +

    long redrawWidget(widget) +

    +

    DESCRIPTION

    +

    This is THE most important function. After you do a bunch of other calls + (moving images, adding images or text, etc), you call this to update the + widget display area. You will not see your changes until you call this. + Redraws widget background. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Widget/redrawWidgetBackground

    + +

    [top]

    +

    SYNOPSIS

    +

    long redrawWidgetBackground(widget) +

    +

    DESCRIPTION

    +

    Redraws widget background. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Widget/resizeWidget

    + +

    [top]

    +

    SYNOPSIS

    +

    long resizeWidget(widget, w, h) +

    +

    DESCRIPTION

    +

    Resizes your karamba widget to width=w, height=h +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long w -- width +
    • +
    • long h -- height +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Widget/toggleWidgetRedraw

    + +

    [top]

    +

    SYNOPSIS

    +

    long toggleWidgetRedraw(widget, b) +

    +

    DESCRIPTION

    +

    Toggles widget redraw. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long b -- 1 = widget is drawn +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/changeText

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeText(widget, text, value) +

    +

    DESCRIPTION

    +

    This will change the contents of a text widget. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    • long value -- new value +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/changeTextColor

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeTextColor(widget, text, r, g, b) +

    +

    DESCRIPTION

    +

    This will change the color of a text widget (only ones you created + through python currently). textToChange is the reference to the text + object to change that you saved from the createText() call. r, g, b are + ints from 0 to 255 that represent red, green, and blue. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    • long red -- red component of color +
    • +
    • long green -- green component of color +
    • +
    • long blue -- blue component of color +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/changeTextFont

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeTextFont(widget, text, font) +

    +

    DESCRIPTION

    +

    This will change the font of a text widget (only ones you created + through python currently). textToChange is the reference to the text + object to change that you saved from the createText() call. newFont is a + string the the name of the font to use. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    • string font -- font name +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/changeTextShadow

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeTextShadow(widget, text, shadow) +

    +

    DESCRIPTION

    +

    This will change the shadow size of a text widget (only ones you + created through python currently). textToChange is the reference to the + text object to change that you saved from the createText() call. size + is the offset of the shadow in pixels. 1 or 2 is a good value in most + cases. Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    • long shadow -- shadow offset +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/changeTextSize

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeTextSize(widget, text, size) +

    +

    DESCRIPTION

    +

    This will change the font size of a text widget (only ones you created + through python currently). textToChange is the reference to the text + object to change that you saved from the createText() call. size is the + new font point size. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    • long size -- new size for text +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/createText

    + +

    [top]

    +

    SYNOPSIS

    +

    long createText(widget, x, y, w, h, text) +

    +

    DESCRIPTION

    +

    This creates a text at x,y with width and height w,h. You need to save + the return value of this function to call other functions on your text + field, such as changeText() +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    • long w -- width +
    • +
    • long h -- height +
    • +
    • string text -- text for the textlabel +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to new text meter +

    +
    +
    + +

    +Text/deleteText

    + +

    [top]

    +

    SYNOPSIS

    +

    long deleteText(widget, text) +

    +

    DESCRIPTION

    +

    This removes a text object from memory. Please do not call functions on + "text" after calling deleteText, as it does not exist anymore and that + could cause crashes in some cases. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long widget -- text +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/getTextAlign

    + +

    [top]

    +

    SYNOPSIS

    +

    string getTextAlign(widget, text) +

    +

    DESCRIPTION

    +

    Get current text align. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    LEFT, CENTER or RIGHT +

    +
    +
    + +

    +Text/getTextColor

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getTextColor(widget, text) +

    +

    DESCRIPTION

    +

    Get current text color +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    (red, green, blue) +

    +
    +
    + +

    +Text/getTextFont

    + +

    [top]

    +

    SYNOPSIS

    +

    string getTextFont(widget, text) +

    +

    DESCRIPTION

    +

    Get current text font name +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    font name +

    +
    +
    + +

    +Text/getTextFontSize

    + +

    [top]

    +

    SYNOPSIS

    +

    long getTextFontSize(widget, text) +

    +

    DESCRIPTION

    +

    Get current text font size +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    text font size +

    +
    +
    + +

    +Text/getTextPos

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getTextPos(widget, text) +

    +

    DESCRIPTION

    +

    Given a reference to a text object, this will return a tuple + containing the x and y coordinate of a text object. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    pos +

    +
    +
    + +

    +Text/getTextSensor

    + +

    [top]

    +

    SYNOPSIS

    +

    string getTextSensor(widget, text) +

    +

    DESCRIPTION

    +

    Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    sensor string +

    +
    +
    + +

    +Text/getTextShadow

    + +

    [top]

    +

    SYNOPSIS

    +

    long getTextShadow(widget, text) +

    +

    DESCRIPTION

    +

    Get current shadow offset +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    shadow offset +

    +
    +
    + +

    +Text/getTextSize

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getTextSize(widget, text) +

    +

    DESCRIPTION

    +

    Given a reference to a text object, this will return a tuple + containing the height and width of a text object. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    size +

    +
    +
    + +

    +Text/getTextValue

    + +

    [top]

    +

    SYNOPSIS

    +

    string getTextValue(widget, text) +

    +

    DESCRIPTION

    +

    Returns current text value. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    value +

    +
    +
    + +

    +Text/getThemeText

    + +

    [top]

    +

    SYNOPSIS

    +

    long getThemeText(widget, name) +

    +

    DESCRIPTION

    +

    You can reference text in your python code that was created in the + theme file. Basically, you just add a NAME= value to the TEXT line in + the .theme file. Then if you want to use that object, instead of calling + createText, you can call this function. +

    + +

    The name you pass to the function is the same one that you gave it for + the NAME= parameter in the .theme file. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string name -- name of the text to get +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to text +

    +
    +
    + +

    +Text/hideText

    + +

    [top]

    +

    SYNOPSIS

    +

    long hideText(widget, text) +

    +

    DESCRIPTION

    +

    Hides text that is visible. You need to call redrawWidget() afterwords + to actually hide the text on screen. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/moveText

    + +

    [top]

    +

    SYNOPSIS

    +

    long moveText(widget, text, x, y) +

    +

    DESCRIPTION

    +

    This moves a text object to a new x, y relative to your widget. In other + words, (0,0) is the top corner of your widget, not the screen. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/resizeText

    + +

    [top]

    +

    SYNOPSIS

    +

    long resizeText(widget, text, w, h) +

    +

    DESCRIPTION

    +

    This will resize text to new height and width. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    • long w -- new width +
    • +
    • long h -- new height +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/setTextAlign

    + +

    [top]

    +

    SYNOPSIS

    +

    long setTextAlign(widget, text, align) +

    +

    DESCRIPTION

    +

    Sets text label align. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    • string align -- LEFT, CENTER or RIGHT +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/setTextSensor

    + +

    [top]

    +

    SYNOPSIS

    +

    long setTextSensor(widget, text, sensor) +

    +

    DESCRIPTION

    +

    Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    • string sensor -- new sensor as in theme files +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Text/showText

    + +

    [top]

    +

    SYNOPSIS

    +

    long showText(widget, text) +

    +

    DESCRIPTION

    +

    Shows text that has been hidden with hideText() +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long text -- pointer to text +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Task/getStartupInfo

    + +

    [top]

    +

    SYNOPSIS

    +

    list getStartupInfo(widget, task) +

    +

    DESCRIPTION

    +

    This returns all of the info about a certain starting task in the form of + a Python List. widget is a reference to the current widget. task is a + reference to the window you want info about which you obtain by calling + getStartupList(). +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long task -- pointer to task +
    • +
    +

    +

    RETURN VALUE

    +

    Here is the format of the returned list by index value: +

    +
    • 0 = Task name (The full name of the window) +
    • +
    • 1 = Icon name +
    • +
    • 2 = Executable name +
    • +
    • 3 = A reference back to the task you got info on +
    • +
    +

    +
    +
    + +

    +Task/getStartupList

    + +

    [top]

    +

    SYNOPSIS

    +

    list getTaskList(widget) +

    +

    DESCRIPTION

    +

    This returns a Python List object with references to all the current + windows that are in the process of loading on this system. You can then + call getStartupInfo() on any of the entries in the list. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    startup list +

    +
    +
    + +

    +Task/getTaskInfo

    + +

    [top]

    +

    SYNOPSIS

    +

    list getTaskInfo(widget, task) +

    +

    DESCRIPTION

    +

    This returns all of the info about a certain task in the form of a Python + List. widget is a reference to the current widget. task is a reference to + the window you want info about which you obtain by calling getTaskList(). +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long task -- pointer to task +
    • +
    +

    +

    RETURN VALUE

    +

    Here is the format of the returned list by index value: +

    +
    • 0 = Task name (The full name of the window) +
    • +
    • 1 = Icon name +
    • +
    • 2 = Class name - This is for grouping tasks. All tasks with the same + name can be grouped together because they are instances of the same + program. +
    • +
    • 3 = Desktop number - The desktop number this window is on +
    • +
    • 4 = Is this window maximized? 0=no, 1=yes +
    • +
    • 5 = Is this window iconified (minimized)? 0=no, 1=yes +
    • +
    • 6 = Is this window shaded (rolled up)? 0=no, 1=yes +
    • +
    • 7 = Is this window focused? 0=no, 1=yes +
    • +
    • 8 = A reference back to the task you got info on +
    • +
    +

    +
    +
    + +

    +Task/getTaskList

    + +

    [top]

    +

    SYNOPSIS

    +

    list getTaskList(widget) +

    +

    DESCRIPTION

    +

    This returns a Python List object with references to all the current + windows open on this system. You can then call performTaskAction() or + getTaskInfo() on any of the entries in the list. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    Task list +

    +
    +
    + +

    +Task/getTaskNames

    + +

    [top]

    +

    SYNOPSIS

    +

    list getTaskNames(widget) +

    +

    DESCRIPTION

    +

    This returns a Python List containing the String names of all open + windows on the system. This is for convience if you want to list open + windows or see if a window by a certain name exists. Anything else + requires the reference to the window you would obtain from getTaskList() +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    Task list +

    +
    +
    + +

    +Task/performTaskAction

    + +

    [top]

    +

    SYNOPSIS

    +

    long performTaskAction(widget, task, action) +

    +

    DESCRIPTION

    +

    This peforms the given action on a task object. widget is a reference to + the current widget. task is a reference to a task object you got from + getTaskList(). Action is a number from 1 to 10. See the list below. +

    + +

    Possible actions: +

    +
    • 1 = Maximize the window +
    • +
    • 2 = Restore the window (use on iconified windows) +
    • +
    • 3 = Iconify the window (minimize it) +
    • +
    • 4 = Close the window +
    • +
    • 5 = Activate (give focus to) the window +
    • +
    • 6 = Raise the window +
    • +
    • 7 = Lower the window +
    • +
    • 8 = Smart Focus/Minimize - This will what the KDE taskbar does when you + click on a window. If it is iconified, raise it. If it has focus, + iconify it. +
    • +
    • 9 = Toggle whether this window is always on top +
    • +
    • 10 = Toggle wheter this window is shaded (rolled up) +
    • +
    +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long task -- pointer to task +
    • +
    • long action -- action number +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Systray/createSystray

    + +

    [top]

    +

    SYNOPSIS

    +

    long createSystray(widget, x, y, w, h) +

    +

    DESCRIPTION

    +

    ?? +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    • long w -- width +
    • +
    • long h -- height +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Systray/getCurrentWindowCount

    + +

    [top]

    +

    SYNOPSIS

    +

    long getCurrentWindowCount(widget) +

    +

    DESCRIPTION

    +

    ?? +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    window count +

    +
    +
    + +

    +Systray/hideSystray

    + +

    [top]

    +

    SYNOPSIS

    +

    long hideSystray(widget) +

    +

    DESCRIPTION

    +

    ?? +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Systray/moveSystray

    + +

    [top]

    +

    SYNOPSIS

    +

    long moveSystray(widget, x, y, w, h) +

    +

    DESCRIPTION

    +

    ?? +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    • long w -- width +
    • +
    • long h -- height +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Systray/showSystray

    + +

    [top]

    +

    SYNOPSIS

    +

    long showSystray(widget) +

    +

    DESCRIPTION

    +

    ?? +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Systray/updateSystrayLayout

    + +

    [top]

    +

    SYNOPSIS

    +

    long getCurrentWindowCount(widget) +

    +

    DESCRIPTION

    +

    ?? +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +RichText/changeRichText

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeRichText(widget, richtext, value) +

    +

    DESCRIPTION

    +

    This will change the contents of a rich text widget. richText is the + reference to the text object to change that you saved from the + createRichText() call. text is a string containing the new value for the + rich text object. +

    + +

    The differance between Rich Text and a regular text field is that rich + text fields can display HTML code embedded in your text. +

    + +

    In a <a href="command"> ... </a> tag command is executed if the link is + click with the left mouse button. +

    + +

    Except if command starts with an '#' (ie: href="#value" ) the callback + meterClicked is called with value (without the #) as the meter argument. +

    + +

    Also inline images work. Unfortunatly currently only when using absolute + paths. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    • string value -- new text +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +RichText/changeRichTextFont

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeRichTextFont(widget, richtext, font) +

    +

    DESCRIPTION

    +

    This will change the font of a richtext widget. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    • string font -- name of the new font +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +RichText/changeRichTextSize

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeRichTextSize(widget, richtext, size) +

    +

    DESCRIPTION

    +

    This will change the font size of a richtext widget. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    • long size -- new font point size +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +RichText/createRichText

    + +

    [top]

    +

    SYNOPSIS

    +

    long createRichText(widget, text, underlineLinks) +

    +

    DESCRIPTION

    +

    This creates creates a rich text string. underlineLinks is a boolean that + determines if html links will be automatically underlined so that the + user knows that the links can be clicked on. You need to save the return + value of this function to call other functions on your rich text field, + such as changeRichText(). +

    + +

    The differance between Rich Text and a regular text field is that rich + text fields can display HTML code embedded in your text. +

    + +

    In a <a href="command"> ... </a> tag command is executed if the link is + click with the left mouse button. +

    + +

    Except if command starts with an '#' (ie: href="#value" ) the callback + meterClicked is called with value (without the #) as the meter argument. +

    + +

    Also inline images work. Unfortunatly currently only when using absolute + paths. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string text -- text for richtext +
    • +
    • long underlineLinks -- should the links be underlined +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to new richtext meter +

    +
    +
    + +

    +RichText/deleteRichText

    + +

    [top]

    +

    SYNOPSIS

    +

    long deleteRichText(widget, richtext) +

    +

    DESCRIPTION

    +

    This removes a richt text object from memory. Please do not call + functions on "text" after calling deleteRichText, as it does not exist + anymore and that could cause crashes in some cases. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long widget -- richtext +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +RichText/getRichTextFont

    + +

    [top]

    +

    SYNOPSIS

    +

    string getRichTextFont(widget, richtext) +

    +

    DESCRIPTION

    +

    This will get the font of a richtext widget. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    +

    +

    RETURN VALUE

    +

    font name +

    +
    +
    + +

    +RichText/getRichTextFontSize

    + +

    [top]

    +

    SYNOPSIS

    +

    long getRichTextFontSize(widget, richtext) +

    +

    DESCRIPTION

    +

    This will get the font size of a richtext widget. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    +

    +

    RETURN VALUE

    +

    font point size +

    +
    +
    + +

    +RichText/getRichTextPos

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getRichTextPos(widget, richtext) +

    +

    DESCRIPTION

    +

    Given a reference to a richtext object, this will return a tuple + containing the x and y coordinate of a richtext object. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    +

    +

    RETURN VALUE

    +

    pos +

    +
    +
    + +

    +RichText/getRichTextSensor

    + +

    [top]

    +

    SYNOPSIS

    +

    string getRichTextSensor(widget, richtext) +

    +

    DESCRIPTION

    +

    Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    +

    +

    RETURN VALUE

    +

    sensor string +

    +
    +
    + +

    +RichText/getRichTextSize

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getRichTextSize(widget, richtext) +

    +

    DESCRIPTION

    +

    Given a reference to a richtext object, this will return a tuple + containing the height and width of a richtext object. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    +

    +

    RETURN VALUE

    +

    size +

    +
    +
    + +

    +RichText/getRichTextValue

    + +

    [top]

    +

    SYNOPSIS

    +

    string getRichTextValue(widget, richtext) +

    +

    DESCRIPTION

    +

    Returns current richtext value. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    +

    +

    RETURN VALUE

    +

    value +

    +
    +
    + +

    +RichText/getThemeRichText

    + +

    [top]

    +

    SYNOPSIS

    +

    long getThemeRichText(widget, name) +

    +

    DESCRIPTION

    +

    You can reference richtext in your python code that was created in the + theme file. Basically, you just add a NAME= value to the GRAPH line in + the .theme file. Then if you want to use that object, instead of calling + createRichText, you can call this function. +

    + +

    The name you pass to the function is the same one that you gave it for + the NAME= parameter in the .theme file. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string name -- name of the richtext to get +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to richtext +

    +
    +
    + +

    +RichText/hideRichText

    + +

    [top]

    +

    SYNOPSIS

    +

    long hideRichText(widget, richtext) +

    +

    DESCRIPTION

    +

    This hides an richtext. In other words, during subsequent calls to + widgetUpdate(), this richtext will not be drawn. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +RichText/moveRichText

    + +

    [top]

    +

    SYNOPSIS

    +

    long moveRichText(widget, richtext, x, y) +

    +

    DESCRIPTION

    +

    This moves a text object to a new x, y relative to your widget. In other + words, (0,0) is the top corner of your widget, not the screen. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +RichText/resizeRichText

    + +

    [top]

    +

    SYNOPSIS

    +

    long resizeRichText(widget, richtext, w, h) +

    +

    DESCRIPTION

    +

    This will resize richtext to new height and width. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    • long w -- new width +
    • +
    • long h -- new height +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +RichText/setRichTextSensor

    + +

    [top]

    +

    SYNOPSIS

    +

    long setRichTextSensor(widget, richtext, sensor) +

    +

    DESCRIPTION

    +

    Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    • string sensor -- new sensor as in theme files +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +RichText/setRichTextWidth

    + +

    [top]

    +

    SYNOPSIS

    +

    long setRichTextWidth(widget, richtext, width) +

    +

    DESCRIPTION

    +

    Given a reference to a rich text object, this function changes it's width + to the specified value in pixels. +

    + +

    The height adjusts automatically as the contents are changed with + changeRichText. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    • long width -- new width in pixels +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +RichText/showRichText

    + +

    [top]

    +

    SYNOPSIS

    +

    long showRichText(widget, richtext) +

    +

    DESCRIPTION

    +

    This shows an richtext. In other words, during subsequent calls to + widgetUpdate(), this richtext will be drawn. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long richtext -- pointer to richtext +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Misc/acceptDrops

    + +

    [top]

    +

    SYNOPSIS

    +

    long acceptDrops(widget) +

    +

    DESCRIPTION

    +

    Calling this enables your widget to receive Drop events. In other words, + the user will be able to drag icons from her desktop and drop them on + your widget. The "itemDropped" callback is called as a result with the + data about the icon that was dropped on your widget. This allows, for + example, icon bars where items are added to the icon bar by Drag and + Drop. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Misc/attachClickArea

    + +

    [top]

    +

    SYNOPSIS

    +

    long attachClickArea(widget, meter, lB, mB, rB) +

    +

    DESCRIPTION

    +

    It is possible to attach a clickarea to a meter (image or text field), + which is moved and resized correctly if the meter is moved or resized. +

    + +

    There is also a callback meterClicked(widget, meter, button) which is + called whenever a meter is clicked (if something is attached to it). + Given an Image or a TextLabel, this call makes it clickable. When a mouse + click is detected, the callback meterClicked is called. +

    + +

    lB, mB, and rB are strings that specify what command is executed when + this meter is clicked with the left mouse button, middle mouse button, + and right mouse button respectively. If given, the appropriate command is + executed when the mouse click is received. +

    + +

    The keyword arguments are all optional. If command is an empty string + nothing is executed. +

    + +

    For now the command given to RightButton has obviosly no effect (because + that brings up the SuperKaramba menu). +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long meter -- pointer to meter +
    • +
    • string lB -- command to left mouse button +
    • +
    • string mB -- command to middle mouse button +
    • +
    • string rB -- command to right mouse button +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Misc/createClickArea

    + +

    [top]

    +

    SYNOPSIS

    +

    long createClickArea(widget, x, y, w, h, cmd_to_run) +

    +

    DESCRIPTION

    +

    This creates a clickable area at x,y with width and height w,h. When + this area is clicked, cmd_to_run will be executed. The mouse will change + to the clickable icon when over this area. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    • long w -- width +
    • +
    • long h -- height +
    • +
    • string cmd_to_run -- command to be run +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Misc/execute

    + +

    [top]

    +

    SYNOPSIS

    +

    long execute(widget, command) +

    +

    DESCRIPTION

    +

    This command simply executes a program or command on the system. This is + just for convience (IE you could accomplish this directly through python, + but sometimes threading problems crop up that way). The only option is a + string containing the command to execute. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string command -- command to execute +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Misc/executeInteractive

    + +

    [top]

    +

    SYNOPSIS

    +

    long executeInteractive(widget, command) +

    +

    DESCRIPTION

    +

    This command executes a program or command on the system. But it allows + you to get any text that the program outputs. Futhermore, it won't freeze + up your widget while the command executes. +

    + +

    To use it, call executeInteractive with the reference to your widget and + a list of command options. The array is simply a list that contains the + command as the first entry, and each option as a seperate list entry. + Output from the command is returned via the commandOutput callback. +

    + +

    The command returns the process number of the command. This is useful if + you want to run more than one program at a time. The number will allow + you to figure out which program is outputting in the commandOutput + callback. +

    + +

    Example: Run the command "ls -la *.zip" +

    + +

    myCommand = ["ls", "-la", "*.zip"] + karamba.executeInteractive(widget, myCommand) +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string command -- command to execute +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Misc/getIp

    + +

    [top]

    +

    SYNOPSIS

    +

    string getIp(widget, interface_name) +

    +

    DESCRIPTION

    +

    get current IP address of the interface_name interface. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string interface_name -- name of the interface to get ip +
    • +
    +

    +

    RETURN VALUE

    +

    ip address +

    +
    +
    + +

    +Misc/getNumberOfDesktop

    + +

    [top]

    +

    SYNOPSIS

    +

    long getNumberOfDesktop(widget) +

    +

    DESCRIPTION

    +

    Returns number fo desktops +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    number of desktops +

    +
    +
    + +

    +Misc/getThemePath

    + +

    [top]

    +

    SYNOPSIS

    +

    string getThemePath(widget) +

    +

    DESCRIPTION

    +

    Returns a string containing the directory where your theme was loaded + from. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    path to theme +

    +
    +
    + +

    +Misc/hide

    + +

    [top]

    +

    SYNOPSIS

    +

    string hide(widget) +

    +

    DESCRIPTION

    +

    hide theme +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Misc/openTheme

    + +

    [top]

    +

    SYNOPSIS

    +

    long openTheme(theme) +

    +

    DESCRIPTION

    +

    Opens new theme. +

    +

    ARGUMENTS

    +
    • string theme -- path to new theme +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Misc/show

    + +

    [top]

    +

    SYNOPSIS

    +

    string show(widget) +

    +

    DESCRIPTION

    +

    show theme +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Misc/toggleShowDesktop

    + +

    [top]

    +

    SYNOPSIS

    +

    long toggleShowDesktop(widget) +

    +

    DESCRIPTION

    +

    This shows/hides the current desktop just like the Show Desktop button on + kicker. Basically, it minimizes all the windows on the current desktop. + Call it once to show the desktop and again to hide it. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Misc/translateAll

    + +

    [top]

    +

    SYNOPSIS

    +

    long translateAll(widget, relative_x, relative_y) +

    +

    DESCRIPTION

    +

    Moves all widgets within a theme in a particular direction relative from + the previous spot without moving the parent theme widget. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long translate_x -- move horizontally +
    • +
    • long translate_y -- move vertically +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Menu/addMenuItem

    + +

    [top]

    +

    SYNOPSIS

    +

    long addMenuItem(widget, menu, text, icon) +

    +

    DESCRIPTION

    +

    This adds an entry to the given menu with label text and with given icon. + icon can be just an application name in which case the user's current + icon set is used, or can be a path to a 16x16 png file. +

    + +

    The function returns the id of the menu item, which identifies that popup + menu item uniquely among popupmenu items application-wide or returns 0 + if the given menu doesn't exist. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long menu -- pointer to menu +
    • +
    • string text -- text for menu item +
    • +
    • string icon -- icon +
    • +
    +

    +

    RETURN VALUE

    +

    menu item id +

    +
    +
    + +

    +Menu/addMenuSeparator

    + +

    [top]

    +

    SYNOPSIS

    +

    long addMenuSeparator(widget, menu) +

    +

    DESCRIPTION

    +

    This adds an menu separator to the given menu. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long menu -- pointer to menu +
    • +
    +

    +

    RETURN VALUE

    +

    menu item id +

    +
    +
    + +

    +Menu/createMenu

    + +

    [top]

    +

    SYNOPSIS

    +

    long createMenu(widget) +

    +

    DESCRIPTION

    +

    This creates an empty popup menu and returns a pointer to the menu. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    +

    +

    RETURN VALUE

    +

    pointer to menu +

    +
    +
    + +

    +Menu/deleteMenu

    + +

    [top]

    +

    SYNOPSIS

    +

    long deleteMenu(widget, menu) +

    +

    DESCRIPTION

    +

    This deletes the referenced menu if that menu exists. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long menu -- pointer to menu +
    • +
    +

    +

    RETURN VALUE

    +

    1 if menu existed and was deleted, returns 0 otherwise. +

    +
    +
    + +

    +Menu/popupMenu

    + +

    [top]

    +

    SYNOPSIS

    +

    long popupMenu(widget, menu, x, y) +

    +

    DESCRIPTION

    +

    This pops up the given menu at the given co-ordinates. The co-ordinates + are relative to the widget, not the screen. You can use negative + co-ordinates to make a menu appear to the right of or above your theme. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long menu -- pointer to menu +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    +

    +

    RETURN VALUE

    +

    1 if the menu existed and was popped up, returns 0 otherwise. +

    +
    +
    + +

    +Menu/removeMenuItem

    + +

    [top]

    +

    SYNOPSIS

    +

    long removeMenuItem(widget, menu, id) +

    +

    DESCRIPTION

    +

    This removes the item with given id from given menu if that menu exists. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long menu -- pointer to menu +
    • +
    • long id -- menu item id +
    • +
    +

    +

    RETURN VALUE

    +

    1 if the menu item existed and was removed or returns zero otherwise. +

    +
    +
    + +

    +Image/addImageTooltip

    + +

    [top]

    +

    SYNOPSIS

    +

    long addImageTooltip(widget, image, text) +

    +

    DESCRIPTION

    +

    This creats a tooltip for image with tooltip_text. +

    + +

    Note: +

    +
    • If you move the image, the tooltip does not move! It stays! Do not + create a tooltip if the image is off-screen because you will not be + able to ever see it. +
    • +
    +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    • string text -- tooltip text +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/changeImageChannelIntensity

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeImageChannelIntensity(widget, image, ratio, channel, millisec) +

    +

    DESCRIPTION

    +

    Changes the "intensity" of the image color channel, which is similar to + it's brightness. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    • float ratio -- -1.0 to 1.0 (dark to bright) +
    • +
    • string channel -- color channel (red|green|blue) +
    • +
    • long millisec -- milliseconds before the image is restored +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/changeImageIntensity

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeImageIntensity(widget, image, ratio, millisec) +

    +

    DESCRIPTION

    +

    Changes the "intensity" of the image, which is similar to it's + brightness. ratio is a floating point number from -1.0 to 1.0 that + determines how much to brighten or darken the image. Millisec specifies + how long in milliseconds before the image is restored to it's original + form. This is useful for "mouse over" type animations. Using 0 for + millisec disables this feature and leaves the image permanently + affected. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    • float ratio -- -1.0 to 1.0 (dark to bright) +
    • +
    • long millisec -- milliseconds before the image is restored +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/changeImageToGray

    + +

    [top]

    +

    SYNOPSIS

    +

    long changeImageToGray(widget, image, millisec) +

    +

    DESCRIPTION

    +

    Turns the given image into a grayscale image. Millisec specifies how + long in milliseconds before the image is restored to it's original form. + This is useful for "mouse over" type animations. Using 0 for millisec + disables this feature and leaves the image permanently affected. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    • long millisec -- milliseconds before the image is restored +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/createBackgroundImage

    + +

    [top]

    +

    SYNOPSIS

    +

    long createBackgroundImage(widget, x, y, w, h, image) +

    +

    DESCRIPTION

    +

    This creates an background image on your widget at x, y. The filename + should be given as the path parameter. In theory the image could be + local or could be a url. It works just like adding an image in your + theme file. You will need to save the return value to be able to call + other functions on your image, such as moveImage() +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    • string image -- image for the imagelabel +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to new image meter +

    +
    +
    + +

    +Image/createImage

    + +

    [top]

    +

    SYNOPSIS

    +

    long createImage(widget, x, y, image) +

    +

    DESCRIPTION

    +

    This creates an image on your widget at x, y. The filename should be + given as the path parameter. In theory the image could be local or could + be a url. It works just like adding an image in your theme file. You + will need to save the return value to be able to call other functions on + your image, such as moveImage() +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    • string image -- image for the imagelabel +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to new image meter +

    +
    +
    + +

    +Image/createTaskIcon

    + +

    [top]

    +

    SYNOPSIS

    +

    long createTaskIcon(widget, x, y, ctask) +

    +

    DESCRIPTION

    +

    This creates a task image at x,y. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    • long task -- task +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to new image meter +

    +
    +
    + +

    +Image/deleteImage

    + +

    [top]

    +

    SYNOPSIS

    +

    long deleteImage(widget, image) +

    +

    DESCRIPTION

    +

    This removes image from memory. Please do not call functions on "image" + after calling deleteImage, as it does not exist anymore and that could + cause crashes in some cases. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long widget -- image +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/getImageHeight

    + +

    [top]

    +

    SYNOPSIS

    +

    long getImageSize(widget, image) +

    +

    DESCRIPTION

    +

    This returns the height of an image. This is useful if you have rotated + an image and its size changed, so you do not know how big it is anymore. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    +

    +

    RETURN VALUE

    +

    height +

    +
    +
    + +

    +Image/getImagePath

    + +

    [top]

    +

    SYNOPSIS

    +

    string getImagePath(widget, image) +

    +

    DESCRIPTION

    +

    Returns current image path. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    +

    +

    RETURN VALUE

    +

    path +

    +
    +
    + +

    +Image/getImagePos

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getImagePos(widget, image) +

    +

    DESCRIPTION

    +

    Given a reference to a image object, this will return a tuple + containing the x and y coordinate of a image object. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    +

    +

    RETURN VALUE

    +

    pos +

    +
    +
    + +

    +Image/getImageSensor

    + +

    [top]

    +

    SYNOPSIS

    +

    string getImageSensor(widget, image) +

    +

    DESCRIPTION

    +

    Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    +

    +

    RETURN VALUE

    +

    sensor string +

    +
    +
    + +

    +Image/getImageSize

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getImageSize(widget, image) +

    +

    DESCRIPTION

    +

    Given a reference to a image object, this will return a tuple + containing the height and width of a image object. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    +

    +

    RETURN VALUE

    +

    size +

    +
    +
    + +

    +Image/getImageWidth

    + +

    [top]

    +

    SYNOPSIS

    +

    long getImageSize(widget, image) +

    +

    DESCRIPTION

    +

    This returns the width of an image. This is useful if you have rotated + an image and its size changed, so you do not know how big it is anymore. // ARGUMENTS + * long widget -- karamba + * long image -- pointer to image +

    +

    RETURN VALUE

    +

    width +

    +
    +
    + +

    +Image/getThemeImage

    + +

    [top]

    +

    SYNOPSIS

    +

    long getThemeImage(widget, name) +

    +

    DESCRIPTION

    +

    You can reference an image in your python code that was created in the + .theme file. Basically, you just add a NAME= value to the IMAGE line in + the .theme file. Then if you want to use that object, instead of calling + createImage, you can call this function. +

    + +

    The name you pass to the function is the same one that you gave it for + the NAME= parameter in the .theme file. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string name -- name of the image to get +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to image +

    +
    +
    + +

    +Image/hideImage

    + +

    [top]

    +

    SYNOPSIS

    +

    long hideImage(widget, image) +

    +

    DESCRIPTION

    +

    This hides an image. In other words, during subsequent calls to + widgetUpdate(), this image will not be drawn. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/moveImage

    + +

    [top]

    +

    SYNOPSIS

    +

    long moveImage(widget, image, x, y) +

    +

    DESCRIPTION

    +

    This moves an image to a new x, y relative to your widget. In other + words, (0,0) is the top corner of your widget, not the screen. The + imageToMove parameter is a reference to the image to move that you saved + as the return value from createImage() +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/removeImageEffects

    + +

    [top]

    +

    SYNOPSIS

    +

    long removeImageEffects(widget, image) +

    +

    DESCRIPTION

    +

    If you have called image effect commands on your image (ex: + changeImageIntensity), you can call this to restore your image to it's + original form. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/removeImageTransformations

    + +

    [top]

    +

    SYNOPSIS

    +

    long removeImageTransformations(widget, image) +

    +

    DESCRIPTION

    +

    If you have rotated or resized your image, you can call this to restore + your image to it's original form. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/resizeImage

    + +

    [top]

    +

    SYNOPSIS

    +

    long resizeImage(widget, image, w, h) +

    +

    DESCRIPTION

    +

    This resizes your image to width, height. The imageToResize parameter is + a reference to an image that you saved as the return value from + createImage() +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    • long w -- width +
    • +
    • long h -- height +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/resizeImageSmooth

    + +

    [top]

    +

    SYNOPSIS

    +

    long resizeImageSmooth(widget, image, w, h) +

    +

    DESCRIPTION

    +

    DEPRECATED: resizeImage now allows the user to pick whether to use fast + or smooth resizing from the SuperKaramba menu - This resizes your image + to width, height. The imageToResize parameter is a reference to an + image that you saved as the return value from createImage() +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    • long w -- width +
    • +
    • long h -- height +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/rotateImage

    + +

    [top]

    +

    SYNOPSIS

    +

    long rotateImage(widget, image, deg) +

    +

    DESCRIPTION

    +

    This rotates your image to by the specified amount of degrees. The + imageToRotate parameter is a reference to an image that you saved as the + return value from createImage() +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    • long deg -- degrees to rotate +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/setImagePath

    + +

    [top]

    +

    SYNOPSIS

    +

    long setImagePath(widget, image, path) +

    +

    DESCRIPTION

    +

    This will change image of a image widget. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    • long path -- new path +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/setImageSensor

    + +

    [top]

    +

    SYNOPSIS

    +

    long setImageSensor(widget, image, sensor) +

    +

    DESCRIPTION

    +

    Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    • string sensor -- new sensor as in theme files +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Image/showImage

    + +

    [top]

    +

    SYNOPSIS

    +

    long showImage(widget, image) +

    +

    DESCRIPTION

    +

    This shows a previously hidden image. It does not actually refresh the + image on screen. That is what redrawWidget() does. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long image -- pointer to image +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Graph/createGraph

    + +

    [top]

    +

    SYNOPSIS

    +

    long createGraph(widget, x, y, w, h, points) +

    +

    DESCRIPTION

    +

    This creates a graph at x,y with width and height w,h. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    • long w -- width +
    • +
    • long h -- height +
    • +
    • long points -- Number of points in graph +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to new graph meter +

    +
    +
    + +

    +Graph/deleteGraph

    + +

    [top]

    +

    SYNOPSIS

    +

    long deleteGraph(widget, graph) +

    +

    DESCRIPTION

    +

    This deletes graph. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long widget -- graph +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Graph/getGraphColor

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getGraphColor(widget, graph) +

    +

    DESCRIPTION

    +

    Get current graph color +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    +

    +

    RETURN VALUE

    +

    (red, green, blue) +

    +
    +
    + +

    +Graph/getGraphMinMax

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getGraphMinMax(widget, graph) +

    +

    DESCRIPTION

    +

    Returns current graph value. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    +

    +

    RETURN VALUE

    +

    min & max +

    +
    +
    + +

    +Graph/getGraphPos

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getGraphPos(widget, graph) +

    +

    DESCRIPTION

    +

    Given a reference to a graph object, this will return a tuple + containing the x and y coordinate of a graph object. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    +

    +

    RETURN VALUE

    +

    pos +

    +
    +
    + +

    +Graph/getGraphSensor

    + +

    [top]

    +

    SYNOPSIS

    +

    string getGraphSensor(widget, graph) +

    +

    DESCRIPTION

    +

    Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    +

    +

    RETURN VALUE

    +

    sensor string +

    +
    +
    + +

    +Graph/getGraphSize

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getGraphSize(widget, graph) +

    +

    DESCRIPTION

    +

    Given a reference to a graph object, this will return a tuple + containing the height and width of a graph object. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    +

    +

    RETURN VALUE

    +

    size +

    +
    +
    + +

    +Graph/getGraphValue

    + +

    [top]

    +

    SYNOPSIS

    +

    long getGraphValue(widget, graph) +

    +

    DESCRIPTION

    +

    Returns current graph value. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    +

    +

    RETURN VALUE

    +

    value +

    +
    +
    + +

    +Graph/getThemeGraph

    + +

    [top]

    +

    SYNOPSIS

    +

    long getThemeGraph(widget, name) +

    +

    DESCRIPTION

    +

    You can reference graph in your python code that was created in the + theme file. Basically, you just add a NAME= value to the GRAPH line in + the .theme file. Then if you want to use that object, instead of calling + createGraph, you can call this function. +

    + +

    The name you pass to the function is the same one that you gave it for + the NAME= parameter in the .theme file. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string name -- name of the graph to get +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to graph +

    +
    +
    + +

    +Graph/hideGraph

    + +

    [top]

    +

    SYNOPSIS

    +

    long hideGraph(widget, graph) +

    +

    DESCRIPTION

    +

    This hides an graph. In other words, during subsequent calls to + widgetUpdate(), this graph will not be drawn. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Graph/moveGraph

    + +

    [top]

    +

    SYNOPSIS

    +

    long moveGraph(widget, graph, x, y) +

    +

    DESCRIPTION

    +

    This will move graph to new x and y coordinates. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Graph/resizeGraph

    + +

    [top]

    +

    SYNOPSIS

    +

    long resizeGraph(widget, graph, w, h) +

    +

    DESCRIPTION

    +

    This will resize graph to new height and width. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    • long w -- new width +
    • +
    • long h -- new height +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Graph/setGraphColor

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple setGraphColor(widget, graph, red, green, blue) +

    +

    DESCRIPTION

    +

    Set current graph color +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    • long red -- red component of color +
    • +
    • long green -- green component of color +
    • +
    • long blue -- blue component of color +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Graph/setGraphMinMax

    + +

    [top]

    +

    SYNOPSIS

    +

    long setGraphMinMax(widget, graph, min, max) +

    +

    DESCRIPTION

    +

    Returns current graph value. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    • long min -- min value +
    • +
    • long max -- max value +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Graph/setGraphSensor

    + +

    [top]

    +

    SYNOPSIS

    +

    long setGraphSensor(widget, graph, sensor) +

    +

    DESCRIPTION

    +

    Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    • string sensor -- new sensor as in theme files +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Graph/setGraphValue

    + +

    [top]

    +

    SYNOPSIS

    +

    long setGraphValue(widget, graph, value) +

    +

    DESCRIPTION

    +

    Sets current graph value. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    • long value -- new value +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Graph/showGraph

    + +

    [top]

    +

    SYNOPSIS

    +

    long showGraph(widget, graph) +

    +

    DESCRIPTION

    +

    This shows an graph. In other words, during subsequent calls to + widgetUpdate(), this graph will be drawn. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long graph -- pointer to graph +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Config/addMenuConfigOption

    + +

    [top]

    +

    SYNOPSIS

    +

    long addMenuConfigOption(widget, key, name) +

    +

    DESCRIPTION

    +

    SuperKaramba supports a simplistic configuration pop-up menu. This menu + appears when you right-click on a widget and choose Configure Theme. + Basically, it allows you to have check-able entrys in the menu to allow + the user to enable or disable features in your theme. +

    + +

    Before you use any configuration menu stuff, you NEED to add a new + callback to your script: +

    + +

    def menuOptionChanged(widget, key, value): +

    + +

    This will get called whenever a config menu option is changed. Now you + can add items to the config menu: +

    + +

    addMenuConfigOption(widget, String key, String name) +

    + +

    Key is the name of a key value where the value will be saved + automatically into the widget's config file. Name is the actual text that + will show up in the config menu. +

    + +

    For example, I could allow the user to enable or disable a clock showing + up in my theme: +

    + +

    karamba.addMenuConfigOption(widget, "showclock", "Display a clock") +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string key -- key for menu item +
    • +
    • string name -- name of the graph to get +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Config/readConfigEntry

    + +

    [top]

    +

    SYNOPSIS

    +

    string|long readConfigEntry(widget, key, value) +

    +

    DESCRIPTION

    +

    This function reads an entry from the config file with the given key. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string key -- key for config item +
    • +
    +

    +

    RETURN VALUE

    +

    config value for key +

    +
    +
    + +

    +Config/readMenuConfigOption

    + +

    [top]

    +

    SYNOPSIS

    +

    long readMenuConfigOption(widget, key) +

    +

    DESCRIPTION

    +

    This returns whether or not the given option is checked in the theme's + Configure Theme menu. +

    + +

    See addMenuConfigOption for a more detailed explanation. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string key -- key for menu item +
    • +
    +

    +

    RETURN VALUE

    +

    0 is returned if it is not checked and 1 is returned if it is. +

    +
    +
    + +

    +Config/setMenuConfigOption

    + +

    [top]

    +

    SYNOPSIS

    +

    long setMenuConfigOption(widget, key, value) +

    +

    DESCRIPTION

    +

    This sets whether or not the given option is checked in the theme's + Configure Theme menu. Value should be 0 if key should not be checked and + 1 if key should be checked. +

    + +

    See addMenuConfigOption for a more detailed explanation. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string key -- key for menu item +
    • +
    • int value -- 1 if checked +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Config/writeConfigEntry

    + +

    [top]

    +

    SYNOPSIS

    +

    long writeConfigEntry(widget, key, value) +

    +

    DESCRIPTION

    +

    SuperKaramba automatically supports configuration files for each theme. + These files will be saved in /your/home/dir/.superkaramba/ and will be + named themenamerc where themename is the name of the theme. +

    + +

    This function writes an entry into the config file with the given key and + value. +

    + +

    For example, to save my favorite color, I would do + karamba.writeConfigEntry(widget, "FavColor", "Red") +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string key -- key for config item +
    • +
    • string value -- config value +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Bar/createBar

    + +

    [top]

    +

    SYNOPSIS

    +

    long createBar(widget, x, y, w, h, image) +

    +

    DESCRIPTION

    +

    This creates a bar at x,y with width and height w,h. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    • long w -- width +
    • +
    • long h -- height +
    • +
    • string image -- Path to image +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to new bar meter +

    +
    +
    + +

    +Bar/deleteBar

    + +

    [top]

    +

    SYNOPSIS

    +

    long deleteBar(widget, bar) +

    +

    DESCRIPTION

    +

    This deletes bar. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long widget -- bar +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Bar/getBarImage

    + +

    [top]

    +

    SYNOPSIS

    +

    string getBarImage(widget, bar) +

    +

    DESCRIPTION

    +

    Get bar image +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    +

    +

    RETURN VALUE

    +

    path to bar image +

    +
    +
    + +

    +Bar/getBarMinMax

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getBarMinMax(widget, bar) +

    +

    DESCRIPTION

    +

    Returns current bar value. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    +

    +

    RETURN VALUE

    +

    min & max +

    +
    +
    + +

    +Bar/getBarPos

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getBarPos(widget, bar) +

    +

    DESCRIPTION

    +

    Given a reference to a bar object, this will return a tuple + containing the x and y coordinate of a bar object. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    +

    +

    RETURN VALUE

    +

    pos +

    +
    +
    + +

    +Bar/getBarSensor

    + +

    [top]

    +

    SYNOPSIS

    +

    string getBarSensor(widget, bar) +

    +

    DESCRIPTION

    +

    Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    +

    +

    RETURN VALUE

    +

    sensor string +

    +
    +
    + +

    +Bar/getBarSize

    + +

    [top]

    +

    SYNOPSIS

    +

    tuple getBarSize(widget, bar) +

    +

    DESCRIPTION

    +

    Given a reference to a bar object, this will return a tuple + containing the height and width of a bar object. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    +

    +

    RETURN VALUE

    +

    size +

    +
    +
    + +

    +Bar/getBarValue

    + +

    [top]

    +

    SYNOPSIS

    +

    long getBarValue(widget, bar) +

    +

    DESCRIPTION

    +

    Returns current bar value. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    +

    +

    RETURN VALUE

    +

    value +

    +
    +
    + +

    +Bar/getBarVertical

    + +

    [top]

    +

    SYNOPSIS

    +

    string getBarVertical(widget, bar) +

    +

    DESCRIPTION

    +

    Check if bar is vertical bar +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    +

    +

    RETURN VALUE

    +

    1 if vertical +

    +
    +
    + +

    +Bar/getThemeBar

    + +

    [top]

    +

    SYNOPSIS

    +

    long getThemeBar(widget, name) +

    +

    DESCRIPTION

    +

    You can reference bar in your python code that was created in the + theme file. Basically, you just add a NAME= value to the BAR line in + the .theme file. Then if you want to use that object, instead of calling + createBar, you can call this function. +

    + +

    The name you pass to the function is the same one that you gave it for + the NAME= parameter in the .theme file. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • string name -- name of the bar to get +
    • +
    +

    +

    RETURN VALUE

    +

    Pointer to bar +

    +
    +
    + +

    +Bar/hideBar

    + +

    [top]

    +

    SYNOPSIS

    +

    long hideBar(widget, bar) +

    +

    DESCRIPTION

    +

    This hides an bar. In other words, during subsequent calls to + widgetUpdate(), this bar will not be drawn. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Bar/moveBar

    + +

    [top]

    +

    SYNOPSIS

    +

    long moveBar(widget, bar, x, y) +

    +

    DESCRIPTION

    +

    This will move bar to new x and y coordinates. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    • long x -- x coordinate +
    • +
    • long y -- y coordinate +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Bar/resizeBar

    + +

    [top]

    +

    SYNOPSIS

    +

    long resizeBar(widget, bar, w, h) +

    +

    DESCRIPTION

    +

    This will resize bar to new height and width. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    • long w -- new width +
    • +
    • long h -- new height +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Bar/setBarImage

    + +

    [top]

    +

    SYNOPSIS

    +

    long setBarImage(widget, bar, image) +

    +

    DESCRIPTION

    +

    Get bar image +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    • string image -- new image +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Bar/setBarMinMax

    + +

    [top]

    +

    SYNOPSIS

    +

    long setBarMinMax(widget, bar, min, max) +

    +

    DESCRIPTION

    +

    Returns current bar value. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    • long min -- min value +
    • +
    • long max -- max value +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Bar/setBarSensor

    + +

    [top]

    +

    SYNOPSIS

    +

    long setBarSensor(widget, bar, sensor) +

    +

    DESCRIPTION

    +

    Get current sensor string +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    • string sensor -- new sensor as in theme files +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Bar/setBarValue

    + +

    [top]

    +

    SYNOPSIS

    +

    long setBarValue(widget, bar, value) +

    +

    DESCRIPTION

    +

    Sets current bar value. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    • long value -- new value +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Bar/setBarVertical

    + +

    [top]

    +

    SYNOPSIS

    +

    long setBarVertical(widget, bar) +

    +

    DESCRIPTION

    +

    Set bar vertical +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    • long vertical -- 1 if vertical +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    +
    + +

    +Bar/showBar

    + +

    [top]

    +

    SYNOPSIS

    +

    long showBar(widget, bar) +

    +

    DESCRIPTION

    +

    This shows an bar. In other words, during subsequent calls to + widgetUpdate(), this bar will be drawn. +

    +

    ARGUMENTS

    +
    • long widget -- karamba +
    • +
    • long bar -- pointer to bar +
    • +
    +

    +

    RETURN VALUE

    +

    1 if successful +

    +
    + + diff --git a/superkaramba/examples/autoHide/main.py b/superkaramba/examples/autoHide/main.py new file mode 100644 index 0000000..85e2b37 --- /dev/null +++ b/superkaramba/examples/autoHide/main.py @@ -0,0 +1,62 @@ +#this import statement allows access to the karamba functions +import karamba + +hidden = 0 +counter = 0 + +def initWidget(widget): + global hidden + hidden = 0 + +def widgetUpdated(widget): + global hidden + global counter + if hidden == 0: + counter = counter + 1 + + if (counter > 5): + hidden = 1 + karamba.moveWidget(widget, 0, -210) + + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetClicked(widget, x, y, button): + pass + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + #Warning: Don't do anything too intensive here + #You don't want to run some complex piece of code everytime the mouse moves + global hidden + global counter + if (hidden==1): + karamba.moveWidget(widget, 0, 0) + hidden = 0 + counter = 0 + + + +# This will be printed when the widget loads. +print "Loaded my python extension!" + diff --git a/superkaramba/examples/autoHide/main.theme b/superkaramba/examples/autoHide/main.theme new file mode 100644 index 0000000..fd924dc --- /dev/null +++ b/superkaramba/examples/autoHide/main.theme @@ -0,0 +1,42 @@ +KARAMBA X=0 Y=0 W=390 H=220 LOCKED=true INTERVAL=1000 ONTOP=false + +IMAGE X=0 Y=0 PATH="pics/calendar.png" + + X=10 Y=-15 +#CPU +GRAPH X=5 Y=49 W=293 H=36 SENSOR=CPU POINTS=100 COLOR=100,100,100 INTERVAL=1000 +IMAGE X=0 Y=47 PATH="pics/label3.png" +BAR X=0 Y=47 W=300 H=40 PATH="pics/bar3.png" SENSOR=CPU +TEXT X=310 Y=56 SENSOR=CPU FORMAT="%v%" COLOR=200,200,200 FONTSIZE=10 FONT="arial" SHADOW=1 + +#time +TEXT X=2 Y=27 SENSOR=TIME COLOR=200,200,200 FONTSIZE=10 FONT="arial" SHADOW=1 + +#date +TEXT X=50 Y=31 SENSOR=TIME FORMAT="ddd d MMM" COLOR=180,180,180 FONTSIZE=8 FONT="arial" + +#mem +IMAGE X=0 Y=97 PATH="pics/label3.png" +BAR X=0 Y=97 W=300 H=40 PATH="pics/bar3.png" SENSOR=MEMORY INTERVAL=2000 +TEXT X=310 Y=106 SENSOR=MEMORY FORMAT="%fmMB" COLOR=200,200,200 FONTSIZE=10 FONT="arial" SHADOW=1 + + +#swap +IMAGE X=0 Y=147 PATH="pics/label4.png" +BAR X=0 Y=147 W=300 H=20 PATH="pics/bar4.png" SENSOR=MEMORY FORMAT="%us" +TEXT X=310 Y=151 SENSOR=MEMORY FORMAT="%fsMB" COLOR=170,170,170 FONTSIZE=8 FONT="arial" + + +#network +GRAPH X=2 Y=179 W=296 H=36 SENSOR=NETWORK FORMAT="%in" POINTS=100 COLOR=100,100,100 MAX=250 INTERVAL=1000 +GRAPH X=2 Y=179 W=296 H=36 SENSOR=NETWORK FORMAT="%out" POINTS=100 COLOR=80,80,80 MAX=250 +IMAGE X=0 Y=177 PATH="pics/label3.png" +BAR X=0 Y=177 W=300 H=40 PATH="pics/bar3.png" SENSOR=NETWORK FORMAT="%in" MAX=250 +BAR X=0 Y=177 W=300 H=40 PATH="pics/bar3.png" SENSOR=NETWORK FORAMT="%out" MAX=250 +TEXT X=310 Y=182 SENSOR=NETWORK COLOR=200,200,200 FORMAT="%inKBs" FONTSIZE=9 FONT="arial" DECIMALS=1 +TEXT X=310 Y=200 SENSOR=NETWORK COLOR=200,200,200 FORMAT="%outKBs" FONTSIZE=9 FONT="arial" DECIMALS=1 + +#uptime +TEXT X=240 Y=32 SENSOR=UPTIME COLOR=190,190,190 FONTSIZE=7 FONT="arial" + + diff --git a/superkaramba/examples/autoHide/pics/MSN-64x64.png b/superkaramba/examples/autoHide/pics/MSN-64x64.png new file mode 100644 index 0000000..3dc0e39 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/MSN-64x64.png differ diff --git a/superkaramba/examples/autoHide/pics/MSN-96x96.png b/superkaramba/examples/autoHide/pics/MSN-96x96.png new file mode 100644 index 0000000..bf0f63a Binary files /dev/null and b/superkaramba/examples/autoHide/pics/MSN-96x96.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_House-64x64.png b/superkaramba/examples/autoHide/pics/Tux_House-64x64.png new file mode 100644 index 0000000..c0b657e Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_House-64x64.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_House-96x96.png b/superkaramba/examples/autoHide/pics/Tux_House-96x96.png new file mode 100644 index 0000000..dc217f3 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_House-96x96.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_Mail-64x64.png b/superkaramba/examples/autoHide/pics/Tux_Mail-64x64.png new file mode 100644 index 0000000..4e29c4d Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_Mail-64x64.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_Mail-96x96.png b/superkaramba/examples/autoHide/pics/Tux_Mail-96x96.png new file mode 100644 index 0000000..9de2596 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_Mail-96x96.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_Mozilla-64x64.png b/superkaramba/examples/autoHide/pics/Tux_Mozilla-64x64.png new file mode 100644 index 0000000..d2413cd Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_Mozilla-64x64.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_Mozilla-96x96.png b/superkaramba/examples/autoHide/pics/Tux_Mozilla-96x96.png new file mode 100644 index 0000000..5f24afb Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_Mozilla-96x96.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_Sherlock-64x64.png b/superkaramba/examples/autoHide/pics/Tux_Sherlock-64x64.png new file mode 100644 index 0000000..e883671 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_Sherlock-64x64.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_Sherlock-96x96.png b/superkaramba/examples/autoHide/pics/Tux_Sherlock-96x96.png new file mode 100644 index 0000000..20628f1 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_Sherlock-96x96.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_Terminal-64x64.png b/superkaramba/examples/autoHide/pics/Tux_Terminal-64x64.png new file mode 100644 index 0000000..066c318 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_Terminal-64x64.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_Terminal-96x96.png b/superkaramba/examples/autoHide/pics/Tux_Terminal-96x96.png new file mode 100644 index 0000000..5eedfe1 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_Terminal-96x96.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_iPhoto-64x64.png b/superkaramba/examples/autoHide/pics/Tux_iPhoto-64x64.png new file mode 100644 index 0000000..9906efc Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_iPhoto-64x64.png differ diff --git a/superkaramba/examples/autoHide/pics/Tux_iPhoto-96x96.png b/superkaramba/examples/autoHide/pics/Tux_iPhoto-96x96.png new file mode 100644 index 0000000..aa6450c Binary files /dev/null and b/superkaramba/examples/autoHide/pics/Tux_iPhoto-96x96.png differ diff --git a/superkaramba/examples/autoHide/pics/bar3.png b/superkaramba/examples/autoHide/pics/bar3.png new file mode 100644 index 0000000..c6d4b9e Binary files /dev/null and b/superkaramba/examples/autoHide/pics/bar3.png differ diff --git a/superkaramba/examples/autoHide/pics/bar4.png b/superkaramba/examples/autoHide/pics/bar4.png new file mode 100644 index 0000000..9e87bff Binary files /dev/null and b/superkaramba/examples/autoHide/pics/bar4.png differ diff --git a/superkaramba/examples/autoHide/pics/calendar.png b/superkaramba/examples/autoHide/pics/calendar.png new file mode 100644 index 0000000..fc0e466 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/calendar.png differ diff --git a/superkaramba/examples/autoHide/pics/ctrl center-64x64.png b/superkaramba/examples/autoHide/pics/ctrl center-64x64.png new file mode 100644 index 0000000..3c6d78f Binary files /dev/null and b/superkaramba/examples/autoHide/pics/ctrl center-64x64.png differ diff --git a/superkaramba/examples/autoHide/pics/ctrl center-96x96.png b/superkaramba/examples/autoHide/pics/ctrl center-96x96.png new file mode 100644 index 0000000..43e7f3d Binary files /dev/null and b/superkaramba/examples/autoHide/pics/ctrl center-96x96.png differ diff --git a/superkaramba/examples/autoHide/pics/iconbarback.png b/superkaramba/examples/autoHide/pics/iconbarback.png new file mode 100644 index 0000000..8a1f2f5 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/iconbarback.png differ diff --git a/superkaramba/examples/autoHide/pics/label3.png b/superkaramba/examples/autoHide/pics/label3.png new file mode 100644 index 0000000..613ae17 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/label3.png differ diff --git a/superkaramba/examples/autoHide/pics/label4.png b/superkaramba/examples/autoHide/pics/label4.png new file mode 100644 index 0000000..d6de907 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/label4.png differ diff --git a/superkaramba/examples/autoHide/pics/osxbarback.png b/superkaramba/examples/autoHide/pics/osxbarback.png new file mode 100644 index 0000000..cb26088 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/osxbarback.png differ diff --git a/superkaramba/examples/autoHide/pics/osxbarbackBig.png b/superkaramba/examples/autoHide/pics/osxbarbackBig.png new file mode 100644 index 0000000..07c6971 Binary files /dev/null and b/superkaramba/examples/autoHide/pics/osxbarbackBig.png differ diff --git a/superkaramba/examples/autoHide/pics/pointer.png b/superkaramba/examples/autoHide/pics/pointer.png new file mode 100644 index 0000000..379079a Binary files /dev/null and b/superkaramba/examples/autoHide/pics/pointer.png differ diff --git a/superkaramba/examples/bar/bar.py b/superkaramba/examples/bar/bar.py new file mode 100644 index 0000000..b018fe8 --- /dev/null +++ b/superkaramba/examples/bar/bar.py @@ -0,0 +1,93 @@ +#this import statement allows access to the karamba functions +import karamba + +bars = [0,0,0,0,0,0,0,0] +b = 0 + +#this is called when you widget is initialized +def initWidget(widget): + global bars, b + bars[0] = karamba.getThemeBar(widget, "bar0") + bars[1] = karamba.getThemeBar(widget, "bar1") + bars[2] = karamba.getThemeBar(widget, "bar2") + bars[3] = karamba.getThemeBar(widget, "bar3") + bars[4] = karamba.getThemeBar(widget, "bar4") + bars[5] = karamba.getThemeBar(widget, "bar5") + bars[6] = karamba.getThemeBar(widget, "bar6") + bars[7] = karamba.getThemeBar(widget, "bar7") + + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + global bars, b + + # vertical & bitmap + b = karamba.getBarVertical(widget, bars[7]) + print "getVertical: " + str(b) + bmp = karamba.getBarImage(widget, bars[7]) + print "getBitmap: " + str(bmp) + b = (b+1)%2 + karamba.setBarVertical(widget, bars[7], b) + if(b): + karamba.setBarImage(widget, bars[7], "ver.png") + karamba.resizeBar(widget, bars[7], 20, 200) + else: + karamba.setBarImage(widget, bars[7], "hor.png") + karamba.resizeBar(widget, bars[7], 200, 20) + + # size & resize + size = karamba.getBarSize(widget, bars[1]) + print "getBarSize: " + str(size) + size = ((b * 100) + 100, size[1]) + karamba.resizeBar(widget, bars[1], size[0], size[1]) + + # pos & move + pos = karamba.getBarPos(widget, bars[2]) + print "getBarPos: " + str(pos) + pos = (b * 200, pos[1]) + karamba.moveBar(widget, bars[2], pos[0], pos[1]) + + # Hide & Show + if(b): + karamba.hideBar(widget, bars[3]) + else: + karamba.showBar(widget, bars[3]) + + # Value + v = karamba.getBarValue(widget, bars[5]) + print "getBarValue: ", v + v = (v + 10) % 110 + karamba.setBarValue(widget, bars[5], v) + + # Min Max + minmax = karamba.getBarMinMax(widget, bars[6]) + print "getBarMinMax: " + str(minmax) + minmax = (0, (b * 100) + 100) + karamba.setBarMinMax(widget, bars[6], minmax[0], minmax[1]) + + # Sensor + sensor = karamba.getBarSensor(widget, bars[4]) + print "getSensor: " + str(sensor) + if(b): + karamba.setBarSensor(widget, bars[4], 'SENSOR=SENSOR TYPE="cpu_temp"') + else: + karamba.setBarSensor(widget, bars[4], 'SENSOR=CPU') + + # Create & delete + if(bars[0]): + karamba.deleteBar(widget, bars[0]) + bars[0] = 0 + else: + bars[0] = karamba.createBar(widget, 0, 20, 200, 20) + karamba.setBarImage(widget, bars[0], "hor.png") + karamba.setBarValue(widget, bars[0], 100) + +def widgetClicked(widget, x, y, button): + pass + +def widgetMouseMoved(widget, x, y, button): + pass + +# This will be printed when the widget loads. +print "Loaded Bar test python extension!" diff --git a/superkaramba/examples/bar/bar.theme b/superkaramba/examples/bar/bar.theme new file mode 100644 index 0000000..ec569e9 --- /dev/null +++ b/superkaramba/examples/bar/bar.theme @@ -0,0 +1,26 @@ +KARAMBA x=100 y=10 w=600 h=580 INTERVAL=1000 LOCKED=true +DEFAULTFONT font="Bitstream Vera Sans" fontsize=16 color=200,200,200 + +TEXT x=0 Y=0 w=600 h=20 VALUE="createBar & deleteBar" name=text0 +BAR x=0 Y=20 w=200 h=20 path=hor.png value=100 min=0 max=100 name=bar0 + +TEXT x=0 Y=45 w=600 h=20 VALUE="getBarSize & resizeBar" name=text1 +BAR x=0 Y=65 w=100 h=20 path=hor.png value=100 min=0 max=100 name=bar1 + +TEXT x=0 Y=90 w=600 h=20 VALUE="getBarPos & moveBar" name=text2 +BAR x=0 Y=110 w=200 h=20 path=hor.png value=100 min=0 max=100 name=bar2 + +TEXT x=0 Y=135 w=600 h=20 VALUE="hideBar & showBar" name=text3 +BAR x=0 Y=155 w=200 h=20 path=hor.png value=100 min=0 max=100 name=bar3 + +TEXT x=0 Y=180 w=600 h=20 VALUE="getBarSensor & setBarSensor" name=text4 +BAR x=0 Y=200 w=200 h=20 path=hor.png value=50 min=0 max=100 name=bar4 + +TEXT x=0 Y=225 w=600 h=20 VALUE="getBarValue & setBarValue" name=text5 +BAR x=0 Y=245 w=200 h=20 path=hor.png value=50 min=0 max=100 name=bar5 + +TEXT x=0 Y=270 w=600 h=20 VALUE="getBarMinMax & setBarMinMax" name=text6 +BAR x=0 Y=290 w=200 h=20 path=hor.png value=50 min=0 max=100 name=bar6 + +TEXT x=0 Y=315 w=600 h=20 VALUE="getBarVertical, setBarVertical, setBarImage & getBarImage" name=text7 +BAR x=0 Y=335 w=200 h=20 path=hor.png value=100 min=0 max=100 name=bar7 diff --git a/superkaramba/examples/bar/hor.png b/superkaramba/examples/bar/hor.png new file mode 100644 index 0000000..56dbbc0 Binary files /dev/null and b/superkaramba/examples/bar/hor.png differ diff --git a/superkaramba/examples/bar/ver.png b/superkaramba/examples/bar/ver.png new file mode 100644 index 0000000..928b869 Binary files /dev/null and b/superkaramba/examples/bar/ver.png differ diff --git a/superkaramba/examples/change_interval/interval.py b/superkaramba/examples/change_interval/interval.py new file mode 100644 index 0000000..6c3422a --- /dev/null +++ b/superkaramba/examples/change_interval/interval.py @@ -0,0 +1,60 @@ +# +# Written by Luke Kenneth Casson Leighton + +# This theme is demonstrates the interval timer changing. + +#this import statement allows access to the karamba functions +import karamba + +seq = 0 +text = None + +#this is called when you widget is initialized +def initWidget(widget): + + karamba.redrawWidget(widget) + +# sequence drops down to zero and changes the time interval to 1 second. +# keeps counting down thereafter... + +def widgetUpdated(widget): + global seq + global text + + seq -= 1 + + if seq <= 0: + karamba.changeInterval(widget, 1000) + + if seq <= 0: + message = "biding-time seq:%d" % -seq + else: + message = "wiggle seq:%d" % seq + + # delete previous text if exists. + if text is not None: + karamba.deleteText(widget, text) + + # display new message + text = karamba.createText(widget, 0, 20, 300, 20, message) + karamba.changeTextColor(widget, text, 252,252,252) + + karamba.redrawWidget(widget) + +# wiggle the mouse over the widget to get the sequence number increased more. +# also set the refresh rate to 50ms so that the theme has to fight against +# the wiggling. + +def widgetMouseMoved(widget, x, y, button): + global seq + + if seq <= 0: + seq = 0 + karamba.changeInterval(widget, 50) + + seq += 1 + + +# This will be printed when the widget loads. +print "Loaded my python extension!" + diff --git a/superkaramba/examples/change_interval/interval.theme b/superkaramba/examples/change_interval/interval.theme new file mode 100644 index 0000000..5711ece --- /dev/null +++ b/superkaramba/examples/change_interval/interval.theme @@ -0,0 +1,2 @@ +KARAMBA x=200 y=100 w=300 h=40 INTERVAL=200 LOCKED=true +TEXT x=0 y=0 w=300 h=20 value="wiggle the mouse over me" color=200,252,200 diff --git a/superkaramba/examples/control_management/mgmt.py b/superkaramba/examples/control_management/mgmt.py new file mode 100644 index 0000000..eae98c2 --- /dev/null +++ b/superkaramba/examples/control_management/mgmt.py @@ -0,0 +1,49 @@ +# +# Written by Luke Kenneth Casson Leighton + +#this import statement allows access to the karamba functions +import karamba + +do_nothing_txt = None +mgmt_txt = None + + +#this is called when you widget is initialized +def initWidget(widget): + global do_nothing_txt + global do_something_txt + + # display new message + do_nothing_txt = karamba.createText(widget, 0, 00, 300, 20, + "Right mouse click me!") + karamba.changeTextColor(widget, do_nothing_txt, 252,252,252) + mgmt_txt = karamba.createText(widget, 0, 20, 300, 20, + "Righ mouse click me too!") + karamba.changeTextColor(widget, mgmt_txt, 252,252,252) + + karamba.redrawWidget(widget) + + karamba.setWantRightButton(widget, 1) + +def widgetUpdated(widget): + karamba.redrawWidget(widget) + +def widgetClicked(widget, x, y, button): + global do_nothing_txt + + if y < 20: + if do_nothing_txt is not None: + karamba.deleteText(widget, do_nothing_txt) + do_nothing_txt = karamba.createText(widget, + 0, 0, 300, 20, "I don't do anything when clicking here.") + karamba.changeTextColor(widget, do_nothing_txt, + 255,200,200) + karamba.redrawWidget(widget) + return + + karamba.managementPopup(widget) + + +# This will be printed when the widget loads. +print "Loaded my python extension!" + diff --git a/superkaramba/examples/control_management/mgmt.theme b/superkaramba/examples/control_management/mgmt.theme new file mode 100644 index 0000000..f54c88f --- /dev/null +++ b/superkaramba/examples/control_management/mgmt.theme @@ -0,0 +1 @@ +KARAMBA x=200 y=100 w=300 h=40 INTERVAL=200 LOCKED=true diff --git a/superkaramba/examples/disableRightClickMenu/disable_menu.py b/superkaramba/examples/disableRightClickMenu/disable_menu.py new file mode 100644 index 0000000..6c524dd --- /dev/null +++ b/superkaramba/examples/disableRightClickMenu/disable_menu.py @@ -0,0 +1,176 @@ +#this import statement allows access to the karamba functions +import karamba + + +#this is called when your widget is initialized +def initWidget(widget): + global clicked, text2 + text2 = 0 + text = 'This theme demonstrates how to manipulate the \nright click menu option.' + text += '\nClick the theme with your left mouse button \nto disable and then re-enable the right click menu.' + karamba.createText(widget,5,5,400,20,text) + clicked = False + karamba.redrawWidget(widget) + +#This is called when your widget is closed. You can use this to clean +#up open files, etc. You don't need to delete text and images in your +#theme. That is done automatically. This callback is just for cleaning up +#external things. Most people don't need to put anything here. +def widgetClosed(widget): + pass + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + pass + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + global clicked,text2 + if clicked and button == 1: + clicked = False + karamba.setWantRightButton(widget, False) + newText = "Enabling the SuperKaramba right click \nconfiguration menu." + if text2: + karamba.deleteText(widget,text2) + text2 = karamba.createText(widget,5,70,400,20,newText) + print newText + elif not clicked and button == 1: + clicked = True + karamba.setWantRightButton(widget, True) + newText = "Disabling the SuperKaramba right click \nconfiguration menu." + if text2: + karamba.deleteText(widget,text2) + text2 = karamba.createText(widget,5,70,400,20,newText) + print newText + if button == 3: + print "Clicking the right mouse button is recognized now." + karamba.redrawWidget(widget) + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + #Warning: Don't do anything too intensive here + #You don't want to run some complex piece of code everytime the mouse moves + pass + + +#This gets called when an item is clicked in a popup menu you have created. +# menu = a reference to the menu +# id = the number of the item that was clicked. +def menuItemClicked(widget, menu, id): + pass + +#This gets called when an item is clicked in the theme CONFIGURATION menu, +#not the popup menus that you create. +# key = the reference to the configuration key that was changed +# value = the new value (true or false) that was selected +def menuOptionChanged(widget, key, value): + pass + +#This gets called when a meter (image, text, etc) is clicked. +# NOTE you must use attachClickArea() to make a meter +# clickable. +# widget = reference to your theme +# meter = the meter clicked +# button = the button clicked (see widgetClicked for button numbers) +def meterClicked(widget, meter, button): + pass + +#This gets called when a command you have executed with executeInteractive() outputs something +#to stdout. This way you can get the output of for example kdialog without freezing up the widget +#waiting for kdialog to end. +# widget = reference to your theme +# pid = process number of the program outputting (use this if you execute more than out process) +# output = the text the program outputted to stdout +def commandOutput(widget, pid, output): + pass + +#This gets called when an item is dropped on this widget. +# NOTE you have to call acceptDrops() before your widget will accept drops. +# widget = reference to your theme +# dropText = the text of the dropped item (probably a URL to it's location in KDE) +def itemDropped(widget, dropText): + pass + + +#This gets called when a new program is LOADING in KDE. When it is done +#loading, startupRemoved() is called, followed by taskAdded(). +# widget = reference to your widget +# task = A refence to the task that is starting. +def startupAdded(widget, startup): + pass + +#This gets called when a new program is done LOADING in KDE. +# widget = reference to your widget +# task = A refence to the task that just finished loading. +def startupRemoved(widget, startup): + pass + +#This is called every time a new task (program) is started in KDE. +# widget = reference to your widget +# task = A refence to the new task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def taskAdded(widget, task): + pass + +#This is called everytime a task (program) is closed in KDE. +# widget = reference to your widget +# task = A refence to the task. +def taskRemoved(widget, task): + pass + +#This is called everytime a different task gains focus (IE, the user clicks +#on a different window). +# widget = reference to your widget +# task = A refence to the task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def activeTaskChanged(widget, task): + pass + +#This is called everytime the systray you created with createSystray() is updated +def systrayUpdated(widget): + pass + +#This is called everytime the current desktop changes +# widget = reference to your widget +# desktop = the current desktop +def desktopChanged(widget, desktop): + pass + +#This is called everytime the wallpaper changes on a desktop +# widget = reference to your widget +# desktop = the desktop whose wallpaper changed +def wallpaperChanged(widget, desktop): + pass + +#This is called everytime there is a key press in any focused input field +# widget = reference to your widget +# meter = reference to an input box +# char = the key that was pressed +def keyPressed(widget, meter, char): + pass + +# This will be printed when the widget loads. +print "Loaded my python extension!" diff --git a/superkaramba/examples/disableRightClickMenu/disable_menu.theme b/superkaramba/examples/disableRightClickMenu/disable_menu.theme new file mode 100644 index 0000000..cbd905a --- /dev/null +++ b/superkaramba/examples/disableRightClickMenu/disable_menu.theme @@ -0,0 +1 @@ +karamba x=0 y=0 w=300 h=100 locked=true diff --git a/superkaramba/examples/globalMouse/README b/superkaramba/examples/globalMouse/README new file mode 100644 index 0000000..758ce4b --- /dev/null +++ b/superkaramba/examples/globalMouse/README @@ -0,0 +1,29 @@ + +Karamba Eyes 0.6 by Wilfried.Huss@gmx.at +---------------------------------------- + +Karamba Eyes is a implementation of the classic xeyes for superkaramba. + + +INSTALLATION: + Karamba Eyes needs a small Python extension module named xcursor + which is implemented in the file extension/xcursor.c. + + To build it go to the extension subdirectory and type + + python setup.py build + + (The Python develop package needs to be installed) + + This creates the shared library xcursor.so, probably in a subdirectory + named build. This file needs to be copied in the same directory as the + eyes.theme and eyes.py file. + + A precompiled xcursor.so file is included (Compiled on Mandrake 9.1). + +CHANGES: + * Moving the theme now works as it should. + * Widget Mask added + +TODO: + Add Theme Support diff --git a/superkaramba/examples/globalMouse/extension/setup.py b/superkaramba/examples/globalMouse/extension/setup.py new file mode 100644 index 0000000..f33f8a6 --- /dev/null +++ b/superkaramba/examples/globalMouse/extension/setup.py @@ -0,0 +1,12 @@ +from distutils.core import setup, Extension + +module1 = Extension('xcursor', + include_dirs = ['/usr/X11R6/include'], + libraries = ['X11'], + library_dirs = ['/usr/X11R6/lib'], + sources = ['xcursor.c']) + +setup (name = 'XMouseCursor', + version = '1.0', + description = 'Determines the position of the X mouse cursor', + ext_modules = [module1]) diff --git a/superkaramba/examples/globalMouse/extension/xcursor.c b/superkaramba/examples/globalMouse/extension/xcursor.c new file mode 100644 index 0000000..8dad240 --- /dev/null +++ b/superkaramba/examples/globalMouse/extension/xcursor.c @@ -0,0 +1,104 @@ +/* + * This module is based on code by found in comp.lang.python: + * http://groups.google.at/groups?q=%22Re:+X+Gurus%22+group:comp.lang.python.*&hl=de&lr=&ie=UTF-8&selm=imnv4.314%24qL4.17232%40newsread1.prod.itd.earthlink.net&rnum=2 + * + * Build with: + * python setup.py build + * + * Copyright (C) 2003 Hans Karlsson + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of Superkaramba. + * + * Superkaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Superkaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Superkaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +static Display* display = 0; +static Window root; +static int screen; + + +static PyObject* xcursor_position(self, args) + PyObject* self; + PyObject* args; +{ + /* Determine X Cursor coordinates */ + Window root_return, child_return; + char* display_name; + int root_x_return, root_y_return; + int win_x_return, win_y_return; + unsigned int mask_return; + + if (! (display_name = getenv("DISPLAY")) ) + { + /* add error handling! */ + + /* + * fprintf(stderr,"environment variable DISPLAY must be set\n"); + * exit(-1); + */ + + return NULL; + } + + if ( display == 0) + { + if (! (display = XOpenDisplay(display_name)) ) + { + /* add error handling! */ + + /* + * fprintf(stderr,"%s: Cannot open display %s\n", argv[0], + * display_name); + * exit(-1); + */ + + return NULL; + } + + screen = DefaultScreen(display); + root = RootWindow(display, screen); + } + + XQueryPointer(display, root, &root_return, &child_return, + &root_x_return, &root_y_return, + &win_x_return, &win_y_return, + &mask_return); + + /* return Python Object */ + return Py_BuildValue("(i,i)", root_x_return, root_y_return); +} + +/* Method Table */ +static PyMethodDef xcursorMethods[] = +{ + {"position", xcursor_position, METH_VARARGS, "Query X Cursor Coordinates"}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +void initxcursor(void) +{ + (void) Py_InitModule("xcursor", xcursorMethods); +} + + diff --git a/superkaramba/examples/globalMouse/eyes.py b/superkaramba/examples/globalMouse/eyes.py new file mode 100644 index 0000000..b95f86d --- /dev/null +++ b/superkaramba/examples/globalMouse/eyes.py @@ -0,0 +1,192 @@ +#this import statement allows access to the karamba functions +import karamba + +#import os +import string +import math +import re + +import xcursor + +linkePupille = "" +rechtePupille = "" + +init = 0 + +#old curser pos +x_old = -1 +y_old = -1 + +#widget size +w_width = 167 +w_height = 111 + +#widget pos +w_x = 10 +w_y = 850 + +#eye center +lx, ly = 39, 55 +rx, ry = 126, 55 + +#eye size +la, lb = 25, 38 +ra, rb = 25, 38 + +#pupille size +lp_width, lp_height = 11, 17 +rp_width, rp_height = 11, 17 + +def pupille(mouse_x, mouse_y, eye_center_x, eye_center_y, eye_a, eye_b, widget_x, widget_y): + x = mouse_x - eye_center_x - widget_x + y = mouse_y - eye_center_y - widget_y + #print x, y + + r = math.sqrt(x * x + y * y) + phi = math.atan2(y, x) + #print phi * math.pi + + eye_x = eye_a * math.cos(phi) + eye_y = eye_b * math.sin(phi) + + eye_r = math.sqrt(eye_x * eye_x + eye_y * eye_y) + + if eye_r < r: + return int(eye_x + eye_center_x), int(eye_y + eye_center_y) + + return int(x + eye_center_x), int(y + eye_center_y) + + +#this is called when you widget is initialized +def initWidget(widget): + pass + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + global init + global linkePupille + global rechtePupille + + global w_width + global w_height + + global w_x + global w_y + + global lx + global ly + global la + global lb + + global lp_width + global lp_height + + global rx + global ry + global ra + global rb + + global rp_width + global rp_height + + global x_old + global y_old + + if init == 0: + theme_path = karamba.getThemePath(widget) + "/" + + # read widget coordinates from eyes.theme + # f = open(theme_path + "eyes.theme") + + # karamba_line = "" + #while re.compile('KARAMBA').search(karamba_line) == None: + # karamba_line = f.readline() + + #w_x = int(re.compile('X=([0-9]+)').search(karamba_line).group(1)) + #w_y = int(re.compile('Y=([0-9]+)').search(karamba_line).group(1)) + + #f.close() + + #karamba.createWidgetMask(widget, theme_path + "pics/mask.png") + + linkePupille = karamba.createImage(widget, 15, 30, theme_path + "pics/pupille.png") + rechtePupille = karamba.createImage(widget, 100, 30, theme_path + "pics/pupille.png") + init = 1 + + karamba.redrawWidget(widget) + + # query mouse-cursor position + x, y = xcursor.position() + + #fp = os.popen("./xpos") + #output = fp.read() + #x, y = output.split() + + #print x, y + + if x != x_old or y != y_old: + x_old, y_old = x, y + # Get Widget Position + w_x, w_y = karamba.getWidgetPosition(widget) + + # Calc left pupille + xp, yp = pupille (int(x), int(y), lx, ly, la, lb, w_x, w_y) + + xp = xp - lp_width / 2 + yp = yp - lp_height / 2 + #print xp, yp + + karamba.moveImage(widget, linkePupille, xp, yp) + + # Calc right pupille + xp, yp = pupille (int(x), int(y), rx, ry, ra, rb, w_x, w_y) + + xp = xp - rp_width / 2 + yp = yp - rp_height / 2 + #print xp, yp + + karamba.moveImage(widget, rechtePupille, xp, yp) + + karamba.redrawWidget(widget) + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + pass + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + #Warning: Don't do anything too intensive here + #You don't want to run some complex piece of code everytime the mouse moves + pass + #global linkePupille + + #karamba.moveImage(widget, linkePupille, x, y) + #karamba.redrawWidget(widget) + + +# This will be printed when the widget loads. +print "Loaded Karamba Eyes" + diff --git a/superkaramba/examples/globalMouse/eyes.theme b/superkaramba/examples/globalMouse/eyes.theme new file mode 100644 index 0000000..4f2417b --- /dev/null +++ b/superkaramba/examples/globalMouse/eyes.theme @@ -0,0 +1,3 @@ +KARAMBA X=5 Y=850 W=167 H=111 MASK="pics/mask.png" LOCKED=false INTERVAL=100 + +IMAGE X=0 Y=0 PATH="pics/eyes.png" diff --git a/superkaramba/examples/globalMouse/pics/eyes.png b/superkaramba/examples/globalMouse/pics/eyes.png new file mode 100644 index 0000000..50823d0 Binary files /dev/null and b/superkaramba/examples/globalMouse/pics/eyes.png differ diff --git a/superkaramba/examples/globalMouse/pics/eyes.xcf b/superkaramba/examples/globalMouse/pics/eyes.xcf new file mode 100644 index 0000000..3f097d1 Binary files /dev/null and b/superkaramba/examples/globalMouse/pics/eyes.xcf differ diff --git a/superkaramba/examples/globalMouse/pics/mask.png b/superkaramba/examples/globalMouse/pics/mask.png new file mode 100644 index 0000000..cf8fc03 Binary files /dev/null and b/superkaramba/examples/globalMouse/pics/mask.png differ diff --git a/superkaramba/examples/globalMouse/pics/pupille.png b/superkaramba/examples/globalMouse/pics/pupille.png new file mode 100644 index 0000000..11d971b Binary files /dev/null and b/superkaramba/examples/globalMouse/pics/pupille.png differ diff --git a/superkaramba/examples/globalMouse/xcursor.so b/superkaramba/examples/globalMouse/xcursor.so new file mode 100755 index 0000000..1ff08d5 Binary files /dev/null and b/superkaramba/examples/globalMouse/xcursor.so differ diff --git a/superkaramba/examples/graph/graph.py b/superkaramba/examples/graph/graph.py new file mode 100644 index 0000000..5798612 --- /dev/null +++ b/superkaramba/examples/graph/graph.py @@ -0,0 +1,89 @@ +#this import statement allows access to the karamba functions +import karamba + +graphs = [0,0,0,0,0,0,0,0] +b = 0 + +#this is called when you widget is initialized +def initWidget(widget): + global graphs + graphs[0] = karamba.getThemeGraph(widget, "graph0") + graphs[1] = karamba.getThemeGraph(widget, "graph1") + graphs[2] = karamba.getThemeGraph(widget, "graph2") + graphs[3] = karamba.getThemeGraph(widget, "graph3") + graphs[4] = karamba.getThemeGraph(widget, "graph4") + graphs[5] = karamba.getThemeGraph(widget, "graph5") + graphs[6] = karamba.getThemeGraph(widget, "graph6") + graphs[7] = karamba.getThemeGraph(widget, "graph7") + + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + global graphs, b + + b = (b+1)%2 + + # Create & delete + if(graphs[0]): + karamba.deleteGraph(widget, graphs[0]) + graphs[0] = 0 + print "Deleted graph." + else: + graphs[0] = karamba.createGraph(widget, 0, 20, 400, 30, 400) + print "Created graph: " + str(graphs[0]) + + # size & resize + size = karamba.getGraphSize(widget, graphs[1]) + print "getGraphSize: " + str(size) + size = ((b * 200) + 200, size[1]) + karamba.resizeGraph(widget, graphs[1], size[0], size[1]) + + # pos & move + pos = karamba.getGraphPos(widget, graphs[2]) + print "getGraphPos: " + str(pos) + pos = (b * 200, pos[1]) + karamba.moveGraph(widget, graphs[2], pos[0], pos[1]) + + # Hide & Show + if(b): + karamba.hideGraph(widget, graphs[3]) + else: + karamba.showGraph(widget, graphs[3]) + + # Sensor + sensor = karamba.getGraphSensor(widget, graphs[4]) + print "getSensor: " + str(sensor) + if(b): + karamba.setGraphSensor(widget, graphs[4], 'SENSOR=NETWORK FORMAT="%in"') + else: + karamba.setGraphSensor(widget, graphs[4], 'SENSOR=CPU') + + # Min Max + minmax = karamba.getGraphMinMax(widget, graphs[5]) + print "getGraphMinMax: " + str(minmax) + minmax = (0, (b * 25) + 25) + karamba.setGraphMinMax(widget, graphs[5], minmax[0], minmax[1]) + + # Value + v = karamba.getGraphValue(widget, graphs[6]) + print "getGraphValue: ", v + v = (v + 1) % 30 + karamba.setGraphValue(widget, graphs[6], v) + + # Color + c = karamba.getGraphColor(widget, graphs[7]) + print "getGraphColor: ", c + r = (c[0] + 10) % 255 + g = (c[1] + 10) % 255 + bl = (c[2] + 10) % 255 + karamba.setGraphColor(widget, graphs[7], r, g, bl) + +def widgetClicked(widget, x, y, button): + pass + +def widgetMouseMoved(widget, x, y, button): + pass + +# This will be printed when the widget loads. +print "Loaded Graph test python extension!" diff --git a/superkaramba/examples/graph/graph.theme b/superkaramba/examples/graph/graph.theme new file mode 100644 index 0000000..d16c8b3 --- /dev/null +++ b/superkaramba/examples/graph/graph.theme @@ -0,0 +1,26 @@ +KARAMBA x=100 y=10 w=600 h=580 INTERVAL=1000 LOCKED=true +DEFAULTFONT font="Bitstream Vera Sans" fontsize=16 color=200,200,200 + +TEXT x=0 Y=0 w=600 h=20 VALUE="createGraph & deleteGraph" name=text0 +GRAPH X=0 Y=20 W=400 H=30 POINTS=400 SENSOR=NETWORK FORMAT="%in" COLOR=192,192,192 MAX=50 NAME=graph0 + +TEXT x=0 Y=50 w=600 h=20 VALUE="getGraphSize & resizeGraph" name=text1 +GRAPH X=0 Y=70 W=400 H=30 POINTS=200 SENSOR=NETWORK FORMAT="%in" COLOR=192,192,192 MAX=50 NAME=graph1 + +TEXT x=0 Y=100 w=600 h=20 VALUE="getGraphPos & moveGraph" name=text2 +GRAPH X=0 Y=120 W=200 H=30 POINTS=200 SENSOR=NETWORK FORMAT="%in" COLOR=192,192,192 MAX=50 NAME=graph2 + +TEXT x=0 Y=150 w=600 h=20 VALUE="hideGraph & showGraph" name=text3 +GRAPH X=0 Y=170 W=200 H=30 POINTS=200 SENSOR=NETWORK FORMAT="%in" COLOR=192,192,192 MAX=50 NAME=graph3 + +TEXT x=0 Y=200 w=600 h=20 VALUE="getGraphSensor & setGraphSensor" name=text4 +GRAPH X=0 Y=220 W=200 H=30 POINTS=200 SENSOR=NETWORK FORMAT="%in" COLOR=192,192,192 MAX=50 NAME=graph4 + +TEXT x=0 Y=250 w=600 h=20 VALUE="getGraphMinMax & setGraphMinMax" name=text5 +GRAPH X=0 Y=270 W=200 H=30 POINTS=200 SENSOR=NETWORK FORMAT="%in" COLOR=192,192,192 MAX=50 NAME=graph5 + +TEXT x=0 Y=300 w=600 h=20 VALUE="getGraphValue & setGraphValue" name=text6 +GRAPH X=0 Y=320 W=200 H=30 POINTS=200 COLOR=192,192,192 NAME=graph6 MAX=30 + +TEXT x=0 Y=350 w=600 h=20 VALUE="getGraphColor & setGraphColor" name=text7 +GRAPH X=0 Y=370 W=200 H=30 POINTS=200 SENSOR=NETWORK FORMAT="%in" COLOR=192,192,192 MAX=50 NAME=graph7 diff --git a/superkaramba/examples/image/flag.png b/superkaramba/examples/image/flag.png new file mode 100644 index 0000000..0e3c9b5 Binary files /dev/null and b/superkaramba/examples/image/flag.png differ diff --git a/superkaramba/examples/image/flag2.png b/superkaramba/examples/image/flag2.png new file mode 100644 index 0000000..4946213 Binary files /dev/null and b/superkaramba/examples/image/flag2.png differ diff --git a/superkaramba/examples/image/image.py b/superkaramba/examples/image/image.py new file mode 100644 index 0000000..97656eb --- /dev/null +++ b/superkaramba/examples/image/image.py @@ -0,0 +1,121 @@ +#this import statement allows access to the karamba functions +import karamba + +images = [0,0,0,0,0,0,0,0,0,0,0,0,0,0] +c = 0 + +#this is called when you widget is initialized +def initWidget(widget): + global images + images[0] = karamba.getThemeImage(widget, "image0") + images[1] = karamba.getThemeImage(widget, "image1") + images[2] = karamba.getThemeImage(widget, "image2") + images[3] = karamba.getThemeImage(widget, "image3") + images[4] = karamba.getThemeImage(widget, "image4") + images[5] = karamba.getThemeImage(widget, "image5") + images[6] = karamba.getThemeImage(widget, "image6") + images[7] = karamba.getThemeImage(widget, "image7") + images[8] = karamba.getThemeImage(widget, "image8") + images[9] = karamba.getThemeImage(widget, "image9") + images[10] = karamba.getThemeImage(widget, "image10") + images[11] = karamba.getThemeImage(widget, "image11") + images[12] = karamba.getThemeImage(widget, "image12") + images[13] = karamba.getThemeImage(widget, "image13") + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + global images, c + + b = c%2 + + # Create & delete + if(images[0]): + karamba.deleteImage(widget, images[0]) + images[0] = 0 + else: + images[0] = karamba.createImage(widget, 0, 20, "flag.png") + + # Hide & Show + if(b): + karamba.hideImage(widget, images[1]) + else: + karamba.showImage(widget, images[1]) + + # size & resize + size = karamba.getImageSize(widget, images[1]) + print "getImageSize: " + str(size) + print "getImageWidth: " + str(karamba.getImageWidth(widget, images[1])) + print "getImageHeight: " + str(karamba.getImageHeight(widget, images[1])) + # Auto size + #size = ((b * 200) + 200, size[1]) + #karamba.resizeImage(widget, images[1], size[0], size[1]) + + # pos & move + pos = karamba.getImagePos(widget, images[2]) + print "getImagePos: " + str(pos) + pos = (b * 200, pos[1]) + karamba.moveImage(widget, images[2], pos[0], pos[1]) + + # Sensor + sensor = karamba.getImageSensor(widget, images[3]) + print "getSensor: " + str(sensor) + if(b): + karamba.setImageSensor(widget, images[3], 'SENSOR=PROGRAM PROGRAM="/tmp/test1.sh"') + else: + karamba.setImageSensor(widget, images[3], 'SENSOR=PROGRAM PROGRAM="/tmp/test2.sh"') + + # Value + v = karamba.getImagePath(widget, images[4]) + print "getImagePath: ", v + if(b): + v = 'flag.png' + else: + v = 'flag2.png' + karamba.setImagePath(widget, images[4], v) + + if((c % 10) == 0): + karamba.removeImageEffects(widget, images[5]) + karamba.removeImageEffects(widget, images[6]) + karamba.removeImageEffects(widget, images[7]) + else: + karamba.changeImageIntensity(widget, images[5], (float(c%10) / 5 - 1.0)) + karamba.changeImageChannelIntensity(widget, images[6], (float(c%10) / 5 - 1.0), 'blue') + karamba.changeImageToGray(widget, images[7], 0) + + if((c % 9) == 0): + karamba.removeImageTransformations(widget, images[8]) + karamba.removeImageTransformations(widget, images[9]) + karamba.removeImageTransformations(widget, images[10]) + else: + karamba.rotateImage(widget, images[8], (c%9)*20 + 45) + karamba.resizeImage(widget, images[9], 50 + (c%5)*10, size[1]) + karamba.resizeImageSmooth(widget, images[10], 50 + (c%5)*10, size[1]) + + if((c % 10) == 0): + karamba.addImageTooltip(widget, images[11], str(c)) + + if((c % 20) == 0): + if(images[12]): + karamba.deleteImage(widget, images[12]) + images[12] = 0 + else: + images[12] = karamba.createBackgroundImage(widget, 0, 340, "flag.png") + + if(images[13]): + karamba.deleteImage(widget, images[13]) + images[13] = 0 + else: + tlist = karamba.getTaskList(widget) + images[13] = karamba.createTaskIcon(widget, 50, 340, tlist[c % len(tlist)]) + + c += 1 + +def widgetClicked(widget, x, y, button): + pass + +def widgetMouseMoved(widget, x, y, button): + pass + +# This will be printed when the widget loads. +print "Loaded Image test python extension!" diff --git a/superkaramba/examples/image/image.theme b/superkaramba/examples/image/image.theme new file mode 100644 index 0000000..99a3974 --- /dev/null +++ b/superkaramba/examples/image/image.theme @@ -0,0 +1,34 @@ +KARAMBA x=100 y=10 w=600 h=580 INTERVAL=1000 LOCKED=true +DEFAULTFONT font="Bitstream Vera Sans" fontsize=16 color=200,200,200 + +TEXT x=0 Y=0 w=600 h=20 VALUE="createImage & deleteImage" name=ttext0 +IMAGE x=0 Y=20 path="flag.png" name=image0 + +TEXT x=0 Y=40 w=600 h=20 VALUE="showImage & hideImage" name=ttext1 +IMAGE x=0 Y=60 path="flag.png" name=image1 + +TEXT x=0 Y=80 w=600 h=20 VALUE="getImagePos & moveImage" name=ttext2 +IMAGE x=0 Y=100 path="flag.png" name=image2 + +TEXT x=0 Y=120 w=600 h=20 VALUE="getImageSensor & setImageSensor" name=ttext3 +IMAGE x=0 Y=140 path="flag.png" name=image3 + +TEXT x=0 Y=160 w=600 h=20 VALUE="getImagePath & setImagePath" name=ttext4 +IMAGE x=0 Y=180 path="flag.png" name=image4 + +TEXT x=0 Y=200 w=600 h=20 VALUE="removeImageEffects, changeImageIntensity, changeImageChannelIntensity, changeImageToGray" name=ttext5 fontsize=10 +IMAGE x=0 Y=220 path="flag.png" name=image5 +IMAGE x=50 Y=220 path="flag.png" name=image6 +IMAGE x=100 Y=220 path="flag.png" name=image7 + +TEXT x=0 Y=240 w=600 h=20 VALUE="removeImageTransformations, rotateImage, resizeImageSmooth, resizeImage" name=ttext6 fontsize=10 +IMAGE x=0 Y=260 path="flag.png" name=image8 +IMAGE x=80 Y=260 path="flag.png" name=image9 +IMAGE x=160 Y=260 path="flag.png" name=image10 + +TEXT x=0 Y=280 w=600 h=20 VALUE="addImageTooltip" name=ttext7 +IMAGE x=0 Y=300 path="flag.png" name=image11 + +TEXT x=0 Y=320 w=600 h=20 VALUE="createBackgroundImage & createTaskIcon" name=ttext7 +IMAGE x=0 Y=340 path="flag.png" name=image12 BACKGROUND=1 +IMAGE x=50 Y=340 path="flag.png" name=image13 diff --git a/superkaramba/examples/image/test1.sh b/superkaramba/examples/image/test1.sh new file mode 100755 index 0000000..28b1c79 --- /dev/null +++ b/superkaramba/examples/image/test1.sh @@ -0,0 +1,2 @@ +#!/bin/sh +echo flag.png diff --git a/superkaramba/examples/image/test2.sh b/superkaramba/examples/image/test2.sh new file mode 100755 index 0000000..c3b75c6 --- /dev/null +++ b/superkaramba/examples/image/test2.sh @@ -0,0 +1,2 @@ +#!/bin/sh +echo flag2.png diff --git a/superkaramba/examples/input_api/input_api.py b/superkaramba/examples/input_api/input_api.py new file mode 100644 index 0000000..59dc9ba --- /dev/null +++ b/superkaramba/examples/input_api/input_api.py @@ -0,0 +1,185 @@ +#this import statement allows access to the karamba functions +import karamba +import os + +input1 = 0 +input2 = 0 +output = 0 +i = 0 +fontSize = 0 + +#this is called when your widget is initialized +def initWidget(widget): + global input1, input2, output, fontSize + #input = karamba.getThemeInputBox(widget, "input01") + input1 = karamba.createInputBox(widget,0,0,50,20,"foo") + input2 = karamba.createInputBox(widget,0,30,50,20,"bar") + fontSize = karamba.getInputBoxFontSize(widget, input2) + output = karamba.getThemeText(widget, "output01") + karamba.changeTextColor(widget, output, 0, 0, 0) + karamba.changeTextSize(widget, output, 10) + karamba.redrawWidget(widget) + +#This is called when your widget is closed. You can use this to clean +#up open files, etc. You don't need to delete text and images in your +#theme. That is done automatically. This callback is just for cleaning up +#external things. Most people don't need to put anything here. +def widgetClosed(widget): + pass + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + global input1, input2, i, fontSize + #Change the font in the input box + if i == 0: + karamba.changeInputBoxFont(widget, input1, "times" ) + karamba.changeInputBoxFontColor(widget, input1, 0, 0, 0) + karamba.changeInputBoxBackgroundColor(widget, input1, 255,255,255) + + karamba.changeInputBoxFrameColor(widget, input2, 0, 0, 255) + karamba.changeInputBoxFontSize(widget, input2, fontSize) + else: + karamba.changeInputBoxFont(widget, input1, "luxi sans" ) + karamba.changeInputBoxFontColor(widget, input1, 255, 0, 0) + karamba.changeInputBoxBackgroundColor(widget, input1, 0, 0, 0) + + karamba.changeInputBoxFrameColor(widget, input2, 255, 255, 255) + karamba.changeInputBoxFontSize(widget, input2, 14) + + i += 1 + if i == 2: + i = 0 + karamba.redrawWidget(widget) + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + pass + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + #Warning: Don't do anything too intensive here + #You don't want to run some complex piece of code everytime the mouse moves + pass + + +#This gets called when an item is clicked in a popup menu you have created. +# menu = a reference to the menu +# id = the number of the item that was clicked. +def menuItemClicked(widget, menu, id): + pass + +#This gets called when an item is clicked in the theme CONFIGURATION menu, +#not the popup menus that you create. +# key = the reference to the configuration key that was changed +# value = the new value (true or false) that was selected +def menuOptionChanged(widget, key, value): + pass + +#This gets called when a meter (image, text, etc) is clicked. +# NOTE you must use attachClickArea() to make a meter +# clickable. +# widget = reference to your theme +# meter = the meter clicked +# button = the button clicked (see widgetClicked for button numbers) +def meterClicked(widget, meter, button): + pass + +#This gets called when a command you have executed with executeInteractive() outputs something +#to stdout. This way you can get the output of for example kdialog without freezing up the widget +#waiting for kdialog to end. +# widget = reference to your theme +# pid = process number of the program outputting (use this if you execute more than out process) +# output = the text the program outputted to stdout +def commandOutput(widget, pid, output): + pass + +#This gets called when an item is dropped on this widget. +# NOTE you have to call acceptDrops() before your widget will accept drops. +# widget = reference to your theme +# dropText = the text of the dropped item (probably a URL to it's location in KDE) +def itemDropped(widget, dropText): + pass + + +#This gets called when a new program is LOADING in KDE. When it is done +#loading, startupRemoved() is called, followed by taskAdded(). +# widget = reference to your widget +# task = A refence to the task that is starting. +def startupAdded(widget, startup): + pass + +#This gets called when a new program is done LOADING in KDE. +# widget = reference to your widget +# task = A refence to the task that just finished loading. +def startupRemoved(widget, startup): + pass + +#This is called every time a new task (program) is started in KDE. +# widget = reference to your widget +# task = A refence to the new task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def taskAdded(widget, task): + pass + +#This is called everytime a task (program) is closed in KDE. +# widget = reference to your widget +# task = A refence to the task. +def taskRemoved(widget, task): + pass + +#This is called everytime a different task gains focus (IE, the user clicks +#on a different window). +# widget = reference to your widget +# task = A refence to the task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def activeTaskChanged(widget, task): + pass + +#This is called everytime the systray you created with createSystray() is updated +def systrayUpdated(widget): + pass + +#This is called everytime the current desktop changes +# widget = reference to your widget +# desktop = the current desktop +def desktopChanged(widget, desktop): + pass + +#This is called everytime the wallpaper changes on a desktop +# widget = reference to your widget +# desktop = the desktop whose wallpaper changed +def wallpaperChanged(widget, desktop): + pass + +#This is called everytime there is a key press in any focused input field +# widget = reference to your widget +# meter = reference to an input box +# char = the key that was pressed +def keyPressed(widget, meter, char): + pass + +# This will be printed when the widget loads. +print "Loaded my python extension!" diff --git a/superkaramba/examples/input_api/input_api.theme b/superkaramba/examples/input_api/input_api.theme new file mode 100644 index 0000000..2cb5ee3 --- /dev/null +++ b/superkaramba/examples/input_api/input_api.theme @@ -0,0 +1,5 @@ +KARAMBA x=0 y=0 w=100 h=50 INTERVAL=1000 LOCKED=true +DEFAULTFONT font="Bitstream Vera Sans" fontsize=16 color=200,200,200 + +#INPUT x=0 y=0 w=100 h=25 name=input01 +TEXT x=0 y=30 w=100 h=25 name=output01 diff --git a/superkaramba/examples/input_example/input_example.py b/superkaramba/examples/input_example/input_example.py new file mode 100644 index 0000000..c0145c9 --- /dev/null +++ b/superkaramba/examples/input_example/input_example.py @@ -0,0 +1,169 @@ +#this import statement allows access to the karamba functions +import karamba +import os + +input = 0 +output = 0 +i = 0 + +#this is called when your widget is initialized +def initWidget(widget): + global input, output + #input = karamba.getThemeInputBox(widget, "input01") + input = karamba.createInputBox(widget,0,0,50,20,"foo") + output = karamba.getThemeText(widget, "output01") + karamba.changeTextColor(widget, output, 0, 0, 0) + karamba.changeTextSize(widget, output, 10) + karamba.redrawWidget(widget) + +#This is called when your widget is closed. You can use this to clean +#up open files, etc. You don't need to delete text and images in your +#theme. That is done automatically. This callback is just for cleaning up +#external things. Most people don't need to put anything here. +def widgetClosed(widget): + pass + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + pass + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + pass + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + #Warning: Don't do anything too intensive here + #You don't want to run some complex piece of code everytime the mouse moves + pass + + +#This gets called when an item is clicked in a popup menu you have created. +# menu = a reference to the menu +# id = the number of the item that was clicked. +def menuItemClicked(widget, menu, id): + pass + +#This gets called when an item is clicked in the theme CONFIGURATION menu, +#not the popup menus that you create. +# key = the reference to the configuration key that was changed +# value = the new value (true or false) that was selected +def menuOptionChanged(widget, key, value): + pass + +#This gets called when a meter (image, text, etc) is clicked. +# NOTE you must use attachClickArea() to make a meter +# clickable. +# widget = reference to your theme +# meter = the meter clicked +# button = the button clicked (see widgetClicked for button numbers) +def meterClicked(widget, meter, button): + pass + +#This gets called when a command you have executed with executeInteractive() outputs something +#to stdout. This way you can get the output of for example kdialog without freezing up the widget +#waiting for kdialog to end. +# widget = reference to your theme +# pid = process number of the program outputting (use this if you execute more than out process) +# output = the text the program outputted to stdout +def commandOutput(widget, pid, output): + pass + +#This gets called when an item is dropped on this widget. +# NOTE you have to call acceptDrops() before your widget will accept drops. +# widget = reference to your theme +# dropText = the text of the dropped item (probably a URL to it's location in KDE) +def itemDropped(widget, dropText): + pass + + +#This gets called when a new program is LOADING in KDE. When it is done +#loading, startupRemoved() is called, followed by taskAdded(). +# widget = reference to your widget +# task = A refence to the task that is starting. +def startupAdded(widget, startup): + pass + +#This gets called when a new program is done LOADING in KDE. +# widget = reference to your widget +# task = A refence to the task that just finished loading. +def startupRemoved(widget, startup): + pass + +#This is called every time a new task (program) is started in KDE. +# widget = reference to your widget +# task = A refence to the new task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def taskAdded(widget, task): + pass + +#This is called everytime a task (program) is closed in KDE. +# widget = reference to your widget +# task = A refence to the task. +def taskRemoved(widget, task): + pass + +#This is called everytime a different task gains focus (IE, the user clicks +#on a different window). +# widget = reference to your widget +# task = A refence to the task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def activeTaskChanged(widget, task): + pass + +#This is called everytime the systray you created with createSystray() is updated +def systrayUpdated(widget): + pass + +#This is called everytime the current desktop changes +# widget = reference to your widget +# desktop = the current desktop +def desktopChanged(widget, desktop): + pass + +#This is called everytime the wallpaper changes on a desktop +# widget = reference to your widget +# desktop = the desktop whose wallpaper changed +def wallpaperChanged(widget, desktop): + pass + +def keyPressed(widget, meter, char): + global input, output + if meter == input: + print "keyPressed: key= '", char, "'" + text = karamba.getInputBoxValue(widget, input) + karamba.changeText(widget, output, "Searched: " + text) + try: + if ord(char) == 13: # Enter + url = "konqueror leo:" + text + os.system(url + "&") + except TypeError: + print "There was a type error" + karamba.redrawWidget(widget) + + +# This will be printed when the widget loads. +print "Loaded my python extension!" diff --git a/superkaramba/examples/input_example/input_example.theme b/superkaramba/examples/input_example/input_example.theme new file mode 100644 index 0000000..2cb5ee3 --- /dev/null +++ b/superkaramba/examples/input_example/input_example.theme @@ -0,0 +1,5 @@ +KARAMBA x=0 y=0 w=100 h=50 INTERVAL=1000 LOCKED=true +DEFAULTFONT font="Bitstream Vera Sans" fontsize=16 color=200,200,200 + +#INPUT x=0 y=0 w=100 h=25 name=input01 +TEXT x=0 y=30 w=100 h=25 name=output01 diff --git a/superkaramba/examples/mouseDrag/karmix/images/bar.png b/superkaramba/examples/mouseDrag/karmix/images/bar.png new file mode 100644 index 0000000..ac893be Binary files /dev/null and b/superkaramba/examples/mouseDrag/karmix/images/bar.png differ diff --git a/superkaramba/examples/mouseDrag/karmix/images/bg.png b/superkaramba/examples/mouseDrag/karmix/images/bg.png new file mode 100644 index 0000000..a69b85b Binary files /dev/null and b/superkaramba/examples/mouseDrag/karmix/images/bg.png differ diff --git a/superkaramba/examples/mouseDrag/karmix/karmix.py b/superkaramba/examples/mouseDrag/karmix/karmix.py new file mode 100644 index 0000000..225eefb --- /dev/null +++ b/superkaramba/examples/mouseDrag/karmix/karmix.py @@ -0,0 +1,190 @@ +# Karmix 0.1 +# Written by Tian ( http://www.c-sait.net ) +# Functionality moved by Ryan Nickell (p0z3r@mail.com) + +# This theme is demonstrates how to use mouse buttons +# being dragged in a theme. +# It shows how to use it for slider bars, but you can +# also apply this to anything you want like moving images +# and other things programmatically. + +#this import statement allows access to the karamba functions +import karamba + +import ossaudiodev + +mixer = "" +onLeftButton = 0 +onMidButton = 0 +#this is called when you widget is initialized +def initWidget(widget): + global mixer + mixer = ossaudiodev.openmixer() + + vol_main = karamba.getThemeImage(widget, "vol_main") + (l, r) = mixer.get(ossaudiodev.SOUND_MIXER_VOLUME) + vol_main_value = max(l, r) + karamba.resizeImage(widget, vol_main, vol_main_value, 10) + + vol_pcm = karamba.getThemeImage(widget, "vol_pcm") + (l, r) = mixer.get(ossaudiodev.SOUND_MIXER_PCM) + vol_pcm_value = max(l, r) + karamba.resizeImage(widget, vol_pcm, vol_pcm_value, 10) + + vol_cd = karamba.getThemeImage(widget, "vol_cd") + (l, r) = mixer.get(ossaudiodev.SOUND_MIXER_CD) + vol_cd_value = max(l, r) + karamba.resizeImage(widget, vol_cd, vol_cd_value, 10) + + vol_mic = karamba.getThemeImage(widget, "vol_mic") + (l, r) = mixer.get(ossaudiodev.SOUND_MIXER_MIC) + vol_mic_value = max(l, r) + karamba.resizeImage(widget, vol_mic, vol_mic_value, 10) + + karamba.redrawWidget(widget) + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + pass + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + pass + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + global onMidButton,onLeftButton + global mixer + if(button == 1 and onLeftButton == 0): + # We are holding the left button here + if ((y>=17) and (y<=28)): + vol_main = karamba.getThemeImage(widget, "vol_main") + vol_main_value = max(min(x-40,100),0) + karamba.resizeImage(widget, vol_main, vol_main_value, 10) + mixer.set(ossaudiodev.SOUND_MIXER_VOLUME, (vol_main_value, vol_main_value)) + karamba.redrawWidget(widget) + + if ((y>=47) and (y<=58)): + vol_pcm = karamba.getThemeImage(widget, "vol_pcm") + vol_pcm_value = max(min(x-40,100),0) + karamba.resizeImage(widget, vol_pcm, vol_pcm_value, 10) + mixer.set(ossaudiodev.SOUND_MIXER_PCM, (vol_pcm_value, vol_pcm_value)) + karamba.redrawWidget(widget) + + if ((y>=77) and (y<=88)): + vol_cd = karamba.getThemeImage(widget, "vol_cd") + vol_cd_value = max(min(x-40,100),0) + karamba.resizeImage(widget, vol_cd, vol_cd_value, 10) + mixer.set(ossaudiodev.SOUND_MIXER_CD, (vol_cd_value, vol_cd_value)) + karamba.redrawWidget(widget) + + if ((y>=107) and (y<=118)): + vol_mic = karamba.getThemeImage(widget, "vol_mic") + vol_mic_value = max(min(x-40,100),0) + karamba.resizeImage(widget, vol_mic, vol_mic_value, 10) + mixer.set(ossaudiodev.SOUND_MIXER_MIC, (vol_mic_value, vol_mic_value)) + karamba.redrawWidget(widget) + + if(button == 2 and onMidButton == 0): + # We are holding the middle button here + pass + +#This gets called when an item is clicked in a popup menu you have created. +# menu = a reference to the menu +# id = the number of the item that was clicked. +def menuItemClicked(widget, menu, id): + pass + +#This gets called when an item is clicked in the theme CONFIGURATION menu, +#not the popup menus that you create. +# key = the reference to the configuration key that was changed +# value = the new value (true or false) that was selected +def menuOptionChanged(widget, key, value): + pass + +#This gets called when a meter (image, text, etc) is clicked. +# NOTE you must use attachClickArea() to make a meter +# clickable. +# widget = reference to your theme +# meter = the meter clicked +# button = the button clicked (see widgetClicked for button numbers) +def meterClicked(widget, meter, button): + pass + +#This gets called when a command you have executed with executeInteractive() outputs something +#to stdout. This way you can get the output of for example kdialog without freezing up the widget +#waiting for kdialog to end. +# widget = reference to your theme +# pid = process number of the program outputting (use this if you execute more than out process) +# output = the text the program outputted to stdout +def commandOutput(widget, pid, output): + pass + +#This gets called when an item is dropped on this widget. +# NOTE you have to call acceptDrops() before your widget will accept drops. +# widget = reference to your theme +# dropText = the text of the dropped item (probably a URL to it's location in KDE) +def itemDropped(widget, dropText): + pass + + +#This gets called when a new program is LOADING in KDE. When it is done +#loading, startupRemoved() is called, followed by taskAdded(). +# widget = reference to your widget +# task = A refence to the task that is starting. +def startupAdded(widget, startup): + pass + +#This gets called when a new program is done LOADING in KDE. +# widget = reference to your widget +# task = A refence to the task that just finished loading. +def startupRemoved(widget, startup): + pass + +#This is called every time a new task (program) is started in KDE. +# widget = reference to your widget +# task = A refence to the new task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def taskAdded(widget, task): + pass + +#This is called everytime a task (program) is closed in KDE. +# widget = reference to your widget +# task = A refence to the task. +def taskRemoved(widget, task): + pass + +#This is called everytime a different task gains focus (IE, the user clicks +#on a different window). +# widget = reference to your widget +# task = A refence to the task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def activeTaskChanged(widget, task): + pass + +# This will be printed when the widget loads. +print "Loaded my python extension!" + diff --git a/superkaramba/examples/mouseDrag/karmix/karmix.theme b/superkaramba/examples/mouseDrag/karmix/karmix.theme new file mode 100644 index 0000000..3844663 --- /dev/null +++ b/superkaramba/examples/mouseDrag/karmix/karmix.theme @@ -0,0 +1,17 @@ +# Karmix 0.1 +# Written by Tian ( http://www.c-sait.net ) + +karamba x=0 y=0 w=160 h=139 locked=true +image x=0 y=0 path="images/bg.png" + +text x=10 y=15 value="Vol" color=252,252,252 fontsize=12 font="sans" +image x=40 y=17 path="images/bar.png" name="vol_main" + +text x=10 y=45 value="Pcm" color=252,252,252 fontsize=12 font="sans" +image x=40 y=47 path="images/bar.png" name="vol_pcm" + +text x=10 y=75 value="CD" color=252,252,252 fontsize=12 font="sans" +image x=40 y=77 path="images/bar.png" name="vol_cd" + +text x=10 y=105 value="Mic" color=252,252,252 fontsize=12 font="sans" +image x=40 y=107 path="images/bar.png" name="vol_mic" diff --git a/superkaramba/examples/mouseDrop/mousedrop.py b/superkaramba/examples/mouseDrop/mousedrop.py new file mode 100644 index 0000000..521f0ee --- /dev/null +++ b/superkaramba/examples/mouseDrop/mousedrop.py @@ -0,0 +1,138 @@ +# Drop Detect +# Written by Luke Kenneth Casson Leighton + +# This theme is demonstrates how to + +#this import statement allows access to the karamba functions +import karamba + +drop_txt = None + +#this is called when you widget is initialized +def initWidget(widget): + + karamba.acceptDrops(widget) + karamba.redrawWidget(widget) + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + pass + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + pass + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + pass + +#This gets called when an item is clicked in a popup menu you have created. +# menu = a reference to the menu +# id = the number of the item that was clicked. +def menuItemClicked(widget, menu, id): + pass + +#This gets called when an item is clicked in the theme CONFIGURATION menu, +#not the popup menus that you create. +# key = the reference to the configuration key that was changed +# value = the new value (true or false) that was selected +def menuOptionChanged(widget, key, value): + pass + +#This gets called when a meter (image, text, etc) is clicked. +# NOTE you must use attachClickArea() to make a meter +# clickable. +# widget = reference to your theme +# meter = the meter clicked +# button = the button clicked (see widgetClicked for button numbers) +def meterClicked(widget, meter, button): + pass + +#This gets called when a command you have executed with executeInteractive() outputs something +#to stdout. This way you can get the output of for example kdialog without freezing up the widget +#waiting for kdialog to end. +# widget = reference to your theme +# pid = process number of the program outputting (use this if you execute more than out process) +# output = the text the program outputted to stdout +def commandOutput(widget, pid, output): + pass + +#This gets called when an item is dropped on this widget. +# NOTE you have to call acceptDrops() before your widget will accept drops. +# widget = reference to your theme +# dropText = the text of the dropped item (probably a URL to it's location in KDE) +# x and y are coordinates of mouse where the drop occurred. +# this you can use to e.g. detect which icon or object in your +# theme that someone wants to "receive" the icon you were dragging +def itemDropped(widget, dropText, x, y): + global drop_txt + # delete previous text if exists. + if drop_txt is not None: + karamba.deleteText(widget, drop_txt) + + disp = "x:%d y:%d command: %s" % (x, y, dropText) + drop_txt = karamba.createText(widget, 10, 40, 500, 20, disp) + karamba.changeTextColor(widget, drop_txt, 252,252,252) + + karamba.redrawWidget(widget) + +#This gets called when a new program is LOADING in KDE. When it is done +#loading, startupRemoved() is called, followed by taskAdded(). +# widget = reference to your widget +# task = A refence to the task that is starting. +def startupAdded(widget, startup): + pass + +#This gets called when a new program is done LOADING in KDE. +# widget = reference to your widget +# task = A refence to the task that just finished loading. +def startupRemoved(widget, startup): + pass + +#This is called every time a new task (program) is started in KDE. +# widget = reference to your widget +# task = A refence to the new task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def taskAdded(widget, task): + pass + +#This is called everytime a task (program) is closed in KDE. +# widget = reference to your widget +# task = A refence to the task. +def taskRemoved(widget, task): + pass + +#This is called everytime a different task gains focus (IE, the user clicks +#on a different window). +# widget = reference to your widget +# task = A refence to the task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def activeTaskChanged(widget, task): + pass + +# This will be printed when the widget loads. +print "Loaded my python extension!" + diff --git a/superkaramba/examples/mouseDrop/mousedrop.theme b/superkaramba/examples/mouseDrop/mousedrop.theme new file mode 100644 index 0000000..6b483d3 --- /dev/null +++ b/superkaramba/examples/mouseDrop/mousedrop.theme @@ -0,0 +1,5 @@ +# simple test of drop receipt, including location. + +karamba x=0 y=0 w=600 h=140 locked=true color=0,50,0 +text x=10 y=10 value="Drag a desktop icon on me and i will tell you where" color=252,252,252 fontsize=12 font="sans" + diff --git a/superkaramba/examples/openCloseTheme/1.py b/superkaramba/examples/openCloseTheme/1.py new file mode 100644 index 0000000..26281aa --- /dev/null +++ b/superkaramba/examples/openCloseTheme/1.py @@ -0,0 +1,22 @@ +import dcop +import dcopext +import karamba +from qt import QString, QCString + +def closeTheme(theme): + dc = dcop.DCOPClient() + dc.attach() + dc.registerAs('sk_script') + apps = dc.registeredApplications() + for app in apps: + s = str(app) + if s[:12] == 'superkaramba': + d = dcopext.DCOPApp(s, dc) + d.KarambaIface.closeTheme(theme) + +def initWidget(widget): + karamba.openTheme('2.theme') + +def widgetClicked(widget, x, y, button): + closeTheme('1') + diff --git a/superkaramba/examples/openCloseTheme/1.theme b/superkaramba/examples/openCloseTheme/1.theme new file mode 100644 index 0000000..5184f0a --- /dev/null +++ b/superkaramba/examples/openCloseTheme/1.theme @@ -0,0 +1,2 @@ +KARAMBA x=200 y=50 w=100 h=20 INTERVAL=1000 LOCKED=true +TEXT x=0 Y=0 w=300 h=20 value="Theme 1" diff --git a/superkaramba/examples/openCloseTheme/2.theme b/superkaramba/examples/openCloseTheme/2.theme new file mode 100644 index 0000000..7298850 --- /dev/null +++ b/superkaramba/examples/openCloseTheme/2.theme @@ -0,0 +1,2 @@ +KARAMBA x=200 y=100 w=100 h=20 INTERVAL=1000 LOCKED=true +TEXT x=0 Y=0 w=300 h=20 value="Theme2" diff --git a/superkaramba/examples/popupMenu/calendar.png b/superkaramba/examples/popupMenu/calendar.png new file mode 100644 index 0000000..fc0e466 Binary files /dev/null and b/superkaramba/examples/popupMenu/calendar.png differ diff --git a/superkaramba/examples/popupMenu/popupMenu.png b/superkaramba/examples/popupMenu/popupMenu.png new file mode 100644 index 0000000..330fc25 Binary files /dev/null and b/superkaramba/examples/popupMenu/popupMenu.png differ diff --git a/superkaramba/examples/popupMenu/popupMenu.py b/superkaramba/examples/popupMenu/popupMenu.py new file mode 100644 index 0000000..8df5aef --- /dev/null +++ b/superkaramba/examples/popupMenu/popupMenu.py @@ -0,0 +1,117 @@ +#this import statement allows access to the karamba functions +import karamba + +menu1 = 0 +menu2 = 0 +id1 = 0 +id2 = 0 +id3 = 0 +id4 = 0 +id5 = 0 + +#this is called when you widget is initialized +def initWidget(widget): + global menu1 + global menu2 + global id1 + global id2 + global id3 + global id4 + global id5 + + menu1 = karamba.createMenu(widget) + print "menu 1 created!" + menu2 = karamba.createMenu(widget) + print "menu 2 created!" + + id1 = karamba.addMenuItem(widget, menu1, "menu 1 first item", "kword") + print "item 1 entered in menu 1" + id2 = karamba.addMenuItem(widget, menu1, "menu 1 second item", "kate") + print "item 2 entered in menu 1" + + id3 = karamba.addMenuItem(widget, menu2, "menu 2 first item", "kword") + print "item 1 entered in menu 2" + id4 = karamba.addMenuItem(widget, menu2, "menu 2 second item", "kate") + print "item 2 entered in menu 2" + id5 = karamba.addMenuItem(widget, menu2, "menu 2 third item", "/opt/kde/share/icons/kdeclassic/16x16/apps/kicker.png") + print "item 3 entered in menu 2" + + + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + pass + + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + global menu1 + global menu2 + + if(button == 1): + karamba.popupMenu(widget, menu1, -100, -100) + elif(button == 2): + karamba.popupMenu(widget, menu2, 200, 200) + + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + #Warning: Don't do anything too intensive here + #You don't want to run some complex piece of code everytime the mouse moves + pass + + +def menuItemClicked(widget, menu, id): + global menu1 + global menu2 + global id1 + global id2 + global id3 + global id4 + global id5 + + if (menu == menu1): + if(id == id1): + print "item 1 in menu 1 clicked." + elif(id == id2): + print "item 2 in menu 1 clicked, removing item 2 in menu 2" + karamba.removeMenuItem(widget, menu2, id4) + elif (menu == menu2): + if(id == id3): + print "item 1 in menu 2 clicked." + elif(id == id4): + print "item 2 in menu 2 clicked, deleting menu 1 (if menu1 still exists...)" + karamba.deleteMenu(widget, menu1) + elif(id == id5): + print "item 3 in menu 2 clicked, removing item 2 in menu 1 (if menu1 still exists...)" + karamba.removeMenuItem(widget, menu1, id2) + + + +# This will be printed when the widget loads. +print "Loaded my python extension!" + + diff --git a/superkaramba/examples/popupMenu/popupMenu.theme b/superkaramba/examples/popupMenu/popupMenu.theme new file mode 100644 index 0000000..5c597f4 --- /dev/null +++ b/superkaramba/examples/popupMenu/popupMenu.theme @@ -0,0 +1,4 @@ + +KARAMBA X=200 Y=200 W=390 H=220 LOCKED=true INTERVAL=1000 ONTOP=false + +IMAGE X=0 Y=0 PATH="popupMenu.png" diff --git a/superkaramba/examples/richtext/info.png b/superkaramba/examples/richtext/info.png new file mode 100644 index 0000000..43b0297 Binary files /dev/null and b/superkaramba/examples/richtext/info.png differ diff --git a/superkaramba/examples/richtext/penguin_executive.png b/superkaramba/examples/richtext/penguin_executive.png new file mode 100644 index 0000000..6f855d3 Binary files /dev/null and b/superkaramba/examples/richtext/penguin_executive.png differ diff --git a/superkaramba/examples/richtext/richtext.py b/superkaramba/examples/richtext/richtext.py new file mode 100644 index 0000000..518aa65 --- /dev/null +++ b/superkaramba/examples/richtext/richtext.py @@ -0,0 +1,136 @@ +#Unicode Example + +#For Symbol Tables look at www.unicode.org/charts/ + +hidden = 0 + +penguin = 0 +penguin_hidden = 1 + +#this import statement allows access to the karamba functions +import karamba + +#this is called when you widget is initialized +def initWidget(widget): + global richtext + global penguin + + karamba.resizeWidget(widget, 360, 520) + + penguin = karamba.createImage(widget, 250, 150, karamba.getThemePath(widget) + "/penguin_executive.png") + karamba.hideImage(widget, penguin) + + + text = """ +

    Richtext Example

    +

    A rich text object allows to display a string interpreted as rich text. +To create a rich text object use the command:

    karamba.createRichText(widget, text)

    +A simple subset of HTML-tags +is used to encode the formatting commands.

    +

    Some features: +

      +
    • Numbered and unnumbered lists
    • +
    • Inline Images +
    • Various different text colours
    • +
    • Hyperlinks: Superkaramba Homepage
    • +
    • Links can also trigger actions in the script
    • +
    • Various different caracter styles
    • +
    • Unicode: \u03B6 \u03B3 \u03BB \u03A3 \u03A9
    • +
    • Simple Tables: + + + + +
      Header
      Cell (1,1)Cell (1,2)Cell (1,3)
      Cell (2,1)Cell (2,2)Cell (2,3)
    • +
    +For a complete documentation of all supported tags look at: + +http://doc.trolltech.com/3.0/qstylesheet.html. +


    +""" + + richtext = karamba.createRichText(widget, text) + + karamba.moveRichText(widget, richtext, 10, 10) + + print "richText Size = ", karamba.getRichTextSize(widget, richtext) + + karamba.setRichTextWidth(widget, richtext, 345) + + #karamba.deleteRichText(widget, richtext) + + karamba.redrawWidget(widget) + + + + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + global hidden + global richtext + + #if hidden == 0: + # hidden = 1 + # karamba.hideRichText(widget, richtext) + #else: + # hidden = 0 + # karamba.showRichText(widget, richtext) + + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + global richtext + global hidden + + #hidden = 0 + #karamba.showRichText(widget, richtext) + + #karamba.changeRichText(widget, richtext, "hihi\n huhu") + +def meterClicked(widget, meter, button): + global penguin + global penguin_hidden + global richtext + + print "Meter clicked", meter + if meter == "trigger": + if penguin_hidden: + karamba.showImage(widget, penguin) + penguin_hidden = 0 + else: + karamba.hideImage(widget, penguin) + penguin_hidden = 1 + if meter == "delete": + karamba.deleteRichText(widget, richtext) + + karamba.redrawWidget(widget) + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + pass + +# This will be printed when the widget loads. +print "Loaded Karamba Unicode Test" diff --git a/superkaramba/examples/richtext/richtext.theme b/superkaramba/examples/richtext/richtext.theme new file mode 100644 index 0000000..1fae0ec --- /dev/null +++ b/superkaramba/examples/richtext/richtext.theme @@ -0,0 +1 @@ +KARAMBA X=80 Y=20 W=400 H=500 LOCKED=true INTERVAL=2000 diff --git a/superkaramba/examples/richtext/rtext.py b/superkaramba/examples/richtext/rtext.py new file mode 100644 index 0000000..68c800a --- /dev/null +++ b/superkaramba/examples/richtext/rtext.py @@ -0,0 +1,99 @@ +#!/usr/bin/python +# -*- coding: latin-1 -*- +#this import statement allows access to the karamba functions +import karamba + +align = ['LEFT', 'CENTER', 'RIGHT'] +texts = [0,0,0,0,0,0,0,0,0,0,0] +b = 0 +a = 0 + +#this is called when you widget is initialized +def initWidget(widget): + global texts, b + texts[0] = karamba.getThemeRichText(widget, "text0") + texts[1] = karamba.getThemeRichText(widget, "text1") + texts[2] = karamba.getThemeRichText(widget, "text2") + texts[3] = karamba.getThemeRichText(widget, "text3") + texts[4] = karamba.getThemeRichText(widget, "text4") + texts[5] = karamba.getThemeRichText(widget, "text5") + texts[7] = karamba.getThemeRichText(widget, "text7") + texts[9] = karamba.getThemeRichText(widget, "text9") + + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + global texts, b, a + + b = (b+1)%2 + text = "Unicode text: htriss on ljy" + + # Create & delete + if(texts[0]): + karamba.deleteRichText(widget, texts[0]) + texts[0] = 0 + else: + texts[0] = karamba.createRichText(widget, text) + karamba.moveRichText(widget, texts[0], 0, 20) + karamba.resizeRichText(widget, texts[0], 200, 20) + pos = karamba.getRichTextPos(widget, texts[0]) + print "--getRichTextPos: " + str(pos) + size = karamba.getRichTextSize(widget, texts[0]) + print "--getRichTextSize: " + str(size) + + # size & resize + size = karamba.getRichTextSize(widget, texts[1]) + print "getRichTextSize: " + str(size) + size = ((b * 200) + 200, size[1]) + karamba.resizeRichText(widget, texts[1], size[0], size[1]) + + # pos & move + pos = karamba.getRichTextPos(widget, texts[2]) + print "getRichTextPos: " + str(pos) + pos = (b * 200, pos[1]) + karamba.moveRichText(widget, texts[2], pos[0], pos[1]) + + # Hide & Show + if(b): + karamba.hideRichText(widget, texts[3]) + else: + karamba.showRichText(widget, texts[3]) + + # Sensor + sensor = karamba.getRichTextSensor(widget, texts[4]) + print "getSensor: " + str(sensor) + if(b): + karamba.setRichTextSensor(widget, texts[4], 'SENSOR=SENSOR TYPE="cpu_temp"') + else: + karamba.setRichTextSensor(widget, texts[4], 'SENSOR=CPU') + + # Value + v = karamba.getRichTextValue(widget, texts[5]) + print "getRichTextValue: ", v + v += '.' + karamba.changeRichText(widget, texts[5], v) + + # Font size + v = karamba.getRichTextFontSize(widget, texts[7]) + print "getRichTextFontSize: ", v + v = 10 + ((v-10)+1)%10; + karamba.changeRichTextSize(widget, texts[7], v) + + # RichText Font + v = karamba.getRichTextFont(widget, texts[9]) + print "getRichTextFont: ", v + if(b): + v = 'Bitstream Vera Sans' + else: + v = 'Bitstream Vera Serif' + karamba.changeRichTextFont(widget, texts[9], v) + +def widgetClicked(widget, x, y, button): + pass + +def widgetMouseMoved(widget, x, y, button): + pass + +# This will be printed when the widget loads. +print "Loaded RichText test python extension!" diff --git a/superkaramba/examples/richtext/rtext.theme b/superkaramba/examples/richtext/rtext.theme new file mode 100644 index 0000000..487065d --- /dev/null +++ b/superkaramba/examples/richtext/rtext.theme @@ -0,0 +1,26 @@ +KARAMBA x=100 y=10 w=600 h=580 INTERVAL=1000 LOCKED=true +DEFAULTFONT font="Bitstream Vera Sans" fontsize=16 color=200,200,200 + +TEXT x=0 Y=0 w=600 h=20 VALUE="createRichText & deleteRichText" name=ttext0 +RICHTEXT x=0 Y=20 w=200 h=20 value="RichText meter" min=0 max=100 name=text0 + +TEXT x=0 Y=45 w=600 h=20 VALUE="getRichTextSize & resizeRichText" name=ttext1 +RICHTEXT x=0 Y=65 w=200 h=20 value="The quick brown fox jumps over the lazy dog" min=0 max=100 name=text1 + +TEXT x=0 Y=90 w=600 h=20 VALUE="getRichTextPos & moveRichText" name=ttext2 +RICHTEXT x=0 Y=110 w=200 h=20 value="RichText meter" min=0 max=100 name=text2 + +TEXT x=0 Y=135 w=600 h=20 VALUE="hideRichText & showRichText" name=ttext3 +RICHTEXT x=0 Y=155 w=200 h=20 value="RichText meter" min=0 max=100 name=text3 + +TEXT x=0 Y=180 w=600 h=20 VALUE="getRichTextSensor & setRichTextSensor" name=ttext4 +RICHTEXT x=0 Y=200 w=200 h=20 value=50 min=0 max=100 name=text4 + +TEXT x=0 Y=225 w=600 h=20 VALUE="getRichTextValue & setRichTextValue" name=ttext5 +RICHTEXT x=0 Y=245 w=200 h=20 value="." min=0 max=100 name=text5 + +TEXT x=0 Y=315 w=600 h=20 VALUE="setRichTextSize & getRichTextSize" name=ttext7 +RICHTEXT x=0 Y=335 w=200 h=20 value="RichText meter" min=0 max=100 name=text7 + +TEXT x=0 Y=405 w=600 h=20 VALUE="setRichTextFont & getRichTextFont" name=ttext9 +RICHTEXT x=0 Y=425 w=400 h=20 value="The quick brown fox jumps over the lazy dog" min=0 max=100 name=text9 diff --git a/superkaramba/examples/service_group/service_group.py b/superkaramba/examples/service_group/service_group.py new file mode 100644 index 0000000..276b9c8 --- /dev/null +++ b/superkaramba/examples/service_group/service_group.py @@ -0,0 +1,143 @@ +# Service Groups demo +# Written by Luke Kenneth Casson Leighton + +# This theme is demonstrates how to parse service groups. +# it's done recursively to give a complete dump of your menu +# that you will also be able to double-check against kmenuedit +# and also the KDE Start button. +# +# for a real-live usage, see kroller.sez (try searching kde-look.org), +# which fires off a sub-theme with the service-group menu options when +# you click on a service group on the "main" bar. + +#this import statement allows access to the karamba functions +import karamba + +# simple function to display + +def create_text(widget, line, depth, disp, name=None, command=None, icon=None): + + x = depth*30 + y = line*7 + width = 400 + height = 8 + drop_txt = karamba.createText(widget, x, y, width, height, disp) + karamba.changeTextSize(widget, drop_txt, 7) + karamba.changeTextColor(widget, drop_txt, 252,252,252) + + # create a (very narrow! only an 8-pixel-high area!) + # service click area to demonstrate that commands get + # executed correctly. + + if name: + karamba.createServiceClickArea( widget, + x,y,width,height, + name, command, icon) + + +# okay. you really should be looking up the KDE Developer documentation +# on service groups. here is a _brief_ explanation of what they contain. +# +# getServiceGroups returns a list of menu options. +# you can either have a subgroup, or you can have an executable program. +# if a list item is a subgroup, then (0, dict) is returned, where +# dict is a dictionary containing information describing the subgroup. +# if a list item is an executable menu option, then (1, dict) is returned, +# where dict is a dictionary containing information describing the menu option. +# +# the information (keys in the dictionary) returned about a subgroup comprises: +# relpath - the fully qualified path of that subgroup, and +# calling getServiceGroups (again) with that path will get +# you all of the menu options in that subgroup, hurrah. +# icon - the name of an icon (a png, usually) which you can, if you +# so wish, use as the filename argument to createImage(). +# caption - i get confused as to which is which, but +# and you can always run this program in combination +# comment with kmenuedit to find out! +# +# the information (keys in the dictionary) returned about an +# executable option comprises: +# exec - obviously the most important bit: the name of the command +# to be executed. +# icon - the filename of the icon (usually a png) which should be +# displayed for this command. +# name - not to be confused with genericname, neither of which i +# am sure about, and if you really want to know, run +# kmenuedit and experiment, or look at the KDE Developer source +# code. +# menuid - don't know what it is for. it's just... there. +# +# how to use the service group info: +# +# the simplest way to get commands actually executed is to hand +# over the name, the command and the icon filename to a +# ServiceClickArea (karamba.createServiceClickArea()). +# +# other than making sure that you put the service click area in +# the right place, you don't have to worry about much else. +# +# or, you could always run it manually, yourself, by using +# karamba.Run(name, command, icon). personally, i prefer +# the service click areas. no, karamba.Run() is not like +# karamba.execute() - if you use karamba.Run() you get to say which +# bouncing icon is used, whereas if you use karamba.execute() you +# always get a superkaramba bouncing icon... +# +# do look out for kroller.sez on http://kde-look.org or other locations +# for a more complex and comprehensive usage of service groups. + +def display_svc_group(widget, rel_path, line, depth): + + grps = karamba.getServiceGroups(rel_path) + + for (type, d) in grps: + + if type is 0: + + # it's a + + sub_relpath = d['relpath'] + icon = d.get('icon', 'unknown') + caption = d.get('caption', None) + comment = d.get('comment', None) + cmt = '' + + # get at least something to display + if comment: + cmt = comment + elif caption: + cmt = caption + + msg = "SVCGRP: %s %s" % (icon, cmt) + create_text(widget, line, depth, msg) + line += 1 + line = display_svc_group(widget, sub_relpath, + line, depth+1) + + elif type is 1 and d.has_key('menuid'): + + relpath = d.get('relpath', '') + cmd = d['exec'] + icon = d.get('icon', 'unknown') + name = d.get('name', None) + genericname = d.get('genericname', None) + cmt = '' + + # get at least something to display + if genericname: + cmt = genericname + elif name: + cmt = name + + msg = "%s %s %s" % (cmd, icon, cmt) + create_text(widget, line, depth, msg, name, cmd, icon) + line += 1 + + return line + +#this is called when you widget is initialized +def initWidget(widget): + + display_svc_group(widget, "", 0, 0) + karamba.redrawWidget(widget) + diff --git a/superkaramba/examples/service_group/service_group.theme b/superkaramba/examples/service_group/service_group.theme new file mode 100644 index 0000000..e52a689 --- /dev/null +++ b/superkaramba/examples/service_group/service_group.theme @@ -0,0 +1,4 @@ +# simple test of service group stuff. displays your kde menu. + +karamba x=0 y=0 w=600 h=800 locked=true + diff --git a/superkaramba/examples/setIncomingData/1.py b/superkaramba/examples/setIncomingData/1.py new file mode 100644 index 0000000..8422de2 --- /dev/null +++ b/superkaramba/examples/setIncomingData/1.py @@ -0,0 +1,27 @@ +import karamba + +sequence_num = 0 + +def initWidget(widget): + karamba.openTheme('2.theme') + +# pass over a sequence number as well - the reason is to +# make it possible to identify the clicks uniquely. +# +# unfortunately, the recipient has to do "polling" +# by calling getIncomingData - see 2.py for more info + +def widgetClicked(widget, x, y, button): + + # do as you wish, but this is a good way: + # compact your stuff with repr() it can cope + # with pretty much any basic types - dictionaries, lists - + # and then use eval() at the other end. + + global sequence_num + sequence_num += 1 + + vars = (sequence_num, x, y, button) + message = repr(vars) + karamba.setIncomingData(widget, "2", message) + diff --git a/superkaramba/examples/setIncomingData/1.theme b/superkaramba/examples/setIncomingData/1.theme new file mode 100644 index 0000000..2e4bfcf --- /dev/null +++ b/superkaramba/examples/setIncomingData/1.theme @@ -0,0 +1,2 @@ +KARAMBA x=200 y=50 w=100 h=20 INTERVAL=1000 LOCKED=true +TEXT x=0 Y=0 w=300 h=20 value="Click me!" diff --git a/superkaramba/examples/setIncomingData/2.py b/superkaramba/examples/setIncomingData/2.py new file mode 100644 index 0000000..a411b60 --- /dev/null +++ b/superkaramba/examples/setIncomingData/2.py @@ -0,0 +1,78 @@ +# +# Written by Luke Kenneth Casson Leighton + +# This theme is demonstrates how to + +#this import statement allows access to the karamba functions +import karamba + +drop_txt = None + +#this is called when you widget is initialized +def initWidget(widget): + + # this resets the text to "" so we know we've never + # received anything yet from the other theme + name = karamba.getPrettyThemeName(widget) + print "2.py name: ", name + karamba.setIncomingData(widget, name, "") + + karamba.redrawWidget(widget) + +# this is a pain. in order to avoid memory-related threading problems, +# and also locking, with the communication between themes, the +# communication is done asynchronously. so you have to POLL for the +# information, by reading getIncomingData(). +# +# therefore, you must set an interval=time_in_ms in your receiving .theme +# file (see 2.theme) and then call getIncomingData() in here. +# +# it's not ideal - but it works. +# +# NOTE: the data received - by getIncomingData - is NOT, i repeat NOT +# deleted when you call getIncomingData. +# so, obviously, you need to take care to not activate repeatedly. +# you could do this in several ways. one of them is to send, in +# the calling theme (the one that calls setIncomingData) a sequential +# number as part of the message. +# +# alternatively, you could reset the text to "" (see above) + + +expected_seq = 0 + +def widgetUpdated(widget): + + global expected_seq # i hate globals. please write better code than this example. + + # get the "message"... + disp = karamba.getIncomingData(widget) + if disp == "": + return + + # decode it... + (seq, x, y, button) = eval(disp) + + # if it's been seen before, skip it... + if seq <= expected_seq: + pass + + expected_seq += 1 + + message = "seq:%d x:%d y:%d btn:%d" % (seq, x, y, button) + # delete previous text if exists. + global drop_txt + if drop_txt is not None: + karamba.deleteText(widget, drop_txt) + + # display it... + drop_txt = karamba.createText(widget, 0, 20, 300, 20, message) + karamba.changeTextColor(widget, drop_txt, 252,252,252) + + karamba.redrawWidget(widget) + + pass + +# This will be printed when the widget loads. +print "Loaded my python 2.py extension!" + diff --git a/superkaramba/examples/setIncomingData/2.theme b/superkaramba/examples/setIncomingData/2.theme new file mode 100644 index 0000000..df7d7b2 --- /dev/null +++ b/superkaramba/examples/setIncomingData/2.theme @@ -0,0 +1,2 @@ +KARAMBA x=200 y=100 w=300 h=40 INTERVAL=200 LOCKED=true +TEXT x=0 y=0 w=300 h=20 value="you clicked on theme 1:" diff --git a/superkaramba/examples/taskBar/cleanbar/README b/superkaramba/examples/taskBar/cleanbar/README new file mode 100644 index 0000000..0f828b6 --- /dev/null +++ b/superkaramba/examples/taskBar/cleanbar/README @@ -0,0 +1,25 @@ +Cleanbar for SuperKaramba, version 0.4 +Written by Adam Geitgey +Released under the GNU General Public License version 2 + + +Cleanbar requires SuperKaramba 0.31 or higher!! + + +Cleanbar is a simple taskbar, xmms control, and clock. Cleanbar is quick, +simple, and appealing. + +The Launch button brings up the K Menu. The play control buttons will control +XMMS (xmmsctrl is required). A clock is shown on the right. Tasks show up +along the middle and the taskbar works just like any other taskbar from the +last 10 years. + +I created this basically as a quick example of how to use the new +event-based task control API in SuperKaramba 0.31. + +It also demonstrates how to create themes that work at any resolution. You +should not have to change anything for this to work on your desktop. + +Please report any major problems you have. + +Thanks. diff --git a/superkaramba/examples/taskBar/cleanbar/cleanbar.py b/superkaramba/examples/taskBar/cleanbar/cleanbar.py new file mode 100644 index 0000000..c0da2a2 --- /dev/null +++ b/superkaramba/examples/taskBar/cleanbar/cleanbar.py @@ -0,0 +1,267 @@ +#this import statement allows access to the karamba functions +import karamba +import os +import time + +###################################### +## Globals +###################################### + +init = 0 +numOfTasks = 0 + +## Default res +## You don't need to change it. It should auto-detect. +resX = 1024 +resY = 768 + +# list of tasks +taskList = [] + +# focused task +activeTask = 0 + +## Task display stuff +taskPanels = [] +taskText = [] +taskMenu = 0 +taskMenuLookup = {} +timeText = 0 + +## My code to detect resolution +havexwi = os.system("which xwininfo") + +if (havexwi == 0): + pass +else: + print "\nCan't find xwininfo in your path." + +fp = os.popen("xwininfo -root -stats") +output = fp.read() +output = output.splitlines() +i = 0 +for x in output: + param = x.split() + if (len(param) > 1): + if param[0].find("Width:") != -1: + resX = int(param[1]) + if param[0].find("Height:") != -1: + resY = int(param[1]) + + + + +def drawTaskbar(widget): + global taskPanels + global taskText + global numOfTasks + + taskList = karamba.getTaskList(widget) + + for image in taskPanels: + karamba.hideImage(widget, image) + + for text in taskText: + karamba.changeText(widget, text, "") + karamba.changeTextShadow(widget, text, 0) + karamba.changeTextColor(widget,text,0,0,0) + + length = len(taskList) + if (numOfTasks < length): + length = numOfTasks + + + knownGroups = {} + groups = [] + groupRefs = {} + + activeGroup = 0 + groupCount = 0 + + #build groups list that contains sub-lists of taskInfo sorted by group + for j in range(len(taskList)): + taskinfo = karamba.getTaskInfo(widget, taskList[j]) + + if knownGroups.has_key(taskinfo[2]) == 0: + groupCount = groupCount + 1 + if (taskinfo[7] == 1): + activeGroup = groupCount + knownGroups[taskinfo[2]] = 1 + thisGroup = [] + thisGroup.append(taskinfo) + groupRefs[taskinfo[2]] = len(groups) + groups.append(thisGroup) + else: + if (taskinfo[7] == 1): + activeGroup = groupRefs[taskinfo[2]] + 1 + knownGroups[taskinfo[2]] = knownGroups[taskinfo[2]] + 1 + thisGroup = groups[groupRefs[taskinfo[2]]] + thisGroup.append(taskinfo) + + #fill out the task bar + j = 0 + for group in groups: + #safety check (could be more task groups than bar is long) + if (j < length): + karamba.showImage(widget, taskPanels[j]) + if len(group) != 1: + karamba.changeText(widget, taskText[j], group[0][2] + " [" + str(len(group)) + "]") + else: + karamba.changeText(widget, taskText[j], (group[0][0])) + j = j + 1 + + if (activeGroup != 0): + karamba.changeTextShadow(widget, taskText[activeGroup - 1], 1) + karamba.changeTextColor(widget, taskText[activeGroup - 1], 239, 220, 11) + + + karamba.redrawWidget(widget) + +#this is called when your widget is initialized +def initWidget(widget): + global resX + global numOfTasks + global taskPanels + global taskText + global timeText + + karamba.createImage(widget, resX - 149, 0, "pics/rightend_new.png") + numOfTasks = (resX - 198 - 149)/121 + + timeText = karamba.createText(widget, resX - 149 + 54, 10, 140, 20, "time") + karamba.changeTextColor(widget, timeText, 0,0,0) + karamba.changeTextSize(widget, timeText, 9) + + for i in range(numOfTasks): + taskPanels.append(karamba.createImage(widget, 198 + (121*i), 3, "pics/task_new.png")) + taskText.append(karamba.createText(widget, 198 + (121*i) +9, 9, 100, 20, "")) + + for text in taskText: + karamba.changeTextSize(widget,text,9) + + drawTaskbar(widget) + +# called to indicate that a new task is currently started +def startupAdded(widget, startup): + pass + +# called whenever a startup is removed. Which either means the task is +# successfully started (and taskAdded will be called), or the task could +# not be started for some reason. +def startupRemoved(widget, startup): + pass + +# called whenever a new task has been started +def taskAdded(widget, task): + drawTaskbar(widget) + +# called whenever a task is removed +def taskRemoved(widget, task): + drawTaskbar(widget) + +# called whenever a new task has gained focus. +# task = the active task +def activeTaskChanged(widget, task): + drawTaskbar(widget) + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + global timeText + + karamba.changeText(widget, timeText, time.strftime("%I:%M %p %a",time.localtime(time.time()))) + karamba.redrawWidget(widget) + + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + global numOfTasks + global taskMenu + global taskMenuLookup + + taskSelected = (x-198)/121 + + ## Make sure its a valid task + if (0 <= taskSelected < numOfTasks): + taskList = karamba.getTaskList(widget) + + #free last menu + karamba.deleteMenu(widget, taskMenu) + + #create new menu + taskMenu = karamba.createMenu(widget) + taskMenuLoopup = {} + + length = len(taskList) + if (numOfTasks < length): + length = numOfTasks + + + knownGroups = {} + groups = [] + groupRefs = {} + for j in range(len(taskList)): + taskinfo = karamba.getTaskInfo(widget, taskList[j]) + + if knownGroups.has_key(taskinfo[2]) == 0: + knownGroups[taskinfo[2]] = 1 + thisGroup = [] + thisGroup.append(taskinfo) + groupRefs[taskinfo[2]] = len(groups) + groups.append(thisGroup) + else: + knownGroups[taskinfo[2]] = knownGroups[taskinfo[2]] + 1 + thisGroup = groups[groupRefs[taskinfo[2]]] + thisGroup.append(taskinfo) + + if taskSelected < len(groups): + taskGroup = groups[taskSelected] + + + if len(taskGroup) == 1: + #only one task in group - just switch to that app + ## perform the task action (see Task API for list of numbers) + karamba.performTaskAction(widget, taskGroup[0][8], 8) + + else: + #more than one task in this group, make a popup + for task in taskGroup: + #if it's minimized, put []'s around name + if task[5] == 1: + item = karamba.addMenuItem(widget, taskMenu, "[ " + task[0] + " ]", task[2]) + else: + item = karamba.addMenuItem(widget, taskMenu, task[0], task[2]) + #save the taskInfo item for later use + #so we will know info for the task that + #will be clicked in the callback + taskMenuLookup[item] = task + + numOfItems = len(taskGroup) + karamba.popupMenu(widget, taskMenu, 198 + (121*taskSelected), -1 * (numOfItems * 26)) + + + + if (taskSelected == numOfTasks): + karamba.toggleShowDesktop(widget) + +#This gets called when an item is clicked in a popup menu you have created. +# menu = a reference to the menu +# id = the number of the item that was clicked. +def menuItemClicked(widget, menu, id): + global taskMenuLookup + + taskinfo = taskMenuLookup[id] + karamba.performTaskAction(widget, taskinfo[8], 8) + + diff --git a/superkaramba/examples/taskBar/cleanbar/cleanbar.theme b/superkaramba/examples/taskBar/cleanbar/cleanbar.theme new file mode 100644 index 0000000..ec111cd --- /dev/null +++ b/superkaramba/examples/taskBar/cleanbar/cleanbar.theme @@ -0,0 +1,14 @@ +KARAMBA X=0 Y=0 W=1600 H=31 LOCKED=true ONTOP=TRUE BOTTOMBAR=true INTERVAL=20000 + +IMAGE X=0 Y=0 PATH="pics/bar2.png" + +#K Menu +CLICKAREA X=4 Y=6 W=64 H=25 ONCLICK="dcop kicker kicker popupKMenu 0" + +#XMMS controls +CLICKAREA X=96 Y=6 W=15 H=23 ONCLICK="xmmsctrl prev" +CLICKAREA X=121 Y=6 W=10 H=23 ONCLICK="xmmsctrl play" +CLICKAREA X=140 Y=6 W=12 H=23 ONCLICK="xmmsctrl pause" +CLICKAREA X=159 Y=6 W=12 H=23 ONCLICK="xmmsctrl stop" +CLICKAREA X=180 Y=6 W=12 H=23 ONCLICK="xmmsctrl next" + diff --git a/superkaramba/examples/taskBar/cleanbar/pics/bar2.png b/superkaramba/examples/taskBar/cleanbar/pics/bar2.png new file mode 100644 index 0000000..1566ff0 Binary files /dev/null and b/superkaramba/examples/taskBar/cleanbar/pics/bar2.png differ diff --git a/superkaramba/examples/taskBar/cleanbar/pics/rightend.png b/superkaramba/examples/taskBar/cleanbar/pics/rightend.png new file mode 100644 index 0000000..0da33ca Binary files /dev/null and b/superkaramba/examples/taskBar/cleanbar/pics/rightend.png differ diff --git a/superkaramba/examples/taskBar/cleanbar/pics/rightend_new.png b/superkaramba/examples/taskBar/cleanbar/pics/rightend_new.png new file mode 100644 index 0000000..356b970 Binary files /dev/null and b/superkaramba/examples/taskBar/cleanbar/pics/rightend_new.png differ diff --git a/superkaramba/examples/taskBar/cleanbar/pics/slickbar.png b/superkaramba/examples/taskBar/cleanbar/pics/slickbar.png new file mode 100644 index 0000000..24b7336 Binary files /dev/null and b/superkaramba/examples/taskBar/cleanbar/pics/slickbar.png differ diff --git a/superkaramba/examples/taskBar/cleanbar/pics/startup.png b/superkaramba/examples/taskBar/cleanbar/pics/startup.png new file mode 100644 index 0000000..0d3555e Binary files /dev/null and b/superkaramba/examples/taskBar/cleanbar/pics/startup.png differ diff --git a/superkaramba/examples/taskBar/cleanbar/pics/task.png b/superkaramba/examples/taskBar/cleanbar/pics/task.png new file mode 100644 index 0000000..3058f41 Binary files /dev/null and b/superkaramba/examples/taskBar/cleanbar/pics/task.png differ diff --git a/superkaramba/examples/taskBar/cleanbar/pics/task_new.png b/superkaramba/examples/taskBar/cleanbar/pics/task_new.png new file mode 100644 index 0000000..e66537c Binary files /dev/null and b/superkaramba/examples/taskBar/cleanbar/pics/task_new.png differ diff --git a/superkaramba/examples/template.py b/superkaramba/examples/template.py new file mode 100644 index 0000000..d79d1a0 --- /dev/null +++ b/superkaramba/examples/template.py @@ -0,0 +1,160 @@ +#this import statement allows access to the karamba functions +import karamba + + +#this is called when your widget is initialized +def initWidget(widget): + pass + +#This is called when your widget is closed. You can use this to clean +#up open files, etc. You don't need to delete text and images in your +#theme. That is done automatically. This callback is just for cleaning up +#external things. Most people don't need to put anything here. +def widgetClosed(widget): + pass + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + pass + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + pass + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + #Warning: Don't do anything too intensive here + #You don't want to run some complex piece of code everytime the mouse moves + pass + + +#This gets called when an item is clicked in a popup menu you have created. +# menu = a reference to the menu +# id = the number of the item that was clicked. +def menuItemClicked(widget, menu, id): + pass + +#This gets called when an item is clicked in the theme CONFIGURATION menu, +#not the popup menus that you create. +# key = the reference to the configuration key that was changed +# value = the new value (true or false) that was selected +def menuOptionChanged(widget, key, value): + pass + +#This gets called when a meter (image, text, etc) is clicked. +# NOTE you must use attachClickArea() to make a meter +# clickable. +# widget = reference to your theme +# meter = the meter clicked +# button = the button clicked (see widgetClicked for button numbers) +def meterClicked(widget, meter, button): + pass + +#This gets called when a command you have executed with executeInteractive() outputs something +#to stdout. This way you can get the output of for example kdialog without freezing up the widget +#waiting for kdialog to end. +# widget = reference to your theme +# pid = process number of the program outputting (use this if you execute more than out process) +# output = the text the program outputted to stdout +def commandOutput(widget, pid, output): + pass + +#This gets called when another theme sends a message. +# widget = reference to your theme +# caller = "pretty" name or regular name (name of theme file with a number attached) of sending theme +# output = the text sent. +def themeNotify(widget, caller, message): + pass + +#This gets called when an item is dropped on this widget. +# NOTE you have to call acceptDrops() before your widget will accept drops. +# widget = reference to your theme +# dropText = the text of the dropped item (probably a URL to it's location in KDE) +# x = the x position on the theme relative to the upper left corner +# y = the y position on the theme relative to the upper left corner +def itemDropped(widget, dropText, x, y): + pass + + +#This gets called when a new program is LOADING in KDE. When it is done +#loading, startupRemoved() is called, followed by taskAdded(). +# widget = reference to your widget +# task = A refence to the task that is starting. +def startupAdded(widget, startup): + pass + +#This gets called when a new program is done LOADING in KDE. +# widget = reference to your widget +# task = A refence to the task that just finished loading. +def startupRemoved(widget, startup): + pass + +#This is called every time a new task (program) is started in KDE. +# widget = reference to your widget +# task = A refence to the new task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def taskAdded(widget, task): + pass + +#This is called everytime a task (program) is closed in KDE. +# widget = reference to your widget +# task = A refence to the task. +def taskRemoved(widget, task): + pass + +#This is called everytime a different task gains focus (IE, the user clicks +#on a different window). +# widget = reference to your widget +# task = A refence to the task. Call getTaskInfo() with this reference +# to get the name, etc of this new task. +def activeTaskChanged(widget, task): + pass + +#This is called everytime the systray you created with createSystray() is updated +def systrayUpdated(widget): + pass + +#This is called everytime the current desktop changes +# widget = reference to your widget +# desktop = the current desktop +def desktopChanged(widget, desktop): + pass + +#This is called everytime the wallpaper changes on a desktop +# widget = reference to your widget +# desktop = the desktop whose wallpaper changed +def wallpaperChanged(widget, desktop): + pass + +#This is called everytime there is a key press in any focused input field +# widget = reference to your widget +# meter = reference to an input box +# char = the key that was pressed +def keyPressed(widget, meter, char): + pass + +# This will be printed when the widget loads. +print "Loaded my python extension!" diff --git a/superkaramba/examples/test_all.sh b/superkaramba/examples/test_all.sh new file mode 100755 index 0000000..5e95063 --- /dev/null +++ b/superkaramba/examples/test_all.sh @@ -0,0 +1,27 @@ +#!/bin/sh +themes=( + "text/text.theme" + "autoHide/main.theme" + "bar/bar.theme" + "graph/graph.theme" + "image/image.theme" + "popupMenu/popupMenu.theme" + "taskBar/cleanbar/cleanbar.theme" + "richtext/richtext.theme" + "richtext/rtext.theme" + "globalMouse/eyes.theme" + "unicode/unicode.theme" + "mouseDrag/karmix/karmix.theme" + "input_api/input_api.theme" + "input_example/input_example.theme" +) + +for theme in "${themes[@]}" +do + echo $theme + dcop `dcop superkaramba* | head -n 1` default openTheme $PWD/$theme + read a + dcop `dcop superkaramba* | head -n 1` default closeTheme `expr $theme : '.*/\(.*\)\.'` +done + +#dcop `dcop superkaramba* | head -n 1` default quit diff --git a/superkaramba/examples/text/text.py b/superkaramba/examples/text/text.py new file mode 100644 index 0000000..4612dd5 --- /dev/null +++ b/superkaramba/examples/text/text.py @@ -0,0 +1,110 @@ +#this import statement allows access to the karamba functions +import karamba + +align = ['LEFT', 'CENTER', 'RIGHT'] +texts = [0,0,0,0,0,0,0,0,0,0,0] +b = 0 +a = 0 + +#this is called when you widget is initialized +def initWidget(widget): + global texts, b + texts[0] = karamba.getThemeText(widget, "text0") + texts[1] = karamba.getThemeText(widget, "text1") + texts[2] = karamba.getThemeText(widget, "text2") + texts[3] = karamba.getThemeText(widget, "text3") + texts[4] = karamba.getThemeText(widget, "text4") + texts[5] = karamba.getThemeText(widget, "text5") + texts[6] = karamba.getThemeText(widget, "text6") + texts[7] = karamba.getThemeText(widget, "text7") + texts[8] = karamba.getThemeText(widget, "text8") + texts[9] = karamba.getThemeText(widget, "text9") + texts[10] = karamba.getThemeText(widget, "text10") + + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + global texts, b, a + + b = (b+1)%2 + + # Create & delete + if(texts[0]): + karamba.deleteText(widget, texts[0]) + texts[0] = 0 + else: + texts[0] = karamba.createText(widget, 0, 20, 200, 20, "Text meter") + + # size & resize + size = karamba.getTextSize(widget, texts[1]) + print "getTextSize: " + str(size) + size = ((b * 200) + 200, size[1]) + karamba.resizeText(widget, texts[1], size[0], size[1]) + + # pos & move + pos = karamba.getTextPos(widget, texts[2]) + print "getTextPos: " + str(pos) + pos = (b * 200, pos[1]) + karamba.moveText(widget, texts[2], pos[0], pos[1]) + + # Hide & Show + if(b): + karamba.hideText(widget, texts[3]) + else: + karamba.showText(widget, texts[3]) + + # Sensor + sensor = karamba.getTextSensor(widget, texts[4]) + print "getSensor: " + str(sensor) + if(b): + karamba.setTextSensor(widget, texts[4], 'SENSOR=SENSOR TYPE="cpu_temp"') + else: + karamba.setTextSensor(widget, texts[4], 'SENSOR=CPU') + + # Value + v = karamba.getTextValue(widget, texts[5]) + print "getTextValue: ", v + v += '.' + karamba.changeText(widget, texts[5], v) + + # Shadow + v = karamba.getTextShadow(widget, texts[6]) + print "getTextShadow: ", v + v = (v+1)%10; + karamba.changeTextShadow(widget, texts[6], v) + + # Font size + v = karamba.getTextFontSize(widget, texts[7]) + print "getTextFontSize: ", v + v = 10 + ((v-10)+1)%10; + karamba.changeTextSize(widget, texts[7], v) + + # Text color + v = karamba.getTextColor(widget, texts[8]) + print "getTextColor: ", v + karamba.changeTextColor(widget, texts[8], b*255, b*255, b*255) + + # Text Font + v = karamba.getTextFont(widget, texts[9]) + print "getTextFont: ", v + if(b): + v = 'Bitstream Vera Sans' + else: + v = 'Bitstream Vera Serif' + karamba.changeTextFont(widget, texts[9], v) + + # Text Alignment + a = (a+1)%3 + v = karamba.getTextAlign(widget, texts[10]) + print "getTextAlign: ", v + karamba.setTextAlign(widget, texts[10], align[a]) + +def widgetClicked(widget, x, y, button): + pass + +def widgetMouseMoved(widget, x, y, button): + pass + +# This will be printed when the widget loads. +print "Loaded Text test python extension!" diff --git a/superkaramba/examples/text/text.theme b/superkaramba/examples/text/text.theme new file mode 100644 index 0000000..522640a --- /dev/null +++ b/superkaramba/examples/text/text.theme @@ -0,0 +1,35 @@ +KARAMBA x=100 y=10 w=600 h=580 INTERVAL=1000 LOCKED=true +DEFAULTFONT font="Bitstream Vera Sans" fontsize=16 color=200,200,200 + +TEXT x=0 Y=0 w=600 h=20 VALUE="createText & deleteText" name=ttext0 +TEXT x=0 Y=20 w=200 h=20 value="Text meter" min=0 max=100 name=text0 + +TEXT x=0 Y=45 w=600 h=20 VALUE="getTextSize & resizeText" name=ttext1 +TEXT x=0 Y=65 w=200 h=20 value="The quick brown fox jumps over the lazy dog" min=0 max=100 name=text1 + +TEXT x=0 Y=90 w=600 h=20 VALUE="getTextPos & moveText" name=ttext2 +TEXT x=0 Y=110 w=200 h=20 value="Text meter" min=0 max=100 name=text2 + +TEXT x=0 Y=135 w=600 h=20 VALUE="hideText & showText" name=ttext3 +TEXT x=0 Y=155 w=200 h=20 value="Text meter" min=0 max=100 name=text3 + +TEXT x=0 Y=180 w=600 h=20 VALUE="getTextSensor & setTextSensor" name=ttext4 +TEXT x=0 Y=200 w=200 h=20 value=50 min=0 max=100 name=text4 + +TEXT x=0 Y=225 w=600 h=20 VALUE="getTextValue & setTextValue" name=ttext5 +TEXT x=0 Y=245 w=200 h=20 value="." min=0 max=100 name=text5 + +TEXT x=0 Y=270 w=600 h=20 VALUE="getTextShadow & setTextShadow" name=ttext6 +TEXT x=0 Y=290 w=400 h=20 value="The quick brown fox jumps over the lazy dog" min=0 max=100 name=text6 + +TEXT x=0 Y=315 w=600 h=20 VALUE="setTextSize & getTextSize" name=ttext7 +TEXT x=0 Y=335 w=200 h=20 value="Text meter" min=0 max=100 name=text7 + +TEXT x=0 Y=360 w=600 h=20 VALUE="setTextColor & getTextColor" name=ttext8 +TEXT x=0 Y=380 w=400 h=20 value="The quick brown fox jumps over the lazy dog" min=0 max=100 name=text8 + +TEXT x=0 Y=405 w=600 h=20 VALUE="setTextFont & getTextFont" name=ttext9 +TEXT x=0 Y=425 w=400 h=20 value="The quick brown fox jumps over the lazy dog" min=0 max=100 name=text9 + +TEXT x=0 Y=450 w=600 h=20 VALUE="setTextAlign & getTextAlign" name=ttext10 +TEXT x=0 Y=470 w=400 h=20 value="Text meter" min=0 max=100 name=text10 diff --git a/superkaramba/examples/unicode/unicode.py b/superkaramba/examples/unicode/unicode.py new file mode 100644 index 0000000..13d1136 --- /dev/null +++ b/superkaramba/examples/unicode/unicode.py @@ -0,0 +1,116 @@ +#Unicode Example + +#For Symbol Tables look at www.unicode.org/charts/ + + +#this import statement allows access to the karamba functions +import karamba + +#this is called when you widget is initialized +def initWidget(widget): + + text=u""" +

    UNICODE Example

    +

    Greek:

    +\u03B1\u03B2\u03B3\u03B4\u03B5\u03B6\u03B7\u03B8\u03B9\u03BA\u03BB\u03BC\u03BD\u03BE\u03BF\u03C0 +\u03C1\u03C2\u03C3\u03C4\u03C5\u03C6\u03C7\u03C8\u03C9 +
    +\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039A\u039B\u039C\u039D\u039E\u039F\u03A0 +\u03A1\u03A3\u03A4\u03A5\u03A6\u03A7\u03A8\u03A9 +

    Cyrillic:

    +\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043A\u043B\u043C\u043D\u043E\u043F +\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044A\u044B\u044C\u044D\u044E\u044F +
    +\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041A\u041B\u041C\u041D\u041E\u041F +\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042A\u042B\u042C\u042D\u042E\u042F +

    Hebrew:

    +\u05D0\u05D1\u05D2\u05D3\u05D4\u05D5\u05D6\u05D7\u05D8\u05D9\u05DA\u05DB\u05DC\u05DD\u05DE\u05DF +\u05E0\u05E1\u05E2\u05E3\u05E4\u05E5\u05E6\u05E7\u05E8\u05E9\u05EA +

    Arabic:

    +\u0621\u0622\u0623\u0624\u0625\u0626\u0627\u0628\u0629\u062A\u062B\u062C\u062D\u062E\u062F\u0630 +\u0631\u0632\u0633\u0634\u0635\u0636\u0637\u0638\u0639\u063A\u0641\u0642\u0643\u0644\u0645\u0646 +\u0647\u0648\u064A +

    +For a complete reference on unicode caracter codes look at: +

    www.unicode.org/charts/
    +

    +""" + karamba.resizeWidget(widget, 400, 400) + + richtext = karamba.createRichText(widget, text) + + karamba.setRichTextWidth(widget, richtext, 370) + +# greek_heading = karamba.createText(widget, 0, 5, 100, 20, "Greek:") +# greek_small = karamba.createText(widget, 0, 25, 400, 15, u"\u03B1\u03B2\u03B3\u03B4\u03B5\u03B6\u03B7\u03B8\u03B9\u03BA\u03BB\u03BC\u03BD\u03BE\u03BF\u03C0\u03C1\u03C2\u03C3\u03C4\u03C5\u03C6\u03C7\u03C8\u03C9"); +# greek_big = karamba.createText(widget, 0, 40, 400, 15, u"\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039A\u039B\u039C\u039D\u039E\u039F\u03A0\u03A1\u03A3\u03A4\u03A5\u03A6\u03A7\u03A8\u03A9"); + +# hebrew_heading = karamba.createText(widget, 0, 60, 100, 20, "Hebrew:") +# hebrew = karamba.createText(widget, 0, 80, 400, 15, u"\u05D0\u05D1\u05D2\u05D3\u05D4\u05D5\u05D6\u05D7\u05D8\u05D9\u05DA\u05DB\u05DC\u05DD\u05DE\u05DF\u05E0\u05E1\u05E2\u05E3\u05E4\u05E5\u05E6\u05E7\u05E8\u05E9\u05EA"); + +# arabic_heading = karamba.createText(widget, 0, 100, 100, 20, "Arabic:") +# arabic = karamba.createText(widget, 0, 120, 400, 15, u"\u0621\u0622\u0623\u0624\u0625\u0626\u0627\u0628\u0629\u062A\u062B\u062C\u062D\u062E\u062F\u0630\u0631\u0632\u0633\u0634\u0635\u0636\u0637\u0638\u0639\u063A\u0641\u0642\u0643\u0644\u0645\u0646\u0647\u0648\u064A"); + +# cyrillic_heading = karamba.createText(widget, 0, 140, 100, 20, "Cyrillic:") +# cyrillic_small = karamba.createText(widget, 0, 160, 400, 15, u"\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043A\u043B\u043C\u043D\u043E\u043F\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044A\u044B\u044C\u044D\u044E\u044F") +# cyrillic_big = karamba.createText(widget, 0, 175, 400, 15, u"\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041A\u041B\u041C\u041D\u041E\u041F\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042A\u042B\u042C\u042D\u042E\u042F") + +# karamba.changeTextColor(widget, greek_heading, 0, 0, 0) +# karamba.changeTextColor(widget, greek_small, 0, 0, 0) +# karamba.changeTextColor(widget, greek_big, 0, 0, 0) +# karamba.changeTextColor(widget, hebrew_heading, 0, 0, 0) +# karamba.changeTextColor(widget, hebrew, 0, 0, 0) +# karamba.changeTextColor(widget, arabic_heading, 0, 0, 0) +# karamba.changeTextColor(widget, arabic, 0, 0, 0) +# karamba.changeTextColor(widget, cyrillic_heading, 0, 0, 0) +# karamba.changeTextColor(widget, cyrillic_small, 0, 0, 0) +# karamba.changeTextColor(widget, cyrillic_big, 0, 0, 0) + +# karamba.changeTextSize(widget, greek_heading, 12) +# karamba.changeTextSize(widget, hebrew_heading, 12) +# karamba.changeTextSize(widget, arabic_heading, 12) +# karamba.changeTextSize(widget, cyrillic_heading, 12) + + + +#this is called everytime your widget is updated +#the update inverval is specified in the .theme file +def widgetUpdated(widget): + pass + + +#This gets called everytime our widget is clicked. +#Notes: +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button clicked: +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +# 4,5 = Scroll wheel up and down +def widgetClicked(widget, x, y, button): + pass + +def meterClicked(widget, meter, button): + pass + +#This gets called everytime our widget is clicked. +#Notes +# widget = reference to our widget +# x = x position (relative to our widget) +# y = y position (relative to our widget) +# botton = button being held: +# 0 = No Mouse Button +# 1 = Left Mouse Button +# 2 = Middle Mouse Button +# 3 = Right Mouse Button, but this will never happen +# because the right mouse button brings up the +# Karamba menu. +def widgetMouseMoved(widget, x, y, button): + pass + +# This will be printed when the widget loads. +print "Loaded Karamba Unicode Test" diff --git a/superkaramba/examples/unicode/unicode.theme b/superkaramba/examples/unicode/unicode.theme new file mode 100644 index 0000000..44cb1c8 --- /dev/null +++ b/superkaramba/examples/unicode/unicode.theme @@ -0,0 +1 @@ +KARAMBA X=80 Y=20 W=400 H=300 LOCKED=true INTERVAL=10000 diff --git a/superkaramba/icons/Makefile.am b/superkaramba/icons/Makefile.am new file mode 100644 index 0000000..da1319d --- /dev/null +++ b/superkaramba/icons/Makefile.am @@ -0,0 +1 @@ +KDE_ICON = AUTO \ No newline at end of file diff --git a/superkaramba/icons/cr128-app-superkaramba.png b/superkaramba/icons/cr128-app-superkaramba.png new file mode 100644 index 0000000..ea1dd27 Binary files /dev/null and b/superkaramba/icons/cr128-app-superkaramba.png differ diff --git a/superkaramba/icons/cr128-mime-superkaramba_theme.png b/superkaramba/icons/cr128-mime-superkaramba_theme.png new file mode 100644 index 0000000..b58d8c6 Binary files /dev/null and b/superkaramba/icons/cr128-mime-superkaramba_theme.png differ diff --git a/superkaramba/icons/cr16-app-superkaramba.png b/superkaramba/icons/cr16-app-superkaramba.png new file mode 100644 index 0000000..0bbcfcd Binary files /dev/null and b/superkaramba/icons/cr16-app-superkaramba.png differ diff --git a/superkaramba/icons/cr16-mime-superkaramba_theme.png b/superkaramba/icons/cr16-mime-superkaramba_theme.png new file mode 100644 index 0000000..8ecdd2e Binary files /dev/null and b/superkaramba/icons/cr16-mime-superkaramba_theme.png differ diff --git a/superkaramba/icons/cr22-app-superkaramba.png b/superkaramba/icons/cr22-app-superkaramba.png new file mode 100644 index 0000000..2ea31f0 Binary files /dev/null and b/superkaramba/icons/cr22-app-superkaramba.png differ diff --git a/superkaramba/icons/cr22-mime-superkaramba_theme.png b/superkaramba/icons/cr22-mime-superkaramba_theme.png new file mode 100644 index 0000000..165e902 Binary files /dev/null and b/superkaramba/icons/cr22-mime-superkaramba_theme.png differ diff --git a/superkaramba/icons/cr32-app-superkaramba.png b/superkaramba/icons/cr32-app-superkaramba.png new file mode 100644 index 0000000..0d35fba Binary files /dev/null and b/superkaramba/icons/cr32-app-superkaramba.png differ diff --git a/superkaramba/icons/cr32-mime-superkaramba_theme.png b/superkaramba/icons/cr32-mime-superkaramba_theme.png new file mode 100644 index 0000000..943b8fc Binary files /dev/null and b/superkaramba/icons/cr32-mime-superkaramba_theme.png differ diff --git a/superkaramba/icons/cr48-app-superkaramba.png b/superkaramba/icons/cr48-app-superkaramba.png new file mode 100644 index 0000000..5af2f63 Binary files /dev/null and b/superkaramba/icons/cr48-app-superkaramba.png differ diff --git a/superkaramba/icons/cr48-mime-superkaramba_theme.png b/superkaramba/icons/cr48-mime-superkaramba_theme.png new file mode 100644 index 0000000..e8cd7a7 Binary files /dev/null and b/superkaramba/icons/cr48-mime-superkaramba_theme.png differ diff --git a/superkaramba/icons/cr64-app-superkaramba.png b/superkaramba/icons/cr64-app-superkaramba.png new file mode 100644 index 0000000..30bf592 Binary files /dev/null and b/superkaramba/icons/cr64-app-superkaramba.png differ diff --git a/superkaramba/icons/cr64-mime-superkaramba_theme.png b/superkaramba/icons/cr64-mime-superkaramba_theme.png new file mode 100644 index 0000000..698eeb2 Binary files /dev/null and b/superkaramba/icons/cr64-mime-superkaramba_theme.png differ diff --git a/superkaramba/icons/crsc-app-superkaramba.svgz b/superkaramba/icons/crsc-app-superkaramba.svgz new file mode 100644 index 0000000..c9c634f Binary files /dev/null and b/superkaramba/icons/crsc-app-superkaramba.svgz differ diff --git a/superkaramba/icons/crsc-mime-superkaramba_theme.svgz b/superkaramba/icons/crsc-mime-superkaramba_theme.svgz new file mode 100644 index 0000000..789d081 Binary files /dev/null and b/superkaramba/icons/crsc-mime-superkaramba_theme.svgz differ diff --git a/superkaramba/karamba.kdevelop b/superkaramba/karamba.kdevelop new file mode 100644 index 0000000..41fb5e7 --- /dev/null +++ b/superkaramba/karamba.kdevelop @@ -0,0 +1,257 @@ + + + + See README for the list of authors + + KDevKDEAutoProject + C++ + + C++ + Code + Qt + KDE + + 0.36 + + + .. + false + + + + + + src/superkaramba + debug + + + superkaramba/src/superkaramba + + false + + build + /home/damu/.kde/share/apps/superkaramba/themes/hdd/ + true + + + + + + + + true + 1 + false + + + + + + 0 + + + + optimized + kdevgccoptions + kdevgppoptions + kdevg77options + -O2 -g0 + + + + + + + + + + + + + --enable-debug=full + debug + kdevgccoptions + kdevgppoptions + kdevg77options + -O0 -g3 + + + + + + + -O0 -g3 + + + + + --prefix=/usr + + kdevgccoptions + kdevgppoptions + kdevpgf77options + + + + + -march=athlon-xp -mcpu=athlon-xp -mmmx -m3dnow -msse + + .. + + + + + + + + + + + + + + false + false + + + false + *.o,*.lo,CVS + false + + + + + gtk + gnustep + python + php + perl + + + /home/hk/src/karamba/html/ + /home/hk/src/karamba/html/ + + + + + + + + + libtool + /home/damu/.kde/share/apps/superkaramba/themes/hdd/hdd.theme + + false + false + false + + + + + + false + true + 10 + + + + + + + + false + false + + + + false + + + .h + .cpp + true + + + + true + 2 + + + -f + + -dP + + -f + -u3 -p + + + + + + + + + false + false + + + + + + + + + + + + false + false + false + 0 + false + false + false + false + + + + + true + true + true + false + true + true + true + 250 + 400 + 250 + + + + + set + m_,_ + theValue + true + true + + + + + + + true + true + true + true + -C + + + + + + + + + diff --git a/superkaramba/karamba.kdevses b/superkaramba/karamba.kdevses new file mode 100644 index 0000000..5cdd262 --- /dev/null +++ b/superkaramba/karamba.kdevses @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/superkaramba/mimetypes/Makefile.am b/superkaramba/mimetypes/Makefile.am new file mode 100644 index 0000000..b5486a5 --- /dev/null +++ b/superkaramba/mimetypes/Makefile.am @@ -0,0 +1,2 @@ +mime_DATA = x-superkaramba.desktop +mimedir = $(kde_mimedir)/application diff --git a/superkaramba/mimetypes/x-superkaramba.desktop b/superkaramba/mimetypes/x-superkaramba.desktop new file mode 100644 index 0000000..946c9e1 --- /dev/null +++ b/superkaramba/mimetypes/x-superkaramba.desktop @@ -0,0 +1,52 @@ +[Desktop Entry] +Comment=Superkaramba Theme File +Comment[ar]=ملف سمِة سوبركارامبا +Comment[bg]=Файл с тема за Superkaramba +Comment[br]=Restr giz Superkaramba +Comment[bs]=Datoteka sa Superkaramba temom +Comment[ca]=Arxiu de tema pel Superkaramba +Comment[cs]=Soubor Superkaramba motivu +Comment[da]=Superkaramba-temafil +Comment[de]=Superkaramba Design-Datei +Comment[el]=Αρχείο θέματος του Superkaramba +Comment[es]=Archivo de tema de Superkaramba +Comment[et]=Superkaramba teemafail +Comment[eu]=Superkaramba gai-fitxategia +Comment[fa]=پروندۀ چهرۀ Superkaramba +Comment[fi]=Superkaramban teematiedosto +Comment[fr]=Fichier de thème SuperKaramba +Comment[ga]=Comhad Téama Superkaramba +Comment[he]=ערכת נושא של Superkaramba +Comment[hu]=SuperKaramba-témafájl +Comment[is]=Súperkaramba þemuskrá +Comment[it]=File di tema Superkaramba +Comment[ja]=Superkaramba テーマファイル +Comment[ka]=Superkaramba-ს თემის ფაილი +Comment[kk]=Superkaramba нақыш файлы +Comment[km]=ឯកសារ​ស្បែក Superkaramba +Comment[lt]=Superkaramba temos byla +Comment[nb]=Temafil for Superkaramba +Comment[nds]=Muster-Datei vun Superkaramba +Comment[ne]=सुपरकराम्बा विषयवस्तु फाइल +Comment[nl]=Thema-bestand van Superkaramba +Comment[nn]=Superkaramba-temafil +Comment[pa]=Superkaramba ਸਰੂਪ ਫਾਇਲ +Comment[pl]=Plik motywu Superkaramby +Comment[pt]=Ficheiro de Tema do Superkaramba +Comment[pt_BR]=Arquivo de Tema do Superkaramba +Comment[ru]=Тема Superkaramba +Comment[sk]=Súbor témy superkaramba +Comment[sl]=Datoteka s temo za Superkarambo +Comment[sr]=Фајл теме СуперКарамбе +Comment[sr@Latn]=Fajl teme SuperKarambe +Comment[sv]=Superkaramba-temafil +Comment[tr]=Superkaramba Tema Dosyası +Comment[uk]=Файл теми Superkaramba +Comment[zh_CN]=Superkaramba 主题文件 +Comment[zh_TW]=Superkaramba 佈景檔案 +DefaultApp=superkaramba +Icon=superkaramba_theme +MimeType=application/x-superkaramba +Patterns=*.skz;*.SKZ;*.theme;*.THEME +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/superkaramba/src/Makefile.am b/superkaramba/src/Makefile.am new file mode 100644 index 0000000..90c9aa3 --- /dev/null +++ b/superkaramba/src/Makefile.am @@ -0,0 +1,54 @@ +# set the include path for X, qt and KDE +INCLUDES = $(all_includes) $(XMMS_INCLUDES) $(PYTHONINC) + +# these are the headers for your project +noinst_HEADERS = karamba.h karambaapp.h karamba_python.h lineparser.h \ + themefile.h themesdlg.h themewidget.h kwidgetlistbox.h themelocale.h input.h \ + sklineedit.h input_python.h + +KDE_OPTIONS = nofinal + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +messages: rc.cpp + $(EXTRACTRC) *.ui >> rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/superkaramba.pot + +######################################################################### +# APPLICATION SECTION +######################################################################### +# this is the program that gets installed. its name is used for all +# of the other Makefile.am variables +bin_PROGRAMS = superkaramba + +# the application source, library search path, and link libraries +superkaramba_SOURCES = main.cpp karamba.cpp meter.cpp bar.cpp sensor.cpp \ + datesensor.cpp textlabel.cpp memsensor.cpp uptimesensor.cpp cpusensor.cpp \ + networksensor.cpp imagelabel.cpp graph.cpp xmmssensor.cpp programsensor.cpp \ + disksensor.cpp sensorparams.cpp sensorsensor.cpp textfilesensor.cpp clickarea.cpp \ + noatunsensor.cpp karambarootpixmap.cpp clickmap.cpp rsssensor.cpp textfield.cpp \ + taskmanager.cpp showdesktop.cpp richtextlabel.cpp karambasessionmanaged.cpp \ + systemtray.cpp bar_python.cpp meter_python.cpp textlabel_python.cpp \ + richtextlabel_python.cpp imagelabel_python.cpp config_python.cpp misc_python.cpp \ + systray_python.cpp task_python.cpp widget_python.cpp menu_python.cpp \ + karambalistboxitem.cpp graph_python.cpp dcopinterface.skel dcopinterface.stub \ + karambainterface.cpp karambaapp.cpp karamba_python.cpp lineparser.cpp themefile.cpp \ + themesdlg.cpp themes_layout.ui themewidget_layout.ui themewidget.cpp \ + kwidgetlistbox.cpp sknewstuff.h sknewstuff.cpp superkarambasettings.kcfgc themelocale.cpp \ + input.cpp sklineedit.cpp input_python.cpp svcgrp_python.cpp + +# kde_cfg_DATA = superkaramba.kcfg + +superkaramba_LDFLAGS = -Wl,-export-dynamic $(KDE_RPATH) $(all_libraries) $(PYTHONLIB) $(XMMS_LDFLAGS) +#superkaramba_LDADD = -lkio $(LIB_KDEUI) $(XMMS_LDADD) $(LIBPYTHON) $(LIBKVM) $(MY_LIBKNEWSTUFF) +superkaramba_LDADD = -lkio $(LIB_KDEUI) $(XMMS_LIBS) $(LIBPYTHON) $(LIBKVM) $(MY_LIBKNEWSTUFF) + +# this is where the desktop file will go +shelldesktopdir = $(kde_appsdir)/Utilities +shelldesktop_DATA = superkaramba.desktop + +# this is where the shell's XML-GUI resource file goes +shellrcdir = $(kde_datadir)/superkaramba +shellrc_DATA = superkarambaui.rc + diff --git a/superkaramba/src/bar.cpp b/superkaramba/src/bar.cpp new file mode 100644 index 0000000..354433d --- /dev/null +++ b/superkaramba/src/bar.cpp @@ -0,0 +1,134 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "bar.h" +#include "karamba.h" + +Bar::Bar(karamba* k, int x, int y, int w, int h) : Meter(k, x, y, w, h) +{ + value = 0; + minValue = 0; + maxValue = 100; + barValue = 0; + vertical = false; +} + +Bar::~Bar() +{ +} + +bool Bar::setImage(QString fileName) +{ + QFileInfo fileInfo(fileName); + bool res = false; + + if(m_karamba->theme().isThemeFile(fileName)) + { + QByteArray ba = m_karamba->theme().readThemeFile(fileName); + res = pixmap.loadFromData(ba); + } + else + { + res = pixmap.load(fileName); + } + pixmapWidth = pixmap.width(); + pixmapHeight = pixmap.height(); + + if(getWidth()==0 || getHeight()==0) + { + setWidth(pixmapWidth); + setHeight(pixmapHeight); + } + if(res) + imagePath = fileName; + return res; +} + +void Bar::setValue( long v ) +{ + if(v > maxValue) + { + // maxValue = v; + v = maxValue; + } + + if(v < minValue) + { + //minValue = v; + v = minValue; + } + + barValue = v; + + long diff = maxValue - minValue; + if(diff != 0) + { + if(vertical) + { + value = long((v-minValue)*getHeight() / diff + 0.5); + } + else // horizontal + { + value = long((v-minValue)*getWidth() / diff + 0.5); + } + } + else + { + value = 0; + } +} + +void Bar::setValue(QString v) +{ + setValue((long)(v.toDouble() + 0.5)); +} + +void Bar::setMax(long m) +{ + Meter::setMax(m); + recalculateValue(); +} + +void Bar::setMin(long m) +{ + Meter::setMin(m); + recalculateValue(); +} + +void Bar::setVertical(bool b) +{ + vertical = b; +} + +void Bar::mUpdate(QPainter *p) +{ + int x, y, width, height; + x = getX(); + y = getY(); + width = getWidth(); + height = getHeight(); + //only draw image if not hidden + if(hidden == 0) + { + if(vertical) + { + // int v = int( (value-minValue)*height / (maxValue-minValue) + 0.5 ); + p->drawTiledPixmap(x, y+height-value, width, value, pixmap, 0, + pixmapHeight-value); + } + else // horizontal + { + //int v = int( (value-minValue)*width / (maxValue-minValue) + 0.5 ); + p->drawTiledPixmap(x, y, value, height, pixmap); + } + } +} + +#include "bar.moc" diff --git a/superkaramba/src/bar.h b/superkaramba/src/bar.h new file mode 100644 index 0000000..d23ac3e --- /dev/null +++ b/superkaramba/src/bar.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef BAR_H +#define BAR_H + +#include "meter.h" +#include +#include +#include + +class Bar : public Meter +{ +Q_OBJECT +public: + Bar(karamba* k,int ix,int iy,int iw,int ih ); + ~Bar(); + + void mUpdate( QPainter * ); + + virtual void setMax( long m ); + virtual void setMin( long m ); + +public slots: + bool setImage( QString imagePath ); + QString getImage() { return imagePath; }; + + void setValue( long ); + long getValue() { return barValue; }; + void setValue( QString ); + void recalculateValue() {setValue(barValue); }; + + void setVertical( bool ); + int getVertical() { return vertical; }; + +private: + long barValue; + long value; + + int pixmapWidth; + int pixmapHeight; + + bool vertical; // vertical bar? + + QString imagePath; + QPixmap pixmap; +} +; +#endif // BAR_H diff --git a/superkaramba/src/bar_python.cpp b/superkaramba/src/bar_python.cpp new file mode 100644 index 0000000..fa94f85 --- /dev/null +++ b/superkaramba/src/bar_python.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** +* bar_python.cpp - Functions for bar python api +* +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "meter.h" +#include "meter_python.h" +#include "bar_python.h" + +PyObject* py_createBar(PyObject *, PyObject *args) +{ + long widget, x, y, w, h; + char *text; + if (!PyArg_ParseTuple(args, (char*)"lllll|s", &widget, &x, &y, &w, &h, &text)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + Bar *tmp = new Bar((karamba*)widget, x,y,w,h); + if (text && text[0] != '\0') + tmp->setImage(text); + ((karamba*)widget)->meterList->append(tmp); + return (Py_BuildValue((char*)"l", (long)tmp)); +} + +PyObject* py_deleteBar(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "Bar")) + return NULL; + + ((karamba*)widget)->deleteMeterFromSensors((Meter*)meter); + return Py_BuildValue((char*)"l", + ((karamba*)widget)->meterList->removeRef((Meter*)meter)); +} + +PyObject* py_getThemeBar(PyObject *self, PyObject *args) +{ + return py_getThemeMeter(self, args, "Bar"); +} + +PyObject* py_getBarSize(PyObject *self, PyObject *args) +{ + return py_getSize(self, args, "Bar"); +} + +PyObject* py_resizeBar(PyObject *self, PyObject *args) +{ + return py_resize(self, args, "Bar"); +} + +PyObject* py_getBarPos(PyObject *self, PyObject *args) +{ + return py_getPos(self, args, "Bar"); +} + +PyObject* py_moveBar(PyObject *self, PyObject *args) +{ + return py_move(self, args, "Bar"); +} + +PyObject* py_hideBar(PyObject *self, PyObject *args) +{ + return py_hide(self, args, "Bar"); +} + +PyObject* py_showBar(PyObject *self, PyObject *args) +{ + return py_show(self, args, "Bar"); +} + +PyObject* py_getBarMinMax(PyObject *self, PyObject *args) +{ + return py_getMinMax(self, args, "Bar"); +} + +PyObject* py_setBarMinMax(PyObject *self, PyObject *args) +{ + return py_setMinMax(self, args, "Bar"); +} + +PyObject* py_getBarValue(PyObject *self, PyObject *args) +{ + return py_getValue(self, args, "Bar"); +} + +PyObject* py_setBarValue(PyObject *self, PyObject *args) +{ + return py_setValue(self, args, "Bar"); +} + +PyObject* py_getBarSensor(PyObject *self, PyObject *args) +{ + return py_getSensor(self, args, "Bar"); +} + +PyObject* py_setBarSensor(PyObject *self, PyObject *args) +{ + return py_setSensor(self, args, "Bar"); +} + +PyObject* py_getBarImage(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "Bar")) + return NULL; + return Py_BuildValue((char*)"s", ((Bar*)meter)->getImage().ascii()); +} + +PyObject* py_setBarImage(PyObject *, PyObject *args) +{ + long widget, meter; + char* s; + if (!PyArg_ParseTuple(args, (char*)"lls", &widget, &meter, &s)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "Bar")) + return NULL; + return Py_BuildValue((char*)"l", ((Bar*)meter)->setImage(s)); +} + +PyObject* py_getBarVertical(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "Bar")) + return NULL; + return Py_BuildValue((char*)"l", ((Bar*)meter)->getVertical()); +} + +PyObject* py_setBarVertical(PyObject *, PyObject *args) +{ + long widget, meter, l; + if (!PyArg_ParseTuple(args, (char*)"lll", &widget, &meter, &l)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "Bar")) + return NULL; + ((Bar*)meter)->setVertical(l); + return Py_BuildValue((char*)"l", 1); +} diff --git a/superkaramba/src/bar_python.h b/superkaramba/src/bar_python.h new file mode 100644 index 0000000..0d5d428 --- /dev/null +++ b/superkaramba/src/bar_python.h @@ -0,0 +1,316 @@ +/**************************************************************************** +* bar_python.cpp - Functions for bar python api +* +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef BAR_PYTHON_H +#define BAR_PYTHON_H + +/** Bar/createBar +* +* SYNOPSIS +* long createBar(widget, x, y, w, h, image) +* DESCRIPTION +* This creates a bar at x,y with width and height w,h. +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * long w -- width +* * long h -- height +* * string image -- Path to image +* RETURN VALUE +* Pointer to new bar meter +*/ +PyObject* py_createBar(PyObject *self, PyObject *args); + +/** Bar/deleteBar +* +* SYNOPSIS +* long deleteBar(widget, bar) +* DESCRIPTION +* This deletes bar. +* ARGUMENTS +* * long widget -- karamba +* * long widget -- bar +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_deleteBar(PyObject *self, PyObject *args); + +/** Bar/getThemeBar +* +* SYNOPSIS +* long getThemeBar(widget, name) +* DESCRIPTION +* You can reference bar in your python code that was created in the +* theme file. Basically, you just add a NAME= value to the BAR line in +* the .theme file. Then if you want to use that object, instead of calling +* createBar, you can call this function. +* +* The name you pass to the function is the same one that you gave it for +* the NAME= parameter in the .theme file. +* ARGUMENTS +* * long widget -- karamba +* * string name -- name of the bar to get +* RETURN VALUE +* Pointer to bar +*/ +PyObject* py_getThemeBar(PyObject *self, PyObject *args); + +/** Bar/getBarSize +* +* SYNOPSIS +* tuple getBarSize(widget, bar) +* DESCRIPTION +* Given a reference to a bar object, this will return a tuple +* containing the height and width of a bar object. +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* RETURN VALUE +* size +*/ +PyObject* py_getBarSize(PyObject *self, PyObject *args); + +/** Bar/resizeBar +* +* SYNOPSIS +* long resizeBar(widget, bar, w, h) +* DESCRIPTION +* This will resize bar to new height and width. +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* * long w -- new width +* * long h -- new height +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_resizeBar(PyObject *self, PyObject *args); + +/** Bar/getBarPos +* +* SYNOPSIS +* tuple getBarPos(widget, bar) +* DESCRIPTION +* Given a reference to a bar object, this will return a tuple +* containing the x and y coordinate of a bar object. +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* RETURN VALUE +* pos +*/ +PyObject* py_getBarPos(PyObject *self, PyObject *args); + +/** Bar/moveBar +* +* SYNOPSIS +* long moveBar(widget, bar, x, y) +* DESCRIPTION +* This will move bar to new x and y coordinates. +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* * long x -- x coordinate +* * long y -- y coordinate +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_moveBar(PyObject *self, PyObject *args); + +/** Bar/hideBar +* +* SYNOPSIS +* long hideBar(widget, bar) +* DESCRIPTION +* This hides an bar. In other words, during subsequent calls to +* widgetUpdate(), this bar will not be drawn. +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_hideBar(PyObject *self, PyObject *args); + +/** Bar/showBar +* +* SYNOPSIS +* long showBar(widget, bar) +* DESCRIPTION +* This shows an bar. In other words, during subsequent calls to +* widgetUpdate(), this bar will be drawn. +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_showBar(PyObject *self, PyObject *args); + +/** Bar/getBarValue +* +* SYNOPSIS +* long getBarValue(widget, bar) +* DESCRIPTION +* Returns current bar value. +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* RETURN VALUE +* value +*/ +PyObject* py_getBarValue(PyObject *self, PyObject *args); + +/** Bar/setBarValue +* +* SYNOPSIS +* long setBarValue(widget, bar, value) +* DESCRIPTION +* Sets current bar value. +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* * long value -- new value +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setBarValue(PyObject *self, PyObject *args); + +/** Bar/getBarMinMax +* +* SYNOPSIS +* tuple getBarMinMax(widget, bar) +* DESCRIPTION +* Returns current bar value. +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* RETURN VALUE +* min & max +*/ +PyObject* py_getBarMinMax(PyObject *self, PyObject *args); + +/** Bar/setBarMinMax +* +* SYNOPSIS +* long setBarMinMax(widget, bar, min, max) +* DESCRIPTION +* Returns current bar value. +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* * long min -- min value +* * long max -- max value +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setBarMinMax(PyObject *self, PyObject *args); + +/** Bar/getBarSensor +* +* SYNOPSIS +* string getBarSensor(widget, bar) +* DESCRIPTION +* Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* RETURN VALUE +* sensor string +*/ +PyObject* py_getBarSensor(PyObject *self, PyObject *args); + +/** Bar/setBarSensor +* +* SYNOPSIS +* long setBarSensor(widget, bar, sensor) +* DESCRIPTION +* Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* * string sensor -- new sensor as in theme files +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setBarSensor(PyObject *self, PyObject *args); + +/** Bar/getBarImage +* +* SYNOPSIS +* string getBarImage(widget, bar) +* DESCRIPTION +* Get bar image +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* RETURN VALUE +* path to bar image +*/ +PyObject* py_getBarImage(PyObject *self, PyObject *args); + +/** Bar/setBarImage +* +* SYNOPSIS +* long setBarImage(widget, bar, image) +* DESCRIPTION +* Get bar image +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* * string image -- new image +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setBarImage(PyObject *self, PyObject *args); + +/** Bar/getBarVertical +* +* SYNOPSIS +* string getBarVertical(widget, bar) +* DESCRIPTION +* Check if bar is vertical bar +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* RETURN VALUE +* 1 if vertical +*/ +PyObject* py_getBarVertical(PyObject *self, PyObject *args); + +/** Bar/setBarVertical +* +* SYNOPSIS +* long setBarVertical(widget, bar) +* DESCRIPTION +* Set bar vertical +* ARGUMENTS +* * long widget -- karamba +* * long bar -- pointer to bar +* * long vertical -- 1 if vertical +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setBarVertical(PyObject *self, PyObject *args); + +#endif // BAR_PYTHON_H diff --git a/superkaramba/src/clickable.cpp b/superkaramba/src/clickable.cpp new file mode 100644 index 0000000..ac3ae1b --- /dev/null +++ b/superkaramba/src/clickable.cpp @@ -0,0 +1,37 @@ +/*************************************************************************** + * Copyright (C) 2003 by Ralph M. Churchill * + * mrchucho@yahoo.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "clickable.h" + + +Clickable::Clickable( int x, int y, int w, int h ) +{ + boundingBox = QRect( x, y, w, h ); +} + +Clickable::~Clickable() +{} + +/* +void Clickable::setOnClick( QString oc ) +{ + onClick = oc; +} + +void Clickable::setOnMiddleClick( QString oc ) +{ + onMiddleClick = oc; +} +*/ + +QRect Clickable::getBoundingBox() +{ + return boundingBox; +} diff --git a/superkaramba/src/clickable.h b/superkaramba/src/clickable.h new file mode 100644 index 0000000..f549893 --- /dev/null +++ b/superkaramba/src/clickable.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2003 by Ralph M. Churchill * + * mrchucho@yahoo.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef CLICKABLE_H +#define CLICKABLE_H + +#include +#include +#include + + +/** + * + * Ralph M. Churchill + **/ +class Clickable +{ +public: + Clickable(int x, int y, int w, int h ); + + virtual ~Clickable(); + + virtual void click( QMouseEvent* ) = 0; + /* + void setOnClick( QString ); + void setOnMiddleClick( QString ); + */ + + virtual QRect getBoundingBox(); + +protected: + QRect boundingBox; + /* + QString onClick; + QString onMiddleClick; + */ +}; + +#endif diff --git a/superkaramba/src/clickarea.cpp b/superkaramba/src/clickarea.cpp new file mode 100644 index 0000000..d060b4d --- /dev/null +++ b/superkaramba/src/clickarea.cpp @@ -0,0 +1,107 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * Copyright (C) 2004,2005 Luke Kenneth Casson Leighton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "clickarea.h" + +#include + + +ClickArea::ClickArea(karamba* k, int x, int y, int w, int h ) + : Meter(k, x, y, w, h ) +{ + value = ""; + rect = QRect( x, y, w, h ); +} + +ClickArea::~ClickArea() +{} + + +bool ClickArea::click( QMouseEvent *e ) +{ + if( rect.contains( e->x(), e->y() ) ) + { + //qDebug(QString::number(e->type())); + //KShellProcess ksp; + if( e->button() != Qt::LeftButton ) + return false; + if (!svc_name.isEmpty()) + { + KService sv(svc_name, svc_onClick, svc_icon); + KURL::List l; + KRun::run(sv, l); + return false; + } + else + { + QString program; + program = onClick; + program.replace( QRegExp("%v", false), value ); + + if( !program.isEmpty() ) + { + //qDebug(program); + KRun::runCommand(program); + } + } + } + return false; +} + +void ClickArea::setOnClick( QString oc ) +{ + onClick = oc; +} + +void ClickArea::setServiceOnClick( QString name , QString exec, QString icon ) +{ + svc_name = name; + svc_onClick = exec; + svc_icon = icon; +} + +void ClickArea::setOnMiddleClick( QString oc ) +{ + onMiddleClick = oc; +} + + +QRect ClickArea::getRectangle() +{ + return rect; +} + +void ClickArea::mUpdate( QPainter *p ) +{ + + p->drawRect(boundingBox); + +} + + +void ClickArea::setValue( long v) +{ + + setValue( QString::number( v ) ); + +} + + +void ClickArea::setValue( QString v ) +{ + value = v; +} + + + + + +#include "clickarea.moc" diff --git a/superkaramba/src/clickarea.h b/superkaramba/src/clickarea.h new file mode 100644 index 0000000..80625ee --- /dev/null +++ b/superkaramba/src/clickarea.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2003 Hans Karlsson + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#ifndef CLICKAREA_H +#define CLICKAREA_H + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "clickable.h" +/** + * + * Hans Karlsson + **/ +class ClickArea : public Meter +{ + Q_OBJECT +public: + ClickArea(karamba* k, int x, int y, int w, int h ); + + ~ClickArea(); + + virtual bool click( QMouseEvent* ); + void setOnClick( QString ); + void setServiceOnClick( QString , QString, QString); + void setOnMiddleClick( QString ); + + + QRect getRectangle(); + + void mUpdate( QPainter* ); + void setValue( long ); + void setValue( QString ); + + QRect rect; + QString onClick; + QString svc_onClick; + QString svc_name; + QString svc_icon; + QString onMiddleClick; + QString value; +}; + +#endif diff --git a/superkaramba/src/clickmap.cpp b/superkaramba/src/clickmap.cpp new file mode 100644 index 0000000..62b4376 --- /dev/null +++ b/superkaramba/src/clickmap.cpp @@ -0,0 +1,96 @@ +/*************************************************************************** + * Copyright (C) 2003 by Ralph M. Churchill * + * mrchucho@yahoo.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "clickmap.h" +#include +#include + +ClickMap::ClickMap(karamba* k, int x, int y, int w, int h ) + :Meter(k, x, y, w, h ) +{ +/* + if( h != 0 || w != 0) + clip = 0; + else + clip = Qt::DontClip; +*/ + + if( h == 0 || w == 0) + { + setWidth(-1); + setHeight(-1); + } +} + +ClickMap::~ClickMap() +{ +} + +void ClickMap::setTextProps( TextField *t ) +{ + text = *t; +} + +bool ClickMap::click( QMouseEvent *e ) { + + //Don't load the web page if the click isn't for us + if (boundingBox.contains(e->x(), e->y())) { + + int index = ((e -> y() - getY()) / text.getLineHeight()) + 1; + if (index >= 1 && index <= (int)displays.count()) { + // qDebug( "You clicked item " + QString::number( index ) + ", " + + // displays[index - 1] + " " + links[index - 1] ); + KRun::runCommand("konqueror " + links[index - 1]); + } + } + return false; +} + +void ClickMap::mUpdate( QPainter *p ) +{ + int i = 0; //text.getLineHeight(); + int row = 1; + + p->setFont(text.getFont()); + QStringList::Iterator it = displays.begin(); + while( it != displays.end() && (row <= getHeight() || getHeight() == -1 ) ) + { + p->setPen( text.getColor() ); + // p->drawText(x,y+i,width,height, Qt::AlignCenter | Qt::ExpandTabs, *it); + p->drawText(getX(), getY() + i + text.getLineHeight(), *it); + i += text.getLineHeight(); + it++; + row++; + } +} + +void ClickMap::setValue( QString v ) +{ + QRegExp rx("^http://", false ); + if ( rx.search( v ) == -1 ) + { + displays.append( v ); + } + else + { + links.append( v ); + } +} + +void ClickMap::setValue( long v ) +{ + if ( v == 0 ) + { + links.clear(); + displays.clear(); + } +} + +#include "clickmap.moc" diff --git a/superkaramba/src/clickmap.h b/superkaramba/src/clickmap.h new file mode 100644 index 0000000..f6df0db --- /dev/null +++ b/superkaramba/src/clickmap.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2003 by Ralph M. Churchill * + * mrchucho@yahoo.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef CLICKMAP_H +#define CLICKMAP_H + +#include +#include "clickable.h" +#include "textfield.h" + + +/** + * + * Ralph M. Churchill + **/ +class ClickMap : public Meter +{ +Q_OBJECT +public: + ClickMap(karamba* k, int x, int y, int w, int h); + ~ClickMap(); + + virtual bool click( QMouseEvent* ); + void mUpdate( QPainter* ); + void setValue( QString ); + void setValue( long ); + void setTextProps( TextField * ); + +private: + TextField text; + + QStringList links; + QStringList displays; +}; + +#endif diff --git a/superkaramba/src/config_python.cpp b/superkaramba/src/config_python.cpp new file mode 100644 index 0000000..28d5364 --- /dev/null +++ b/superkaramba/src/config_python.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +* config_python.cpp - Functions for config python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "meter.h" +#include "meter_python.h" +#include "config_python.h" + +// API-Function addMenuConfigOption +long addMenuConfigOption(long widget, QString key, QString name) +{ + karamba* currTheme = (karamba*)widget; + + currTheme -> addMenuConfigOption(key, name); + + return 1; +} + +PyObject* py_add_menu_config_option(PyObject *, PyObject *args) +{ + long widget; + char* key; + PyObject* name; + + if (!PyArg_ParseTuple(args, (char*)"lsO:addMenuConfigOption", &widget, &key, &name)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + QString k, n; + k.setAscii(key); + n = PyString2QString(name); + + return Py_BuildValue((char*)"l", addMenuConfigOption(widget, k, n)); +} + +long setMenuConfigOption(long widget, QString key, bool value) +{ + karamba* currTheme = (karamba*)widget; + + return currTheme -> setMenuConfigOption(key, value); +} + +PyObject* py_set_menu_config_option(PyObject *, PyObject *args) +{ + long widget; + char* key; + int value; + + if (!PyArg_ParseTuple(args, (char*)"lsi:setMenuConfigOption", &widget, &key, &value)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + QString k; + k.setAscii(key); + + return Py_BuildValue((char*)"l", setMenuConfigOption(widget, k, (bool)value)); +} + +long readMenuConfigOption(long widget, QString key) +{ + karamba* currTheme = (karamba*)widget; + + return currTheme -> readMenuConfigOption(key); +} + +PyObject* py_read_menu_config_option(PyObject *, PyObject *args) +{ + long widget; + char* key; + + if (!PyArg_ParseTuple(args, (char*)"ls:readMenuConfigOption", &widget, &key)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + QString k; + k.setAscii(key); + + return Py_BuildValue((char*)"l", readMenuConfigOption(widget, k)); +} + +// API-Function writeConfigEntry +long writeConfigEntry(long widget, QString key, QString value) +{ + karamba* currTheme = (karamba*)widget; + + currTheme -> config -> setGroup("theme"); + currTheme -> config -> writeEntry(key, value); + + return 1; +} + +PyObject* py_write_config_entry(PyObject *, PyObject *args) +{ + long widget; + char* key; + char* value; + + if (!PyArg_ParseTuple(args, (char*)"lss:writeConfigEntry", &widget, &key, &value)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + QString k, v; + k.setAscii(key); + v.setAscii(value); + + return Py_BuildValue((char*)"l", writeConfigEntry(widget, k, value)); +} + +// API-Function readConfigEntry +QVariant readConfigEntry(long widget, QString key) +{ + karamba* currTheme = (karamba*)widget; + + currTheme -> config -> setGroup("theme"); + return currTheme -> config -> readEntry(key); +} + +PyObject* py_read_config_entry(PyObject *, PyObject *args) +{ + long widget; + char* key; + if (!PyArg_ParseTuple(args, (char*)"ls:readConfigEntry", &widget, &key)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + QString k; + k.setAscii(key); + + QVariant entry = readConfigEntry(widget, k); + QString type; + type.setAscii(entry.typeName()); + + if (type == "Bool") + { + return Py_BuildValue((char*)"l", (int)entry.toBool()); + } + + bool isint = false; + int i = entry.toInt(&isint); + if (isint) + { + return Py_BuildValue((char*)"l", i); + } + + if (type == "QString") + { + return Py_BuildValue((char*)"s", entry.toString().ascii()); + } + // Add more types if needed + return NULL; +} + diff --git a/superkaramba/src/config_python.h b/superkaramba/src/config_python.h new file mode 100644 index 0000000..c22a032 --- /dev/null +++ b/superkaramba/src/config_python.h @@ -0,0 +1,138 @@ +/**************************************************************************** +* config_python.h - Functions for config python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef CONFIG_PYTHON_H +#define CONFIG_PYTHON_H + +/** Config/addMenuConfigOption +* +* SYNOPSIS +* long addMenuConfigOption(widget, key, name) +* DESCRIPTION +* SuperKaramba supports a simplistic configuration pop-up menu. This menu +* appears when you right-click on a widget and choose Configure Theme. +* Basically, it allows you to have check-able entrys in the menu to allow +* the user to enable or disable features in your theme. +* +* Before you use any configuration menu stuff, you NEED to add a new +* callback to your script: +* +* def menuOptionChanged(widget, key, value): +* +* This will get called whenever a config menu option is changed. Now you +* can add items to the config menu: +* +* addMenuConfigOption(widget, String key, String name) +* +* Key is the name of a key value where the value will be saved +* automatically into the widget's config file. Name is the actual text that +* will show up in the config menu. +* +* For example, I could allow the user to enable or disable a clock showing +* up in my theme: +* +* karamba.addMenuConfigOption(widget, "showclock", "Display a clock") +* ARGUMENTS +* * long widget -- karamba +* * string key -- key for menu item +* * string name -- name of the graph to get +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_add_menu_config_option(PyObject *self, PyObject *args); + +/** Config/setMenuConfigOption +* +* SYNOPSIS +* long setMenuConfigOption(widget, key, value) +* DESCRIPTION +* This sets whether or not the given option is checked in the theme's +* Configure Theme menu. Value should be 0 if key should not be checked and +* 1 if key should be checked. +* +* See addMenuConfigOption for a more detailed explanation. +* ARGUMENTS +* * long widget -- karamba +* * string key -- key for menu item +* * int value -- 1 if checked +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_set_menu_config_option(PyObject *self, PyObject *args); + +/** Config/readMenuConfigOption +* +* SYNOPSIS +* long readMenuConfigOption(widget, key) +* DESCRIPTION +* This returns whether or not the given option is checked in the theme's +* Configure Theme menu. +* +* See addMenuConfigOption for a more detailed explanation. +* ARGUMENTS +* * long widget -- karamba +* * string key -- key for menu item +* RETURN VALUE +* 0 is returned if it is not checked and 1 is returned if it is. +*/ +PyObject* py_read_menu_config_option(PyObject *self, PyObject *args); + +/** Config/writeConfigEntry +* +* SYNOPSIS +* long writeConfigEntry(widget, key, value) +* DESCRIPTION +* SuperKaramba automatically supports configuration files for each theme. +* These files will be saved in /your/home/dir/.superkaramba/ and will be +* named themenamerc where themename is the name of the theme. +* +* This function writes an entry into the config file with the given key and +* value. +* +* For example, to save my favorite color, I would do +* karamba.writeConfigEntry(widget, "FavColor", "Red") +* ARGUMENTS +* * long widget -- karamba +* * string key -- key for config item +* * string value -- config value +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_write_config_entry(PyObject *self, PyObject *args); + +/** Config/readConfigEntry +* +* SYNOPSIS +* string|long readConfigEntry(widget, key, value) +* DESCRIPTION +* This function reads an entry from the config file with the given key. +* ARGUMENTS +* * long widget -- karamba +* * string key -- key for config item +* RETURN VALUE +* config value for key +*/ +PyObject* py_read_config_entry(PyObject *self, PyObject *args); + +#endif // CONFIG_PYTHON_H diff --git a/superkaramba/src/cpusensor.cpp b/superkaramba/src/cpusensor.cpp new file mode 100644 index 0000000..bc4b095 --- /dev/null +++ b/superkaramba/src/cpusensor.cpp @@ -0,0 +1,167 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include + +#ifdef __FreeBSD__ +#include +#include +#include +#include +#include +#endif + +#if defined(Q_OS_NETBSD) +#include +#include +#include +#endif + +#include "cpusensor.h" + +CPUSensor::CPUSensor( QString cpu, int interval ) : + Sensor(interval), userTicks(0), sysTicks(0), niceTicks(0), idleTicks(0) +{ + cpuNbr = cpu; + QRegExp rx("^\\d+$"); + if( rx.search( cpu.lower() ) == -1) + cpuNbr = ""; + cpuNbr = "cpu"+cpuNbr; + getCPULoad(); +} + +CPUSensor::~CPUSensor() +{ +} + +void CPUSensor::getTicks (long &u,long &s,long &n,long &i) +{ +#ifdef __FreeBSD__ + static long cp_time[CPUSTATES]; + + size_t size = sizeof(cp_time); + + /* get the cp_time array */ + if (sysctlbyname("kern.cp_time", &cp_time, &size, NULL, 0) != -1) { + u = cp_time[CP_USER]; + s = cp_time[CP_SYS] + cp_time[CP_INTR]; + n = cp_time[CP_NICE]; + i = cp_time[CP_IDLE]; + } +#else +#if defined(Q_OS_NETBSD) + static uint64_t cp_time[CPUSTATES]; + + size_t size = sizeof(cp_time); + + /* get the cp_time array */ + if (sysctlbyname("kern.cp_time", &cp_time, &size, NULL, 0) != -1) { + u = cp_time[CP_USER]; + s = cp_time[CP_SYS] + cp_time[CP_INTR]; + n = cp_time[CP_NICE]; + i = cp_time[CP_IDLE]; + } +#else + QFile file("/proc/stat"); + QString line; + if ( file.open(IO_ReadOnly | IO_Translate) ) + { + QTextStream t( &file ); // use a text stream + QRegExp rx( cpuNbr+"\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)"); + line = t.readLine(); + rx.search( line ); + while( (line = t.readLine()) !=0 && rx.cap(0) == "" ) + { + rx.search( line ); + } + //user + u = rx.cap(1).toLong(); + //nice + n = rx.cap(2).toLong(); + //system + s = rx.cap(3).toLong(); + //idle + i = rx.cap(4).toLong(); + file.close(); + } +#endif +#endif + else + { + u = 0; + s = 0; + n = 0; + i = 0; + } +} + +int CPUSensor::getCPULoad() +{ + long uTicks, sTicks, nTicks, iTicks; + + getTicks(uTicks, sTicks, nTicks, iTicks); + + const long totalTicks = ((uTicks - userTicks) + + (sTicks - sysTicks) + + (nTicks - niceTicks) + + (iTicks - idleTicks)); + + int load = (totalTicks == 0) ? 0 : (int) ( 100.0 * ( (uTicks+sTicks+nTicks) - (userTicks+sysTicks+niceTicks))/( totalTicks+0.001) + 0.5 ); + user = (totalTicks == 0) ? 0 : (int) ( 100.0 * ( uTicks - userTicks)/( totalTicks+0.001) + 0.5 ); + idle = (totalTicks == 0) ? 0 : (int) ( 100.0 * ( iTicks - idleTicks)/( totalTicks+0.001) + 0.5 ); + system = (totalTicks == 0) ? 0 : (int) ( 100.0 * ( sTicks - sysTicks)/( totalTicks+0.001) + 0.5 ); + nice = (totalTicks == 0) ? 0 : (int) ( 100.0 * ( nTicks - niceTicks)/( totalTicks+0.001) + 0.5 ); + + userTicks = uTicks; + sysTicks = sTicks; + niceTicks = nTicks; + idleTicks = iTicks; + + return load; +} + +void CPUSensor::update() +{ + SensorParams *sp; + Meter *meter; + QString format; + int load = getCPULoad(); + + QObjectListIt it( *objList ); + while (it != 0) + { + sp = (SensorParams*)(*it); + meter = sp->getMeter(); + format = sp->getParam( "FORMAT" ); + + if( format.length() == 0) + { + format = "%v"; + } + format.replace( QRegExp("%load", false), QString::number( load ) ); + format.replace( QRegExp("%user", false), QString::number( user ) ); + format.replace( QRegExp("%nice", false), QString::number( nice ) ); + format.replace( QRegExp("%idle", false), QString::number( idle ) ); + format.replace( QRegExp("%system", false), QString::number( system ) ); + format.replace( QRegExp("%v", false), QString::number( load ) ); + + meter->setValue( format ); + ++it; + } +} + +void CPUSensor::setMaxValue( SensorParams *sp ) +{ + Meter *meter; + meter = sp->getMeter(); + meter->setMax( 100 ); +} + +#include "cpusensor.moc" diff --git a/superkaramba/src/cpusensor.h b/superkaramba/src/cpusensor.h new file mode 100644 index 0000000..5b857f6 --- /dev/null +++ b/superkaramba/src/cpusensor.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef CPUSENSOR_H +#define CPUSENSOR_H +#include "sensor.h" + +#include +#include + +class CPUSensor : public Sensor +{ + Q_OBJECT +public: + CPUSensor( QString cpuNbr, int interval ); + ~CPUSensor(); + void update(); + void setMaxValue( SensorParams *sp ); + + int getCPULoad(); + +private: + long userTicks; + long sysTicks; + long niceTicks; + long idleTicks; + + int user; + int system; + int nice; + int idle; + + void getTicks (long &u,long &s,long &n,long &i); + QString cpuNbr; + +}; + +#endif // CPUSENSOR_H diff --git a/superkaramba/src/datesensor.cpp b/superkaramba/src/datesensor.cpp new file mode 100644 index 0000000..186f552 --- /dev/null +++ b/superkaramba/src/datesensor.cpp @@ -0,0 +1,129 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "datesensor.h" + +#include +DateSensor::DateSensor( int interval ) : Sensor( interval ) +{ + hidden = true; +} +DateSensor::~DateSensor() +{ +} + +void DateSensor::update() +{ + QDateTime qdt = QDateTime::currentDateTime(); + QString format; + SensorParams *sp; + Meter *meter; + + QObjectListIt it( *objList ); + while (it != 0) + { + sp = (SensorParams*)(*it); + meter = sp->getMeter(); + format = sp->getParam("FORMAT"); + + if (format.length() == 0 ) + { + format = "hh:mm"; + } + meter->setValue(qdt.toString(format)); + ++it; + } +} + +void DateSensor::slotCalendarDeleted() +{ + hidden = true; + cal = 0L; +} + + +DatePicker::DatePicker(QWidget *parent) + : QVBox( parent, 0, WType_TopLevel | WDestructiveClose | + WStyle_Customize | WStyle_StaysOnTop | WStyle_NoBorder ) +{ + setFrameStyle( QFrame::PopupPanel | QFrame::Raised ); + //KWin::setOnAllDesktops( handle(), true ); + picker = new KDatePicker(this); + picker->setCloseButton(true); + + /* name and icon for kicker's taskbar */ + //setCaption(i18n("Calendar")); + //setIcon(SmallIcon("date")); +} + +void DatePicker::keyReleaseEvent(QKeyEvent *e) +{ + QVBox::keyReleaseEvent(e); + if (e->key() == Qt::Key_Escape) + close(); +} + +void DateSensor::toggleCalendar(QMouseEvent *ev) +{ + QObjectListIt it(*objList); + while (it != 0) + { + SensorParams *sp = (SensorParams*)(*it); + Meter *meter = sp->getMeter(); + QString width = sp->getParam("CALWIDTH"); + QString height = sp->getParam("CALHEIGHT"); + + QRect rect(meter->getX(),meter->getY(),width.toInt(), height.toInt()); + if (rect.contains( ev->x(), ev->y() )) + { + if (hidden) + { + hidden = false; + cal = new DatePicker(0); + + connect(cal, SIGNAL(destroyed()), SLOT(slotCalendarDeleted())); + QPoint c = (QPoint(ev->x(), ev->y())); + + int w = cal->sizeHint().width(); + int h = cal->sizeHint().height(); + + // make calendar fully visible + QRect deskR = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(c)); + + + if (c.y()+h > deskR.bottom()) c.setY(deskR.bottom()-h-1); + if (c.x()+w > deskR.right()) c.setX(deskR.right()-w-1); + cal->move(c); + cal->show(); + + } + else + { + cal->close(); + } + } + + ++it; + } +} + +void DateSensor::mousePressEvent(QMouseEvent *ev) +{ + switch (ev->button()) + { + case QMouseEvent::LeftButton: + toggleCalendar(ev); + break; + default: + break; + } +} + + +#include "datesensor.moc" diff --git a/superkaramba/src/datesensor.h b/superkaramba/src/datesensor.h new file mode 100644 index 0000000..75db6e0 --- /dev/null +++ b/superkaramba/src/datesensor.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef DATESENSOR_H +#define DATESENSOR_H +#include "sensor.h" +#include "sensorparams.h" +#include +#include +#include + +class DatePicker : public QVBox +{ +public: + DatePicker(QWidget*); +private: + KDatePicker *picker; + void keyReleaseEvent(QKeyEvent *e); +}; + +class DateSensor : public Sensor +{ +Q_OBJECT +public: + DateSensor( int interval ); + ~DateSensor(); + + void toggleCalendar(QMouseEvent *ev); + void mousePressEvent(QMouseEvent *ev); + void update(); + +protected slots: + void slotCalendarDeleted(); + +private: + bool hidden; + DatePicker* cal; + +}; + +#endif // SENSOR_H diff --git a/superkaramba/src/dcopinterface.h b/superkaramba/src/dcopinterface.h new file mode 100644 index 0000000..665187d --- /dev/null +++ b/superkaramba/src/dcopinterface.h @@ -0,0 +1,37 @@ +/*************************************************************************** + * Copyright (C) 2004 by Petri Damsten * + * petri.damsten@iki.fi * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef DCOPINTERFACE_H +#define DCOPINTERFACE_H + +#include + +class dcopIface : virtual public DCOPObject +{ + K_DCOP +public: + +k_dcop: + virtual ASYNC openTheme(QString file) = 0; + virtual ASYNC openNamedTheme(QString file, QString name, bool is_sub_theme) = 0; + virtual ASYNC closeTheme(QString name) = 0; + virtual ASYNC quit() = 0; + virtual ASYNC hideSystemTray(bool hide) = 0; + virtual ASYNC showThemeDialog() = 0; + + virtual int themeAdded(QString appId, QString file) = 0; + virtual ASYNC themeClosed(QString appId, QString file, int instance) = 0; + virtual ASYNC themeNotify(QString name, QString text) = 0; + virtual ASYNC setIncomingData(QString name, QString obj) = 0; + virtual bool isMainKaramba() = 0; + +}; + +#endif // DCOPINTERFACE_H diff --git a/superkaramba/src/disksensor.cpp b/superkaramba/src/disksensor.cpp new file mode 100644 index 0000000..b8b9b96 --- /dev/null +++ b/superkaramba/src/disksensor.cpp @@ -0,0 +1,175 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "disksensor.h" + +#include +#include +#include +#include +#include +#include + +DiskSensor::DiskSensor( int msec ) : Sensor( msec ) +{ + connect(&ksp, SIGNAL(receivedStdout(KProcess *, char *, int )), + this,SLOT(receivedStdout(KProcess *, char *, int ))); + connect(&ksp, SIGNAL(processExited(KProcess *)), + this,SLOT(processExited( KProcess * ))); + + // update values on startup + ksp.clearArguments(); + ksp << "df"; + ksp.start( KProcIO::Block,KProcIO::Stdout); + init = 1; +} +DiskSensor::~DiskSensor() +{} + +long DiskSensor::getFreeSpace(QString mntPt) const +{ + QRegExp rx( "^\\S*\\s*\\d+\\s+\\d+\\s+(\\d+)"); + rx.search(mntMap[mntPt]); + return rx.cap(1).toLong(); +} + +long DiskSensor::getUsedSpace(QString mntPt) const +{ + QRegExp rx( "^\\S*\\s*\\d+\\s+(\\d+)\\s+\\d+"); + rx.search(mntMap[mntPt]); + return rx.cap(1).toLong(); +} + +long DiskSensor::getTotalSpace(QString mntPt) const +{ + + QRegExp rx( "^\\S*\\s*(\\d+)\\s+\\d+\\s+\\d+"); + rx.search(mntMap[mntPt]); + + return rx.cap(1).toLong(); + +} + +int DiskSensor::getPercentUsed(QString mntPt) const +{ + QRegExp rx( "\\s+(\\d+)%\\s+"); + rx.search(mntMap[mntPt]); + return rx.cap(1).toInt(); +} + +int DiskSensor::getPercentFree(QString mntPt) const +{ + return ( 100 - getPercentUsed( mntPt ) ); +} + +void DiskSensor::receivedStdout(KProcess *, char *buffer, int len ) +{ + + buffer[len] = 0; + sensorResult += QString( QCString(buffer) ); + +} + +void DiskSensor::processExited(KProcess *) +{ + QStringList stringList = QStringList::split('\n',sensorResult); + sensorResult = ""; + QStringList::Iterator it = stringList.begin(); + //QRegExp rx( "^(/dev/).*(/\\S*)$"); + QRegExp rx( ".*\\s+(/\\S*)$"); + + while( it != stringList.end()) + { + rx.search( *it ); + if ( !rx.cap(0).isEmpty()) + { + mntMap[rx.cap(1)] = *it; + } + it++; + } + stringList.clear(); + + QString format; + QString mntPt; + SensorParams *sp; + Meter *meter; + + QObjectListIt lit( *objList ); + while (lit != 0) + { + sp = (SensorParams*)(*lit); + meter = sp->getMeter(); + format = sp->getParam("FORMAT"); + mntPt = sp->getParam("MOUNTPOINT"); + if (mntPt.length() == 0) + mntPt="/"; + + if (format.length() == 0 ) + { + format = "%u"; + } + format.replace( QRegExp("%fp", false),QString::number(getPercentFree(mntPt))); + format.replace( QRegExp("%fg",false), + QString::number(getFreeSpace(mntPt)/(1024*1024))); + format.replace( QRegExp("%fkb",false), + QString::number(getFreeSpace(mntPt)*8) ); + format.replace( QRegExp("%fk",false), + QString::number(getFreeSpace(mntPt)) ); + format.replace( QRegExp("%f", false),QString::number(getFreeSpace(mntPt)/1024)); + + format.replace( QRegExp("%up", false),QString::number(getPercentUsed(mntPt))); + format.replace( QRegExp("%ug",false), + QString::number(getUsedSpace(mntPt)/(1024*1024))); + format.replace( QRegExp("%ukb",false), + QString::number(getUsedSpace(mntPt)*8) ); + format.replace( QRegExp("%uk",false), + QString::number(getUsedSpace(mntPt)) ); + format.replace( QRegExp("%u", false),QString::number(getUsedSpace(mntPt)/1024)); + + format.replace( QRegExp("%tg",false), + QString::number(getTotalSpace(mntPt)/(1024*1024))); + format.replace( QRegExp("%tkb",false), + QString::number(getTotalSpace(mntPt)*8)); + format.replace( QRegExp("%tk",false), + QString::number(getTotalSpace(mntPt))); + format.replace( QRegExp("%t", false),QString::number(getTotalSpace(mntPt)/1024)); + meter->setValue(format); + ++lit; + } + if ( init == 1 ) + { + emit initComplete(); + init = 0; + } +} + +void DiskSensor::update() +{ + ksp.clearArguments(); + ksp << "df"; + ksp.start( KProcIO::NotifyOnExit,KProcIO::Stdout); +} + +void DiskSensor::setMaxValue( SensorParams *sp ) +{ + Meter *meter; + meter = sp->getMeter(); + const QString mntPt = sp->getParam( "MOUNTPOINT" ); + + QString f; + f = sp->getParam("FORMAT"); + if( f == "%fp" || f == "%up" ) + meter->setMax( 100 ); + else + meter->setMax( getTotalSpace( mntPt ) / 1024 ); +} + + + +#include "disksensor.moc" diff --git a/superkaramba/src/disksensor.h b/superkaramba/src/disksensor.h new file mode 100644 index 0000000..e35b9d8 --- /dev/null +++ b/superkaramba/src/disksensor.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef DISKSENSOR_H +#define DISKSENSOR_H +#include "sensor.h" +#include +#include +#include +#include +#include +#include +class DiskSensor : public Sensor +{ +Q_OBJECT +public: + DiskSensor(int msec ); + ~DiskSensor(); + void update(); + void setMaxValue( SensorParams *sp ); + +private: + long getFreeSpace(QString mntPt) const; + long getUsedSpace(QString mntPt) const; + long getTotalSpace(QString mntPt) const; + int getPercentUsed(QString mntPt) const; + int getPercentFree(QString mntPt) const; + + KShellProcess ksp; + QString sensorResult; + + QMap mntMap; + QStringList stringList; + + int init; + +private slots: + void receivedStdout(KProcess *, char *buffer, int); + void processExited(KProcess *); + +signals: + void initComplete(); + +}; +#endif // DISKSENSOR_H diff --git a/superkaramba/src/graph.cpp b/superkaramba/src/graph.cpp new file mode 100644 index 0000000..c028aea --- /dev/null +++ b/superkaramba/src/graph.cpp @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "graph.h" +#include + +Graph::Graph(karamba* k, int x, int y, int w, int h, int nbrPts): + Meter(k, x, y, w, h), lastValue(0) +{ + + nbrPoints = (nbrPts==0)? 50:nbrPts ; + ptPtr = 0; + values = new int[nbrPoints]; + for(int i = 0; i < nbrPoints; i++) + values[i] = 0; + minValue = 0; + maxValue = 100; +} + +Graph::~Graph() +{ + delete[] values; +} + +void Graph::setValue( long v) +{ + if( v > maxValue) + { + // maxValue = v; + v = maxValue; + } + if( v < minValue) + { + //minValue = v; + v = minValue; + } + lastValue = v; + values[ptPtr] = (int) (v / (maxValue + 0.0001) * getHeight()); + ptPtr = (ptPtr + 1) % nbrPoints; +} + +void Graph::setValue( QString v ) +{ + setValue((long)(v.toDouble() + 0.5)); +} + +void Graph::mUpdate(QPainter *p) +{ + if (hidden == 0) + { + double step = (getWidth() / (nbrPoints-1.001)); + double xPos = 0; + double nextXPos = 0; + p->setPen(color); + for (int i = 0; i < nbrPoints - 1 ; i ++) + { + nextXPos = xPos + step; + p->drawLine(getX() + (int)xPos, getY()+getHeight() - + (int) values[(ptPtr+i) % nbrPoints] , + getX() + (int)nextXPos, getY()+getHeight() - + (int) values[(ptPtr + i +1) % nbrPoints] ); + xPos = nextXPos; + } + } +} + +#include "graph.moc" diff --git a/superkaramba/src/graph.h b/superkaramba/src/graph.h new file mode 100644 index 0000000..626b569 --- /dev/null +++ b/superkaramba/src/graph.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef GRAPH_H +#define GRAPH_H + +#include "meter.h" +#include +#include + +class Graph : public Meter +{ +Q_OBJECT + +public: + Graph(karamba* k, int ix, int iy, int iw, int ih, int nbrPoints); + Graph(); + ~Graph(); + + void setValue( long ); + long getValue() { return lastValue; }; + void setValue( QString ); + void mUpdate( QPainter * ); + +private: + int lastValue; + int* values; + int nbrPoints; + int ptPtr; // points to the array position +}; + +#endif // GRAPH_H diff --git a/superkaramba/src/graph_python.cpp b/superkaramba/src/graph_python.cpp new file mode 100644 index 0000000..1ef6e73 --- /dev/null +++ b/superkaramba/src/graph_python.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +* graph_python.h - Functions for graph python api +* +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "meter.h" +#include "meter_python.h" +#include "graph_python.h" + +PyObject* py_createGraph(PyObject *, PyObject *args) +{ + long widget, x, y, w, h, points; + + if (!PyArg_ParseTuple(args, (char*)"llllll", &widget, &x, &y, &w, &h, &points)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + Graph *tmp = + new Graph((karamba*)widget, (int)x, (int)y, (int)w, (int)h, (int)points); + ((karamba*)widget)->meterList->append(tmp); + return (Py_BuildValue((char*)"l", (long)tmp)); +} + +PyObject* py_deleteGraph(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "Graph")) + return NULL; + + ((karamba*)widget)->deleteMeterFromSensors((Meter*)meter); + return Py_BuildValue((char*)"l", + ((karamba*)widget)->meterList->removeRef((Meter*)meter)); +} + +PyObject* py_getThemeGraph(PyObject *self, PyObject *args) +{ + return py_getThemeMeter(self, args, "Graph"); +} + +PyObject* py_getGraphSize(PyObject *self, PyObject *args) +{ + return py_getSize(self, args, "Graph"); +} + +PyObject* py_resizeGraph(PyObject *self, PyObject *args) +{ + return py_resize(self, args, "Graph"); +} + +PyObject* py_getGraphPos(PyObject *self, PyObject *args) +{ + return py_getPos(self, args, "Graph"); +} + +PyObject* py_moveGraph(PyObject *self, PyObject *args) +{ + return py_move(self, args, "Graph"); +} + +PyObject* py_hideGraph(PyObject *self, PyObject *args) +{ + return py_hide(self, args, "Graph"); +} + +PyObject* py_showGraph(PyObject *self, PyObject *args) +{ + return py_show(self, args, "Graph"); +} + +PyObject* py_getGraphMinMax(PyObject *self, PyObject *args) +{ + return py_getMinMax(self, args, "Graph"); +} + +PyObject* py_setGraphMinMax(PyObject *self, PyObject *args) +{ + return py_setMinMax(self, args, "Graph"); +} + +PyObject* py_getGraphValue(PyObject *self, PyObject *args) +{ + return py_getValue(self, args, "Graph"); +} + +PyObject* py_setGraphValue(PyObject *self, PyObject *args) +{ + return py_setValue(self, args, "Graph"); +} + +PyObject* py_getGraphSensor(PyObject *self, PyObject *args) +{ + return py_getSensor(self, args, "Graph"); +} + +PyObject* py_setGraphSensor(PyObject *self, PyObject *args) +{ + return py_setSensor(self, args, "Graph"); +} + +PyObject* py_getGraphColor(PyObject *self, PyObject *args) +{ + return py_getColor(self, args, "Graph"); +} + +PyObject* py_setGraphColor(PyObject *self, PyObject *args) +{ + return py_setColor(self, args, "Graph"); +} + + diff --git a/superkaramba/src/graph_python.h b/superkaramba/src/graph_python.h new file mode 100644 index 0000000..e635c07 --- /dev/null +++ b/superkaramba/src/graph_python.h @@ -0,0 +1,289 @@ +/**************************************************************************** +* graph_python.cpp - Functions for graph python api +* +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef GRAPH_PYTHON_H +#define GRAPH_PYTHON_H + +/** Graph/createGraph +* +* SYNOPSIS +* long createGraph(widget, x, y, w, h, points) +* DESCRIPTION +* This creates a graph at x,y with width and height w,h. +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * long w -- width +* * long h -- height +* * long points -- Number of points in graph +* RETURN VALUE +* Pointer to new graph meter +*/ +PyObject* py_createGraph(PyObject *self, PyObject *args); + +/** Graph/deleteGraph +* +* SYNOPSIS +* long deleteGraph(widget, graph) +* DESCRIPTION +* This deletes graph. +* ARGUMENTS +* * long widget -- karamba +* * long widget -- graph +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_deleteGraph(PyObject *self, PyObject *args); + +/** Graph/getThemeGraph +* +* SYNOPSIS +* long getThemeGraph(widget, name) +* DESCRIPTION +* You can reference graph in your python code that was created in the +* theme file. Basically, you just add a NAME= value to the GRAPH line in +* the .theme file. Then if you want to use that object, instead of calling +* createGraph, you can call this function. +* +* The name you pass to the function is the same one that you gave it for +* the NAME= parameter in the .theme file. +* ARGUMENTS +* * long widget -- karamba +* * string name -- name of the graph to get +* RETURN VALUE +* Pointer to graph +*/ +PyObject* py_getThemeGraph(PyObject *self, PyObject *args); + +/** Graph/getGraphSize +* +* SYNOPSIS +* tuple getGraphSize(widget, graph) +* DESCRIPTION +* Given a reference to a graph object, this will return a tuple +* containing the height and width of a graph object. +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* RETURN VALUE +* size +*/ +PyObject* py_getGraphSize(PyObject *self, PyObject *args); + +/** Graph/resizeGraph +* +* SYNOPSIS +* long resizeGraph(widget, graph, w, h) +* DESCRIPTION +* This will resize graph to new height and width. +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* * long w -- new width +* * long h -- new height +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_resizeGraph(PyObject *self, PyObject *args); + +/** Graph/getGraphPos +* +* SYNOPSIS +* tuple getGraphPos(widget, graph) +* DESCRIPTION +* Given a reference to a graph object, this will return a tuple +* containing the x and y coordinate of a graph object. +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* RETURN VALUE +* pos +*/ +PyObject* py_getGraphPos(PyObject *self, PyObject *args); + +/** Graph/moveGraph +* +* SYNOPSIS +* long moveGraph(widget, graph, x, y) +* DESCRIPTION +* This will move graph to new x and y coordinates. +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* * long x -- x coordinate +* * long y -- y coordinate +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_moveGraph(PyObject *self, PyObject *args); + +/** Graph/hideGraph +* +* SYNOPSIS +* long hideGraph(widget, graph) +* DESCRIPTION +* This hides an graph. In other words, during subsequent calls to +* widgetUpdate(), this graph will not be drawn. +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_hideGraph(PyObject *self, PyObject *args); + +/** Graph/showGraph +* +* SYNOPSIS +* long showGraph(widget, graph) +* DESCRIPTION +* This shows an graph. In other words, during subsequent calls to +* widgetUpdate(), this graph will be drawn. +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_showGraph(PyObject *self, PyObject *args); + +/** Graph/getGraphValue +* +* SYNOPSIS +* long getGraphValue(widget, graph) +* DESCRIPTION +* Returns current graph value. +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* RETURN VALUE +* value +*/ +PyObject* py_getGraphValue(PyObject *self, PyObject *args); + +/** Graph/setGraphValue +* +* SYNOPSIS +* long setGraphValue(widget, graph, value) +* DESCRIPTION +* Sets current graph value. +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* * long value -- new value +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setGraphValue(PyObject *self, PyObject *args); + +/** Graph/getGraphMinMax +* +* SYNOPSIS +* tuple getGraphMinMax(widget, graph) +* DESCRIPTION +* Returns current graph value. +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* RETURN VALUE +* min & max +*/ +PyObject* py_getGraphMinMax(PyObject *self, PyObject *args); + +/** Graph/setGraphMinMax +* +* SYNOPSIS +* long setGraphMinMax(widget, graph, min, max) +* DESCRIPTION +* Returns current graph value. +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* * long min -- min value +* * long max -- max value +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setGraphMinMax(PyObject *self, PyObject *args); + +/** Graph/getGraphSensor +* +* SYNOPSIS +* string getGraphSensor(widget, graph) +* DESCRIPTION +* Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* RETURN VALUE +* sensor string +*/ +PyObject* py_getGraphSensor(PyObject *self, PyObject *args); + +/** Graph/setGraphSensor +* +* SYNOPSIS +* long setGraphSensor(widget, graph, sensor) +* DESCRIPTION +* Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* * string sensor -- new sensor as in theme files +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setGraphSensor(PyObject *self, PyObject *args); + +/** Graph/getGraphColor +* +* SYNOPSIS +* tuple getGraphColor(widget, graph) +* DESCRIPTION +* Get current graph color +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* RETURN VALUE +* (red, green, blue) +*/ +PyObject* py_getGraphColor(PyObject *self, PyObject *args); + +/** Graph/setGraphColor +* +* SYNOPSIS +* tuple setGraphColor(widget, graph, red, green, blue) +* DESCRIPTION +* Set current graph color +* ARGUMENTS +* * long widget -- karamba +* * long graph -- pointer to graph +* * long red -- red component of color +* * long green -- green component of color +* * long blue -- blue component of color +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setGraphColor(PyObject *self, PyObject *args); + +#endif // GRAPH_PYTHON_H diff --git a/superkaramba/src/imagelabel.cpp b/superkaramba/src/imagelabel.cpp new file mode 100644 index 0000000..9959e8b --- /dev/null +++ b/superkaramba/src/imagelabel.cpp @@ -0,0 +1,632 @@ +/**************************************************************************** +* imagelabel.cpp - ImageLabel meter +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "karambaapp.h" +#include "imagelabel.h" + +// Effect +Effect::Effect(ImageLabel* img, int msec) : + myImage(img) +{ + if (msec > 0) + { + // remove the effect after the given time + //QTimer::singleShot (millisec, myImage, SLOT(slotEffectExpired())); + //timer -> changeInterval(millisec); + millisec = msec; + } + else + { + millisec = msec; + } +} + +Effect::~Effect() +{ +} + +void Effect::startTimer() +{ + if (millisec > 0) + { + QTimer::singleShot (millisec, myImage, SLOT(slotEffectExpired())); + millisec = 0; + } +} + +// Intensity +Intensity::Intensity(ImageLabel* img, float r, int millisec) : + Effect(img, millisec) +{ + ratio = r; + ratio = (ratio > 1) ? 1 : ratio; + ratio = (ratio < -1) ? -1 : ratio; +} + +KPixmap Intensity::apply(KPixmap pixmap) +{ + return KPixmapEffect::intensity(pixmap, ratio); +} + +// ChannelIntensity +ChannelIntensity::ChannelIntensity(ImageLabel* img, float r, QString c, + int millisec) : + Effect(img, millisec) +{ + ratio = r; + ratio = (ratio > 1) ? 1 : ratio; + ratio = (ratio < -1) ? -1 : ratio; + + channel = 0; + if (c.find("red", 0 , false)) + { + channel = 0; + } + else if (c.find("green", 0, false)) + { + channel = 1; + } + else if (c.find("blue", 0, false)) + { + channel = 2; + } +} + +KPixmap ChannelIntensity::apply(KPixmap pixmap) +{ + return KPixmapEffect::channelIntensity(pixmap, ratio, + (KPixmapEffect::RGBComponent)channel); +} + +// ToGray +ToGray::ToGray(ImageLabel* img, int millisec) : Effect(img, millisec) +{ +} + +KPixmap ToGray::apply(KPixmap pixmap) +{ + return KPixmapEffect::toGray(pixmap); +} + +/***********************************************************************/ + +ImageLabel::ImageLabel(karamba* k, int ix,int iy,int iw,int ih) : + Meter(k, ix,iy,iw,ih), zoomed(false), rollover(false) +{ + background = 0; + cblend = 0; + //scaleMat.reset(); + //rotMat.reset(); + scale_w = 1; + scale_h = 1; + rot_angle = 0; + + doScale = false; + doRotate = false; + + imageEffect = 0; +} + +ImageLabel::ImageLabel(karamba* k) : + Meter(k), zoomed(false), rollover(false) +{ + cblend = 0; + background = 0; +} + +ImageLabel::~ImageLabel() +{ + if (imageEffect != 0) + { + delete imageEffect; + imageEffect = 0; + } + if(!old_tip_rect.isNull()) + { + QToolTip::remove(m_karamba, old_tip_rect); + } +} + +void ImageLabel::setValue(long v) +{ + setValue( QString::number( v ) ); +} + +void ImageLabel::show() +{ + Meter::show(); + setEnabled(true); +} + +void ImageLabel::hide() +{ + Meter::hide(); + setEnabled(false); +} + +void ImageLabel::rotate(int deg) +{ + doRotate = !(deg == 0); + + rot_angle = deg; + + applyTransformations(); +} + +void ImageLabel::scale(int w, int h) +{ + doScale = !(w == realpixmap.width() && h == realpixmap.height()); + + scale_w = w; + scale_h = h; + + applyTransformations(); +} + +void ImageLabel::smoothScale(int w, int h) +{ + doScale = !(w == realpixmap.width() && h == realpixmap.height()); + + scale_w = w; + scale_h = h; + + applyTransformations(true); + +// double widthFactor = ((double)w) / ((double)realpixmap.width()); +// double heightFactor = ((double)h) / ((double)realpixmap.height()); + +// pixmap.convertFromImage(realpixmap.convertToImage().smoothScale(w, h)); + +// setWidth(pixmap.width()); +// setHeight(pixmap.height()); + +} + +void ImageLabel::removeImageTransformations() +{ + doScale = false; + doRotate = false; + + scale_w = 1; + scale_h = 1; + rot_angle = 0; + pixmap = realpixmap; +} + +void ImageLabel::applyTransformations(bool useSmoothScale) +{ + pixmap = realpixmap; + if (doRotate) + { + // KDE and QT seem to miss a high quality image rotation + QWMatrix rotMat; + rotMat.rotate(rot_angle); + pixmap = pixmap.xForm(rotMat); + } + if (doScale) + { + if (m_karamba -> useSmoothTransforms() || useSmoothScale) + { + pixmap.convertFromImage( + pixmap.convertToImage().smoothScale(scale_w, scale_h)); + } + else + { + double widthFactor = ((double)scale_w) / ((double)pixmap.width()); + double heightFactor = ((double)scale_h) / ((double)pixmap.height()); + QWMatrix scaleMat; + scaleMat.scale(widthFactor, heightFactor); + pixmap = pixmap.xForm(scaleMat); + } + } + if (imageEffect != 0) + { + pixmap = imageEffect -> apply(pixmap); + } + setWidth(pixmap.width()); + setHeight(pixmap.height()); +} + +void ImageLabel::slotCopyResult(KIO::Job* job) +{ + QString tempFile = ((KIO::FileCopyJob*)job)->destURL().path(); + if(job->error() == 0) + { + setValue(tempFile); + imagePath = ((KIO::FileCopyJob*)job)->srcURL().path(); + emit pixmapLoaded(); + } + else + { + qWarning("Error downloading (%s): %s", job->errorText().ascii(), + tempFile.ascii()); + } + KIO::NetAccess::removeTempFile(tempFile); +} + +void ImageLabel::setValue(QString fn) +{ + // use the first line + QStringList sList = QStringList::split( "\n", fn ); + QString fileName = *sList.begin(); + KURL url(fileName); + QRegExp rx("^[a-zA-Z]{1,5}:/",false); + bool protocol = (rx.search(fileName)!=-1)?true:false; + QPixmap pm; + + if(protocol && url.isLocalFile() == false) + { + KTempFile tmpFile; + KIO::FileCopyJob* copy = KIO::file_copy(fileName, tmpFile.name(), 0600, + true, false, false); + connect(copy, SIGNAL(result(KIO::Job*)), + this, SLOT(slotCopyResult(KIO::Job*))); + return; + } + else + { + if(m_karamba->theme().isThemeFile(fileName)) + { + QByteArray ba = m_karamba->theme().readThemeFile(fileName); + pm.loadFromData(ba); + } + else + { + pm.load(fileName); + } + imagePath = fileName; + } + setValue(pm); +} + +//Matthew Kay: a new version of setValue to be used by createTaskIcon() +/** + * set the internal pixmap of this image to the given QPixmap pix + */ +void ImageLabel::setValue(QPixmap& pix) +{ + realpixmap = KPixmap(pix); + pixmap = realpixmap; + setWidth(pixmap.width()); + setHeight(pixmap.height()); + + pixmapWidth = pixmap.width(); + pixmapHeight = pixmap.height(); + rect_off = QRect(getX(),getY(),pixmapWidth,pixmapHeight); +} + +void ImageLabel::mUpdate(QPainter* p, int backgroundUpdate) +{ + if (backgroundUpdate == 1) + { + //only draw image if not hidden + if (hidden == 0) + { + if (cblend == 0) + //draw the pixmap + p->drawPixmap(getX(),getY(),pixmap); + else + { + //Blend this image with a color + + QImage image = pixmap.convertToImage(); + + QImage result = KImageEffect::blend(QColor(255,0,0), image, 0.5f); + p->drawImage(getX(),getY(),result); + + //p->drawRect(boundingBox); + } + } + // start Timer + if (imageEffect != 0) + { + imageEffect -> startTimer(); + } + } +} + +void ImageLabel::mUpdate(QPainter* p) +{ + //only draw image if not hidden + if (hidden == 0 && background == 0) + { + if (cblend == 0) + { + //draw the pixmap + p->drawPixmap(getX(),getY(),pixmap); + } + else + { + //Blend this image with a color + + QImage image = pixmap.convertToImage(); + + QImage result = KImageEffect::blend(QColor(255,0,0), image, 0.5f); + p->drawImage(getX(),getY(),result); + + //p->drawRect(boundingBox); + } + } + // start Timer + if (imageEffect != 0) + { + imageEffect -> startTimer(); + } +} + +bool ImageLabel::click(QMouseEvent* e) +{ + if (getBoundingBox().contains(e -> x(), e -> y()) && isEnabled()) + { + QString program; + if (e -> button() == Qt::LeftButton) + { + program = leftButtonAction; + } + else if (e -> button() == Qt::MidButton) + { + program = middleButtonAction; + } + else if (e -> button() == Qt::RightButton) + { + program = rightButtonAction; + } + + if( !program.isEmpty() ) + { + KRun::runCommand(program); + } + else + { + return true; + } + } + return false; +} + +void ImageLabel::parseImages(QString fn, QString fn_roll, int _xoff, + int _yoff, int _xon, int _yon) +{ + //fn = filename; + //fn_roll = filename_roll; + + xoff = _xoff; + yoff = _yoff; + xon = _xon; + yon = _yon; + + // use the first line + QStringList sList = QStringList::split( "\n", fn ); + QString fileName = *sList.begin(); + QFileInfo fileInfo( fileName ); + QString path; + + QRegExp rx("^http://",false); + bool fileOnNet = (rx.search(fileName)!=-1)?true:false; + + + if( fileInfo.isRelative() && !fileOnNet ) + { + path = m_karamba->theme().path() + "/" + fileName; + } + else + { + path = fileName; + } + + if ( fileOnNet ) + { + QString tmpFile; +#if defined(KDE_3_2) + if(KIO::NetAccess::download(KURL(path), tmpFile, karambaApp->parentWindow())) +#else + if(KIO::NetAccess::download(KURL(path), tmpFile)) +#endif + { + pixmap_off = KPixmap(tmpFile); + KIO::NetAccess::removeTempFile(tmpFile); + qDebug( "Downloaded: %s to %s", path.ascii(), tmpFile.ascii() ); + } + else + { + qDebug( "Error Downloading: %s", path.ascii()); + } + } + else + { + pixmap_off = KPixmap( path ); + } + + pixmapOffWidth = pixmap.width(); + pixmapOffHeight = pixmap.height(); + + rect_off = QRect(xoff,yoff,pixmapWidth,pixmapHeight); +///////////////////////////// + if (fn_roll.isEmpty()) + return; + + rollover=true; + sList = QStringList::split( "\n", fn_roll ); + fileName = *sList.begin(); + fileInfo = QFileInfo( fileName ); + + fileOnNet = (rx.search(fileName)!=-1)?true:false; + + + if( fileInfo.isRelative() && !fileOnNet ) + { + path = m_karamba->theme().path() + "/" + fileName; + } + else + { + path = fileName; + } + + if ( fileOnNet ) + { + QString tmpFile; +#if defined(KDE_3_2) + if(KIO::NetAccess::download(KURL(path), tmpFile, karambaApp->parentWindow())) +#else + if(KIO::NetAccess::download(KURL(path), tmpFile)) +#endif + { + pixmap_on = KPixmap(tmpFile); + KIO::NetAccess::removeTempFile(tmpFile); + qDebug( "Downloaded: %s to %s", path.ascii(), tmpFile.ascii()); + } + else + { + qDebug( "Error Downloading: %s", path.ascii()); + } + } + else + { + pixmap_on = KPixmap( path ); + } + pixmapOnWidth = pixmap_on.width(); + pixmapOnHeight = pixmap_on.height(); + + rect_on = QRect(xon,yon,pixmapOnWidth,pixmapOnHeight); +} + +void ImageLabel::setBackground(int b) +{ + background = b; +} + +void ImageLabel::rolloverImage(QMouseEvent *e) +{ + if (!rollover) + return; + + if (zoomed) + { + if (!rect_off.contains(e->pos())) + { + // rollover the image to the zoomed image + //setValue(fn_roll); + setX(xoff); + setY(yoff); + pixmap = pixmap_off; + pixmapWidth = pixmapOffWidth; + pixmapHeight = pixmapOffHeight; + zoomed = false; + m_karamba->step(); + } + } + else + { + if (rect_off.contains(e->pos())) + { + // rollover the image to the zoomed image + //setValue(fn_roll); + setX(xon); + setY(yon); + pixmap = pixmap_on; + pixmapWidth = pixmapOnWidth; + pixmapHeight = pixmapOnHeight; + zoomed = true; + m_karamba->step(); + } + } +} + +void ImageLabel::setTooltip(QString txt) +{ + QRect rect(getX(),getY(),pixmapWidth,pixmapHeight); + QToolTip::add(m_karamba, rect, txt); + old_tip_rect = QRect(rect.topLeft(), rect.bottomRight()); +} + + +void ImageLabel::removeEffects() +{ + if (imageEffect != 0) + { + delete imageEffect; + imageEffect = 0; + } + applyTransformations(); +} + +void ImageLabel::intensity(float ratio, int millisec) +{ + if (imageEffect != 0) + { + delete imageEffect; + imageEffect = 0; + } + //KPixmapEffect::intensity(pixmap, ratio); + imageEffect = new Intensity(this, ratio, millisec); + applyTransformations(); +} + +void ImageLabel::channelIntensity(float ratio, QString channel, int millisec) +{ + if (imageEffect != 0) + { + delete imageEffect; + imageEffect = 0; + } + //KPixmapEffect::channelIntensity(pixmap, ratio, rgbChannel); + imageEffect = new ChannelIntensity(this, ratio, channel, millisec); + applyTransformations(); +} + +void ImageLabel::toGray(int millisec) +{ + if (imageEffect != 0) + { + delete imageEffect; + imageEffect = 0; + } + //KPixmapEffect::toGray(pixmap); + imageEffect = new ToGray(this, millisec); + applyTransformations(); +} + +void ImageLabel::slotEffectExpired() +{ + removeEffects(); + m_karamba -> externalStep(); +} + +void ImageLabel::attachClickArea(QString leftMouseButton, + QString middleMouseButton, + QString rightMouseButton) +{ + leftButtonAction = leftMouseButton; + middleButtonAction = middleMouseButton; + rightButtonAction = rightMouseButton; +} + +#include "imagelabel.moc" diff --git a/superkaramba/src/imagelabel.h b/superkaramba/src/imagelabel.h new file mode 100644 index 0000000..ff2a7ec --- /dev/null +++ b/superkaramba/src/imagelabel.h @@ -0,0 +1,191 @@ +/**************************************************************************** +* imagelabel.h - ImageLabel meter +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef IMAGELABEL_H +#define IMAGELABEL_H + +#include "meter.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "karamba.h" + +class ImageLabel; +class KIO::CopyJob; + +// Abstract Effects Baseclass +class Effect : public QObject +{ + +Q_OBJECT + +public: + Effect(ImageLabel*, int millisec); + + virtual ~Effect(); + + virtual KPixmap apply(KPixmap pixmap) = 0; + + void startTimer(); + +protected: + ImageLabel* myImage; + + int millisec; +}; + +// Intensity +class Intensity : public Effect +{ +public: + Intensity(ImageLabel*, float r, int millisec); + + KPixmap apply(KPixmap pixmap); + +private: + float ratio; +}; + + +// ChannelIntensity +class ChannelIntensity : public Effect +{ +public: + ChannelIntensity(ImageLabel*, float r, QString c, int millisec); + + KPixmap apply(KPixmap pixmap); + +private: + float ratio; + int channel; +}; + +// ToGray +class ToGray : public Effect +{ +public: + ToGray(ImageLabel*, int millisec); + + KPixmap apply(KPixmap pixmap); +}; + +class ImageLabel : public Meter +{ + +Q_OBJECT + +public: + ImageLabel(karamba* k, int ix,int iy,int iw,int ih ); + ImageLabel(karamba* k); + ~ImageLabel(); + void setValue( QString imagePath ); + + void setValue( long ); + void setValue( QPixmap& ); + QString getStringValue() { return imagePath; }; + void scale( int, int ); + void smoothScale( int, int ); + + void rotate(int); + void removeImageTransformations(); + void mUpdate( QPainter * ); + void mUpdate( QPainter *, int ); + + void rolloverImage(QMouseEvent *e); + void parseImages( QString fn, QString fn_roll, int, int, int, int ); + virtual void show(); + virtual void hide(); + + void setTooltip(QString txt); + int cblend; + int background; + // Pixmap Effects + void removeEffects(); + void intensity(float ratio, int millisec); + void channelIntensity(float ratio, QString channel, int millisec); + void toGray(int millisec); + void setBackground(int b); + + void attachClickArea(QString leftMouseButton, QString middleMouseButton, + QString rightMouseButton); + + virtual bool click(QMouseEvent*); + +private slots: + + // gets called if a timed effects needs to bee removed + void slotEffectExpired(); + void slotCopyResult(KIO::Job* job); + +signals: + void pixmapLoaded(); + +private: + void applyTransformations(bool useSmoothScale = false); + int pixmapWidth; + int pixmapHeight; + int pixmapOffWidth; + int pixmapOffHeight; + int pixmapOnWidth; + int pixmapOnHeight; + + // true if Image has been scaled + bool doScale; + // true if Image has been rotated + bool doRotate; + + // Contains the current Effect or is 0 if no Effect is applied + Effect* imageEffect; + + // Scale Matrix + //QWMatrix scaleMat; + int scale_w; + int scale_h; + // Rotation Matrix + //QWMatrix rotMat; + int rot_angle; + + KPixmap pixmap; + KPixmap realpixmap; + + QRect rect_off, rect_on; + QRect old_tip_rect; + + bool zoomed; + //QString fn, fn_roll; + bool rollover; + KPixmap pixmap_off; + KPixmap pixmap_on; + int xoff,xon; + int yoff,yon; + QString imagePath; +}; + +#endif // IMAGELABEL_H diff --git a/superkaramba/src/imagelabel_python.cpp b/superkaramba/src/imagelabel_python.cpp new file mode 100644 index 0000000..6564ce5 --- /dev/null +++ b/superkaramba/src/imagelabel_python.cpp @@ -0,0 +1,331 @@ +/**************************************************************************** +* imagelabel_python.cpp - Imagelabel functions for python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "imagelabel.h" +#include "meter_python.h" +#include "imagelabel_python.h" +#include "lineparser.h" + +ImageLabel* createImageLabel(karamba *theme, long x, long y, + char* path, bool bg) +{ + QString file; + //QString fakefile; + + /*tmp->setThemePath(theme->themePath);*/ + //FIXME: This is an ugly hack to ensure a unique reference + //to add to the meterList. It is a workaround for when a clickarea + //is attached to an image, the image is deleted, and a new image is + //created. A correct solution would be have dictionaries with a key/value + //pair of ints->refs. + ImageLabel *tmp2 = new ImageLabel(theme, x, y, 0, 0); + ImageLabel *tmp = new ImageLabel(theme, x, y, 0, 0); + delete tmp2; + + if(path) + { + file.setAscii(path); + tmp->setValue(file); + //tmp->parseImages(file, fakefile, x,y, 0, 0); + } + tmp->setBackground(bg); + theme->setSensor(LineParser(file), tmp); + theme->meterList->append (tmp); + theme->imageList->append (tmp); + if(bg) + theme->kroot->repaint(true); + return tmp; +} + +PyObject* py_createImage(PyObject *, PyObject *args) +{ + long widget, x, y; + char *text; + if (!PyArg_ParseTuple(args, (char*)"llls:createImage", &widget, &x, &y, &text)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + ImageLabel *tmp = createImageLabel((karamba*)widget, x, y, text, 0); + return (Py_BuildValue((char*)"l", (long)tmp)); +} + +PyObject* py_createBackgroundImage(PyObject *, PyObject *args) +{ + long widget, x, y; + char *text; + if (!PyArg_ParseTuple(args, (char*)"llls:createBackgroundImage", &widget, &x, &y, + &text)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + ImageLabel *tmp = createImageLabel((karamba*)widget, x, y, text, 1); + return (Py_BuildValue((char*)"l", (long)tmp)); +} + +//Matthew Kay: new function for creating icons for tasks +/** + * creates the icon for the specified task as a karamba image + * @param ctask the window id of the task to create the icon for + */ +PyObject* py_createTaskIcon(PyObject *, PyObject *args) +{ + long widget, x, y; + long ctask; + if (!PyArg_ParseTuple(args, (char*)"llll:createTaskIcon", &widget, &x, &y, &ctask)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + //get the specified task and insure it exists + TaskList taskList = ((karamba*)widget)->taskManager.tasks(); + Task* task = 0; + Task* currTask = 0; + for (task = taskList.first(); task; task = taskList.next()) + { + if ((long)task == (long)ctask) + { + //task found + currTask = task; + break; + } + } + if (currTask == 0) + { + //no task was found + qWarning("Task not found."); + return (long)NULL ; + } + //retrieve the QPixmap that represents this image + QPixmap iconPixmap = KWin::icon(currTask->window()); + + ImageLabel *tmp = createImageLabel((karamba*)widget, x, y, 0, 0); + tmp->setValue(iconPixmap); + return (Py_BuildValue((char*)"l", (long)tmp)); +} + +PyObject* py_deleteImage(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll:deleteImage", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + + ((karamba*)widget)->deleteMeterFromSensors((Meter*)meter); + ((karamba*)widget)->clickList->removeRef((Meter*)meter); + ((karamba*)widget)->imageList->removeRef((Meter*)meter); + return Py_BuildValue((char*)"l", + ((karamba*)widget)->meterList->removeRef((Meter*)meter)); +} + +PyObject* py_getThemeImage(PyObject *self, PyObject *args) +{ + return py_getThemeMeter(self, args, "ImageLabel"); +} + +PyObject* py_getImagePos(PyObject *self, PyObject *args) +{ + return py_getPos(self, args, "ImageLabel"); +} + +PyObject* py_getImageSize(PyObject *self, PyObject *args) +{ + return py_getSize(self, args, "ImageLabel"); +} + +PyObject* py_moveImage(PyObject *self, PyObject *args) +{ + return py_move(self, args, "ImageLabel"); +} + +PyObject* py_hideImage(PyObject *self, PyObject *args) +{ + return py_hide(self, args, "ImageLabel"); +} + +PyObject* py_showImage(PyObject *self, PyObject *args) +{ + return py_show(self, args, "ImageLabel"); +} + +PyObject* py_getImageValue(PyObject *self, PyObject *args) +{ + return py_getStringValue(self, args, "ImageLabel"); +} + +PyObject* py_setImageValue(PyObject *self, PyObject *args) +{ + return py_setStringValue(self, args, "ImageLabel"); +} + +PyObject* py_getImageSensor(PyObject *self, PyObject *args) +{ + return py_getSensor(self, args, "ImageLabel"); +} + +PyObject* py_setImageSensor(PyObject *self, PyObject *args) +{ + return py_setSensor(self, args, "ImageLabel"); +} + +PyObject* py_removeImageEffects(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll:removeImageEffects", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + ((ImageLabel*)meter)->removeEffects(); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_changeImageIntensity(PyObject *, PyObject *args) +{ + long widget, meter; + long millisec = 0; + float ratio; + if (!PyArg_ParseTuple(args, (char*)"llf|l:changeImageIntensity", &widget, &meter, + &ratio, &millisec)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + ((ImageLabel*)meter)->intensity(ratio, millisec); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_changeImageChannelIntensity(PyObject *, PyObject *args) +{ + long widget, meter; + float ratio; + char* channel; + long millisec = 0; + if (!PyArg_ParseTuple(args, (char*)"llfs|l:changeImageChannelIntensity", &widget, + &meter, &ratio, &channel, &millisec)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + ((ImageLabel*)meter)->channelIntensity(ratio, channel, millisec); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_changeImageToGray(PyObject *, PyObject *args) +{ + long widget, meter; + long millisec = 0; + if (!PyArg_ParseTuple(args, (char*)"ll|l:changeImageToGray", &widget, &meter, + &millisec)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + ((ImageLabel*)meter)->toGray(millisec); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_removeImageTransformations(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll:removeImageTransformations", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + ((ImageLabel*)meter)->removeImageTransformations(); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_rotateImage(PyObject *, PyObject *args) +{ + long widget, meter; + long deg; + if (!PyArg_ParseTuple(args, (char*)"lll:rotateImage", &widget, &meter, °)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + ((ImageLabel*)meter)->rotate((int)deg); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getImageHeight(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll:getImageHeight", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + return Py_BuildValue((char*)"l", ((ImageLabel*)meter)->getHeight()); +} + +PyObject* py_getImageWidth(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll:getImageWidth", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + return Py_BuildValue((char*)"l", ((ImageLabel*)meter)->getWidth()); +} + +PyObject* py_resizeImageSmooth(PyObject *, PyObject *args) +{ + long widget, meter; + long w, h; + if (!PyArg_ParseTuple(args, (char*)"llll:resizeImageSmooth", &widget, &meter, + &w, &h)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + ((ImageLabel*)meter)->smoothScale((int)w, (int)h); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_resizeImage(PyObject *, PyObject *args) +{ + long widget, meter, w, h; + if (!PyArg_ParseTuple(args, (char*)"llll:resizeImage", &widget, &meter, + &w, &h)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + ((ImageLabel*)meter)->scale((int)w, (int)h); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_addImageTooltip(PyObject *, PyObject *args) +{ + long widget, meter; + PyObject* t; + if (!PyArg_ParseTuple(args, (char*)"llO:addImageTooltip", &widget, &meter, &t)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "ImageLabel")) + return NULL; + ((ImageLabel*)meter)->setTooltip(PyString2QString(t)); + return Py_BuildValue((char*)"l", 1); +} diff --git a/superkaramba/src/imagelabel_python.h b/superkaramba/src/imagelabel_python.h new file mode 100644 index 0000000..5a7f4b6 --- /dev/null +++ b/superkaramba/src/imagelabel_python.h @@ -0,0 +1,449 @@ +/**************************************************************************** +* imagelabel_python.h - Imagelabel functions for python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef IMAGELABEL_PYTHON_H +#define IMAGELABEL_PYTHON_H + +/** Image/createImage +* +* SYNOPSIS +* long createImage(widget, x, y, image) +* DESCRIPTION +* This creates an image on your widget at x, y. The filename should be +* given as the path parameter. In theory the image could be local or could +* be a url. It works just like adding an image in your theme file. You +* will need to save the return value to be able to call other functions on +* your image, such as moveImage() +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * string image -- image for the imagelabel +* RETURN VALUE +* Pointer to new image meter +*/ +PyObject* py_createImage(PyObject *self, PyObject *args); + +/** Image/createBackgroundImage +* +* SYNOPSIS +* long createBackgroundImage(widget, x, y, w, h, image) +* DESCRIPTION +* This creates an background image on your widget at x, y. The filename +* should be given as the path parameter. In theory the image could be +* local or could be a url. It works just like adding an image in your +* theme file. You will need to save the return value to be able to call +* other functions on your image, such as moveImage() +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * string image -- image for the imagelabel +* RETURN VALUE +* Pointer to new image meter +*/ +PyObject* py_createBackgroundImage(PyObject *self, PyObject *args); + +/** Image/createTaskIcon +* +* SYNOPSIS +* long createTaskIcon(widget, x, y, ctask) +* DESCRIPTION +* This creates a task image at x,y. +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * long task -- task +* RETURN VALUE +* Pointer to new image meter +*/ +PyObject* py_createTaskIcon(PyObject *self, PyObject *args); + +/** Image/deleteImage +* +* SYNOPSIS +* long deleteImage(widget, image) +* DESCRIPTION +* This removes image from memory. Please do not call functions on "image" +* after calling deleteImage, as it does not exist anymore and that could +* cause crashes in some cases. +* ARGUMENTS +* * long widget -- karamba +* * long widget -- image +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_deleteImage(PyObject *self, PyObject *args); + +/** Image/getThemeImage +* +* SYNOPSIS +* long getThemeImage(widget, name) +* DESCRIPTION +* You can reference an image in your python code that was created in the +* .theme file. Basically, you just add a NAME= value to the IMAGE line in +* the .theme file. Then if you want to use that object, instead of calling +* createImage, you can call this function. +* +* The name you pass to the function is the same one that you gave it for +* the NAME= parameter in the .theme file. +* ARGUMENTS +* * long widget -- karamba +* * string name -- name of the image to get +* RETURN VALUE +* Pointer to image +*/ +PyObject* py_getThemeImage(PyObject *self, PyObject *args); + +/** Image/getImagePos +* +* SYNOPSIS +* tuple getImagePos(widget, image) +* DESCRIPTION +* Given a reference to a image object, this will return a tuple +* containing the x and y coordinate of a image object. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* RETURN VALUE +* pos +*/ +PyObject* py_getImagePos(PyObject *self, PyObject *args); + +/** Image/getImageSize +* +* SYNOPSIS +* tuple getImageSize(widget, image) +* DESCRIPTION +* Given a reference to a image object, this will return a tuple +* containing the height and width of a image object. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* RETURN VALUE +* size +*/ +PyObject* py_getImageSize(PyObject *self, PyObject *args); + +/** Image/getImageHeight +* +* SYNOPSIS +* long getImageSize(widget, image) +* DESCRIPTION +* This returns the height of an image. This is useful if you have rotated +* an image and its size changed, so you do not know how big it is anymore. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* RETURN VALUE +* height +*/ +PyObject* py_getImageHeight(PyObject *self, PyObject *args); + +/** Image/getImageWidth +* +* SYNOPSIS +* long getImageSize(widget, image) +* DESCRIPTION +* This returns the width of an image. This is useful if you have rotated +* an image and its size changed, so you do not know how big it is anymore. // ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* RETURN VALUE +* width +*/ +PyObject* py_getImageWidth(PyObject *self, PyObject *args); + +/** Image/showImage +* +* SYNOPSIS +* long showImage(widget, image) +* DESCRIPTION +* This shows a previously hidden image. It does not actually refresh the +* image on screen. That is what redrawWidget() does. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_showImage(PyObject *self, PyObject *args); + +/** Image/hideImage +* +* SYNOPSIS +* long hideImage(widget, image) +* DESCRIPTION +* This hides an image. In other words, during subsequent calls to +* widgetUpdate(), this image will not be drawn. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_hideImage(PyObject *self, PyObject *args); + +/** Image/moveImage +* +* SYNOPSIS +* long moveImage(widget, image, x, y) +* DESCRIPTION +* This moves an image to a new x, y relative to your widget. In other +* words, (0,0) is the top corner of your widget, not the screen. The +* imageToMove parameter is a reference to the image to move that you saved +* as the return value from createImage() +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* * long x -- x coordinate +* * long y -- y coordinate +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_moveImage(PyObject *self, PyObject *args); + +/** Image/getImagePath +* +* SYNOPSIS +* string getImagePath(widget, image) +* DESCRIPTION +* Returns current image path. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* RETURN VALUE +* path +*/ +PyObject* py_getImageValue(PyObject *self, PyObject *args); + +/** Image/setImagePath +* +* SYNOPSIS +* long setImagePath(widget, image, path) +* DESCRIPTION +* This will change image of a image widget. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* * long path -- new path +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setImageValue(PyObject *self, PyObject *args); + +/** Image/getImageSensor +* +* SYNOPSIS +* string getImageSensor(widget, image) +* DESCRIPTION +* Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* RETURN VALUE +* sensor string +*/ +PyObject* py_getImageSensor(PyObject *self, PyObject *args); + +/** Image/setImageSensor +* +* SYNOPSIS +* long setImageSensor(widget, image, sensor) +* DESCRIPTION +* Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* * string sensor -- new sensor as in theme files +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setImageSensor(PyObject *self, PyObject *args); + +/** Image/removeImageEffects +* +* SYNOPSIS +* long removeImageEffects(widget, image) +* DESCRIPTION +* If you have called image effect commands on your image (ex: +* changeImageIntensity), you can call this to restore your image to it's +* original form. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_removeImageEffects(PyObject *self, PyObject *args); + +/** Image/changeImageIntensity +* +* SYNOPSIS +* long changeImageIntensity(widget, image, ratio, millisec) +* DESCRIPTION +* Changes the "intensity" of the image, which is similar to it's +* brightness. ratio is a floating point number from -1.0 to 1.0 that +* determines how much to brighten or darken the image. Millisec specifies +* how long in milliseconds before the image is restored to it's original +* form. This is useful for "mouse over" type animations. Using 0 for +* millisec disables this feature and leaves the image permanently +* affected. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* * float ratio -- -1.0 to 1.0 (dark to bright) +* * long millisec -- milliseconds before the image is restored +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_changeImageIntensity(PyObject *self, PyObject *args); + +/** Image/changeImageChannelIntensity +* +* SYNOPSIS +* long changeImageChannelIntensity(widget, image, ratio, channel, millisec) +* DESCRIPTION +* Changes the "intensity" of the image color channel, which is similar to +* it's brightness. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* * float ratio -- -1.0 to 1.0 (dark to bright) +* * string channel -- color channel (red|green|blue) +* * long millisec -- milliseconds before the image is restored +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_changeImageChannelIntensity(PyObject *self, PyObject *args); + +/** Image/changeImageToGray +* +* SYNOPSIS +* long changeImageToGray(widget, image, millisec) +* DESCRIPTION +* Turns the given image into a grayscale image. Millisec specifies how +* long in milliseconds before the image is restored to it's original form. +* This is useful for "mouse over" type animations. Using 0 for millisec +* disables this feature and leaves the image permanently affected. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* * long millisec -- milliseconds before the image is restored +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_changeImageToGray(PyObject *self, PyObject *args); + +/** Image/removeImageTransformations +* +* SYNOPSIS +* long removeImageTransformations(widget, image) +* DESCRIPTION +* If you have rotated or resized your image, you can call this to restore +* your image to it's original form. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_removeImageTransformations(PyObject *self, PyObject *args); + +/** Image/rotateImage +* +* SYNOPSIS +* long rotateImage(widget, image, deg) +* DESCRIPTION +* This rotates your image to by the specified amount of degrees. The +* imageToRotate parameter is a reference to an image that you saved as the +* return value from createImage() +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* * long deg -- degrees to rotate +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_rotateImage(PyObject *self, PyObject *args); + +/** Image/resizeImageSmooth +* +* SYNOPSIS +* long resizeImageSmooth(widget, image, w, h) +* DESCRIPTION +* DEPRECATED: resizeImage now allows the user to pick whether to use fast +* or smooth resizing from the SuperKaramba menu - This resizes your image +* to width, height. The imageToResize parameter is a reference to an +* image that you saved as the return value from createImage() +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* * long w -- width +* * long h -- height +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_resizeImageSmooth(PyObject *self, PyObject *args); + +/** Image/resizeImage +* +* SYNOPSIS +* long resizeImage(widget, image, w, h) +* DESCRIPTION +* This resizes your image to width, height. The imageToResize parameter is +* a reference to an image that you saved as the return value from +* createImage() +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* * long w -- width +* * long h -- height +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_resizeImage(PyObject *self, PyObject *args); + +/** Image/addImageTooltip +* +* SYNOPSIS +* long addImageTooltip(widget, image, text) +* DESCRIPTION +* This creats a tooltip for image with tooltip_text. +* +* Note: +* * If you move the image, the tooltip does not move! It stays! Do not +* create a tooltip if the image is off-screen because you will not be +* able to ever see it. +* ARGUMENTS +* * long widget -- karamba +* * long image -- pointer to image +* * string text -- tooltip text +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_addImageTooltip(PyObject *self, PyObject *args); + +#endif // IMAGELABEL_PYTHON_H diff --git a/superkaramba/src/input.cpp b/superkaramba/src/input.cpp new file mode 100644 index 0000000..a917488 --- /dev/null +++ b/superkaramba/src/input.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** + * Copyright (c) 2005 Alexander Wiedenbruch + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "input.h" +#include "kdebug.h" + +Input::Input(karamba* k, int x, int y, int w, int h): + Meter(k, x, y, w, h) +{ + edit = new SKLineEdit((QWidget*)k, this); + edit->setGeometry(x,y,w,h); +} + +Input::~Input() +{ + delete edit; +} + +void Input::mUpdate(QPainter*) +{ + edit->repaint(); +} + +void Input::setValue(QString text) +{ + edit->setText(text); +} + +QString Input::getStringValue() const +{ + return edit->text(); +} + +void Input::setBGColor(QColor c) +{ + edit->setBackgroundColor(c); +} + +void Input::setColor(QColor c) +{ + Meter::setColor(c); + edit->setFrameColor(c); +} + +QColor Input::getBGColor() const +{ + return edit->backgroundColor(); +} + +QColor Input::getColor() const +{ + return edit->getFrameColor(); +} + +void Input::hide() +{ + Meter::hide(); + edit->setHidden(true); +} + +void Input::show() +{ + Meter::show(); + edit->setHidden(false); +} + +void Input::setSize(int ix, int iy, int iw, int ih) +{ + Meter::setSize(ix, iy, iw, ih); + edit->setGeometry(ix, iy, iw, ih); +} + +void Input::setX(int ix) +{ + Meter::setX(ix); + edit->setGeometry(ix, getY(), getWidth(), getHeight()); +} + +void Input::setY(int iy) +{ + Meter::setY(iy); + edit->setGeometry(getX(), iy, getWidth(), getHeight()); +} + +void Input::setWidth(int iw) +{ + Meter::setWidth(iw); + edit->setGeometry(getX(), getY(), iw, getHeight()); +} + +void Input::setHeight(int ih) +{ + Meter::setHeight(ih); + edit->setGeometry(getX(), getY(), getWidth(), ih); +} + +void Input::setFont(QString f) +{ + font.setFamily(f); + edit->setFont(font); +} + +QString Input::getFont() const +{ + return font.family(); +} + +void Input::setFontColor(QColor fontColor) +{ + QPalette palette = edit->palette(); + palette.setColor(QColorGroup::Text, fontColor); + edit->setPalette(palette); +} + +QColor Input::getFontColor() const +{ + const QColorGroup &color = edit->colorGroup(); + return color.text(); +} + +void Input::setSelectionColor(QColor selectionColor) +{ + QPalette palette = edit->palette(); + palette.setColor(QColorGroup::Highlight, selectionColor); + edit->setPalette(palette); +} + +QColor Input::getSelectionColor() const +{ + const QColorGroup &color = edit->colorGroup(); + return color.highlight(); +} + +void Input::setSelectedTextColor(QColor selectedTextColor) +{ + QPalette palette = edit->palette(); + palette.setColor(QColorGroup::HighlightedText, selectedTextColor); + edit->setPalette(palette); +} + +QColor Input::getSelectedTextColor() const +{ + const QColorGroup &color = edit->colorGroup(); + return color.highlightedText(); +} + +void Input::setFontSize(int size) +{ + font.setPixelSize(size); + edit->setFont(font); +} + +int Input::getFontSize() const +{ + return font.pixelSize(); +} + +void Input::setTextProps(TextField* t) +{ + if(t) + { + setFontSize(t->getFontSize()); + setFont(t->getFont()); + setColor(t->getColor()); + setBGColor(t->getBGColor()); + } +} + +void Input::setInputFocus() +{ + edit->setFocus(); +} + +void Input::clearInputFocus() +{ + edit->clearFocus(); +} + +#include "input.moc" diff --git a/superkaramba/src/input.h b/superkaramba/src/input.h new file mode 100644 index 0000000..15c16e0 --- /dev/null +++ b/superkaramba/src/input.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * Copyright (c) 2005 Alexander Wiedenbruch + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#ifndef INPUT_H +#define INPUT_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "textfield.h" + +class Input : public Meter +{ +Q_OBJECT +public: + Input(karamba* k, int ix, int iy, int iw, int ih); + Input(); + + ~Input(); + + void mUpdate(QPainter *p); + + void setValue(QString text); + QString getStringValue() const; + + void setBGColor(QColor c); + QColor getBGColor() const; + void setColor(QColor c); + QColor getColor() const; + void setFontColor(QColor fontColor); + QColor getFontColor() const; + void setSelectionColor(QColor selectionColor); + QColor getSelectionColor() const; + void setSelectedTextColor(QColor selectedTextColor); + QColor getSelectedTextColor() const; + void setTextProps(TextField*); + + void hide(); + void show(); + + void setSize(int ix, int iy, int iw, int ih); + void setX(int ix); + void setY(int iy); + void setWidth(int iw); + void setHeight(int ih); + + void setFont(QString f); + QString getFont() const; + void setFontSize(int size); + int getFontSize() const; + + void setInputFocus(); + void clearInputFocus(); + +private: + SKLineEdit *edit; + QFont font; +}; + +#endif diff --git a/superkaramba/src/input_python.cpp b/superkaramba/src/input_python.cpp new file mode 100644 index 0000000..0bf45e1 --- /dev/null +++ b/superkaramba/src/input_python.cpp @@ -0,0 +1,355 @@ +/**************************************************************************** +* input_python.cpp - Functions for input box python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* Copyright (c) 2005 Alexander Wiedenbruch +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "meter.h" +#include "meter_python.h" +#include "input_python.h" + +PyObject* py_createInputBox(PyObject *, PyObject *args) +{ + long widget, x, y, w, h; + PyObject *text; + if (!PyArg_ParseTuple(args, (char*)"lllllO:createInputBox", &widget, &x, &y, &w, &h, &text)) + return NULL; + + if (!checkKaramba(widget)) + return NULL; + + Input *tmp = new Input((karamba*)widget, (int)x, (int)y, (int)w, (int)h); + tmp->setValue(PyString2QString(text)); + tmp->setTextProps(((karamba*)widget)->getDefaultTextProps()); + ((karamba*)widget)->meterList->append(tmp); + tmp->show(); + + ((karamba*)widget)->makeActive(); + + return (Py_BuildValue((char*)"l", (long)tmp)); +} + +PyObject* py_deleteInputBox(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll:deleteInputBox", &widget, &meter)) + return NULL; + + if (!checkKarambaAndMeter(widget, meter, "Input")) + return NULL; + + bool result = ((karamba*)widget)->meterList->removeRef((Meter*)meter); + + ((karamba*)widget)->makePassive(); + + return Py_BuildValue((char*)"l", result); +} + +PyObject* py_getThemeInputBox(PyObject *self, PyObject *args) +{ + return py_getThemeMeter(self, args, "Input"); +} + +PyObject* py_getInputBoxValue(PyObject *self, PyObject *args) +{ + return py_getStringValue(self, args, "Input"); +} + +PyObject* py_setInputBoxValue(PyObject *self, PyObject *args) +{ + return py_setStringValue(self, args, "Input"); +} + +PyObject* py_hideInputBox(PyObject *self, PyObject *args) +{ + return py_hide(self, args, "Input"); +} + +PyObject* py_showInputBox(PyObject *self, PyObject *args) +{ + return py_show(self, args, "Input"); +} + +PyObject* py_getInputBoxPos(PyObject *self, PyObject *args) +{ + return py_getPos(self, args, "Input"); +} + +PyObject* py_moveInputBox(PyObject *self, PyObject *args) +{ + return py_move(self, args, "Input"); +} + +PyObject* py_getInputBoxSize(PyObject *self, PyObject *args) +{ + return py_getSize(self, args, "Input"); +} + +PyObject* py_resizeInputBox(PyObject *self, PyObject *args) +{ + return py_resize(self, args, "Input"); +} + +PyObject* py_setInputBoxFont(PyObject *, PyObject *args) +{ + long widget, inputBox; + char* text; + if (!PyArg_ParseTuple(args, (char*)"lls:changeInputBoxFont", + &widget, &inputBox, &text)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + ((Input*)inputBox)->setFont(text); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getInputBoxFont(PyObject *, PyObject *args) +{ + long widget, inputBox; + if (!PyArg_ParseTuple(args, (char*)"ll:getInputBoxFont", &widget, &inputBox)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + return Py_BuildValue((char*)"s", ((Input*)inputBox)->getFont().ascii()); +} + +PyObject* py_setInputBoxFontColor(PyObject *, PyObject *args) +{ + long widget, inputBox; + long r, g, b; + if (!PyArg_ParseTuple(args, (char*)"lllll:changeInputBoxFontColor", &widget, &inputBox, &r, &g, &b)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + ((Input*)inputBox)->setFontColor(QColor(r, g, b)); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getInputBoxFontColor(PyObject *, PyObject *args) +{ + long widget, inputBox; + if (!PyArg_ParseTuple(args, (char*)"ll:changeInputBoxFontColor", &widget, &inputBox)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + QColor color = ((Input*)inputBox)->getFontColor(); + return Py_BuildValue((char*)"(i,i,i)", color.red(), color.green(), color.blue()); +} + +PyObject* py_setInputBoxSelectionColor(PyObject *, PyObject *args) +{ + long widget, inputBox; + long r, g, b; + if (!PyArg_ParseTuple(args, (char*)"lllll:changeInputBoxSelectionColor", &widget, &inputBox, &r, &g, &b)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + ((Input*)inputBox)->setSelectionColor(QColor(r, g, b)); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getInputBoxSelectionColor(PyObject *, PyObject *args) +{ + long widget, inputBox; + if (!PyArg_ParseTuple(args, (char*)"ll:changeInputBoxSelectionColor", &widget, &inputBox)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + QColor color = ((Input*)inputBox)->getSelectionColor(); + return Py_BuildValue((char*)"(i,i,i)", color.red(), color.green(), color.blue()); +} + +PyObject* py_setInputBoxBGColor(PyObject *, PyObject *args) +{ + long widget, inputBox; + long r, g, b; + if (!PyArg_ParseTuple(args, (char*)"lllll:changeInputBoxBackgroundColor", &widget, &inputBox, &r, &g, &b)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + ((Input*)inputBox)->setBGColor(QColor(r, g, b)); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getInputBoxBGColor(PyObject *, PyObject *args) +{ + long widget, inputBox; +if (!PyArg_ParseTuple(args, (char*)"ll:getInputBoxBackgroundColor", &widget, &inputBox)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + QColor color = ((Input*)inputBox)->getBGColor(); + return Py_BuildValue((char*)"(i,i,i)", color.red(), color.green(), color.blue()); +} + +PyObject* py_setInputBoxFrameColor(PyObject *, PyObject *args) +{ + long widget, inputBox; + long r, g, b; +if (!PyArg_ParseTuple(args, (char*)"lllll:changeInputBoxFrameColor", &widget, &inputBox, &r, &g, &b)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + ((Input*)inputBox)->setColor(QColor(r, g, b)); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getInputBoxFrameColor(PyObject *, PyObject *args) +{ + long widget, inputBox; +if (!PyArg_ParseTuple(args, (char*)"ll:getInputBoxFrameColor", &widget, &inputBox)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + QColor color = ((Input*)inputBox)->getColor(); + return Py_BuildValue((char*)"(i,i,i)", color.red(), color.green(), color.blue()); +} + +PyObject* py_setInputBoxSelectedTextColor(PyObject *, PyObject *args) +{ + long widget, inputBox; + long r, g, b; +if (!PyArg_ParseTuple(args, (char*)"lllll:changeInputBoxSelectedTextColor", &widget, &inputBox, &r, &g, &b)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + ((Input*)inputBox)->setSelectedTextColor(QColor(r, g, b)); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getInputBoxSelectedTextColor(PyObject *, PyObject *args) +{ + long widget, inputBox; +if (!PyArg_ParseTuple(args, (char*)"ll:getInputBoxSelectedTextColor", &widget, &inputBox)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + QColor color = ((Input*)inputBox)->getSelectedTextColor(); + return Py_BuildValue((char*)"(i,i,i)", color.red(), color.green(), color.blue()); +} + +PyObject* py_setInputBoxFontSize(PyObject *, PyObject *args) +{ + long widget, inputBox; + long size; + if (!PyArg_ParseTuple(args, (char*)"lll:changeInputBoxFontSize", + &widget, &inputBox, &size)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + ((Input*)inputBox)->setFontSize( size ); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getInputBoxFontSize(PyObject *, PyObject *args) +{ + long widget, inputBox; + if (!PyArg_ParseTuple(args, (char*)"ll:getInputBoxFontSize", &widget, &inputBox)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + return Py_BuildValue((char*)"l", ((Input*)inputBox)->getFontSize()); +} + +PyObject* py_setInputFocus(PyObject *, PyObject *args) +{ + long widget, inputBox; + if (!PyArg_ParseTuple(args, (char*)"ll:setInputFocus", &widget, &inputBox)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + //((karamba*)widget)->setActiveWindow(); + + ((Input*)inputBox)->setInputFocus(); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_clearInputFocus(PyObject *, PyObject *args) +{ + long widget, inputBox; + if (!PyArg_ParseTuple(args, (char*)"ll:clearInputFocus", &widget, &inputBox)) + return NULL; + + if (!checkKarambaAndMeter(widget, inputBox, "Input")) + return NULL; + + ((Input*)inputBox)->clearInputFocus(); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getInputFocus(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:getInputFocus", &widget)) + return NULL; + + if (!checkKaramba(widget)) + return NULL; + + // + // FocusWidget() returns the currently focused line edit, + // but unfortunately we need an 'Input' object here. + // + QWidget *obj = ((karamba*)widget)->focusWidget(); + + if(obj->isA("QLineEdit")) // SKLineEdit is no Q_Object, but QLineEdit can only be here as a SKLineEdit + return Py_BuildValue((char*)"l", ((SKLineEdit*)obj)->getInput()); + + return Py_BuildValue((char*)"l", 0); +} diff --git a/superkaramba/src/input_python.h b/superkaramba/src/input_python.h new file mode 100644 index 0000000..4080b0c --- /dev/null +++ b/superkaramba/src/input_python.h @@ -0,0 +1,475 @@ +/**************************************************************************** +* input_python.h - Functions for input box python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* Copyright (c) 2005 Alexander Wiedenbruch +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef INPUT_PYTHON_H +#define INPUT_PYTHON_H + +/** InputBox/createInputBox +* +* SYNOPSIS +* long createInputBox(widget, x, y, w, h, text) +* DESCRIPTION +* This creates a Input Box at x, y with width and height w, h. You need to save +* the return value of this function to call other functions on your Input Box +* field, such as changeInputBox(). +* The karamba widget is automatically set active, to allow user interactions. +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * long w -- width +* * long h -- height +* * string text -- text for the Input Box +* RETURN VALUE +* Pointer to new Input Box +*/ +PyObject* py_createInputBox(PyObject *, PyObject *args); + +/** InputBox/deleteInputBox +* +* SYNOPSIS +* long deleteInputBox(widget, inputBox) +* DESCRIPTION +* This removes a Input Box object from memory. Please do not call functions of +* the Input Box after calling deleteInputBox, as it does not exist anymore and that +* could cause crashes in some cases. +* The karamba widget ist automatically set passive, when no more Input Boxes are on +* the karamba widget. +* ARGUMENTS +* * long widget -- karamba +* * long widget -- inputBox +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_deleteInputBox(PyObject *, PyObject *args); + +/** InputBox/getThemeInputBox +* +* SYNOPSIS +* long getThemeInputBox(widget, name) +* DESCRIPTION +* You can reference text in your python code that was created in the +* theme file. Basically, you just add a NAME= value to the INPUT line in +* the .theme file. Then if you want to use that object, instead of calling +* createInputBox, you can call this function. +* +* The name you pass to the function is the same one that you gave it for +* the NAME= parameter in the .theme file. +* ARGUMENTS +* * long widget -- karamba +* * string name -- name of the Input Box to get +* RETURN VALUE +* Pointer to Input Box +*/ +PyObject* py_getThemeInputBox(PyObject *self, PyObject *args); + +/** InputBox/getInputBoxValue +* +* SYNOPSIS +* string getInputBoxValue(widget, inputBox) +* DESCRIPTION +* Returns current Input Box text. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to text +* RETURN VALUE +* value +*/ +PyObject* py_getInputBoxValue(PyObject *self, PyObject *args); + +/** InputBox/changeInputBox +* +* SYNOPSIS +* long changeInputBox(widget, inputBox, value) +* DESCRIPTION +* This will change the contents of a input box widget. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to Input Box +* * long value -- new value +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setInputBoxValue(PyObject *self, PyObject *args); + +/** InputBox/hideInputBox +* +* SYNOPSIS +* long hideInputBox(widget, inputBox) +* DESCRIPTION +* Hides a Input Box that is visible. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_hideInputBox(PyObject *self, PyObject *args); + +/** InputBox/showInputBox +* +* SYNOPSIS +* long showInputBox(widget, inputBox) +* DESCRIPTION +* Shows Input Box that has been hidden with hideInputBox() +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_showInputBox(PyObject *self, PyObject *args); + +/** InputBox/getInputBoxPos +* +* SYNOPSIS +* tuple getInputBoxPos(widget, inputBox) +* DESCRIPTION +* Given a reference to a Input Box object, this will return a tuple +* containing the x and y coordinate of a Input Box object. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* pos +*/ +PyObject* py_getInputBoxPos(PyObject *self, PyObject *args); + +/** InputBox/moveInputBox +* +* SYNOPSIS +* long moveInputBox(widget, inputBox, x, y) +* DESCRIPTION +* This moves a Input Box object to a new x, y relative to your widget. In other +* words, (0,0) is the top corner of your widget, not the screen. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* * long x -- x coordinate +* * long y -- y coordinate +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_moveInputBox(PyObject *self, PyObject *args); + +/** InputBox/getInputBoxSize +* +* SYNOPSIS +* tuple getInputBoxSize(widget, inputBox) +* DESCRIPTION +* Given a reference to a Input Box object, this will return a tuple +* containing the height and width of a Input Box object. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* size +*/ +PyObject* py_getInputBoxSize(PyObject *self, PyObject *args); + +/** InputBox/resizeInputBox +* +* SYNOPSIS +* long resizeInputBox(widget, inputBox, w, h) +* DESCRIPTION +* This will resize Input Box to new height and width. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* * long w -- new width +* * long h -- new height +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_resizeInputBox(PyObject *self, PyObject *args); + +/** InputBox/changeInputBoxFont +* +* SYNOPSIS +* long changeInputBoxFont(widget, inputBox, font) +* DESCRIPTION +* This will change the font of a Input Box widget. InputBox is the reference to the +* Input Box object to change. Font is a string the the name of the font to use. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to inputBox +* * string font -- font name +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setInputBoxFont(PyObject *, PyObject *args); + +/** InputBox/getInputBoxFont +* +* SYNOPSIS +* string getInputBoxFont(widget, inputBox) +* DESCRIPTION +* Get current Input Box font name +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* font name +*/ +PyObject* py_getInputBoxFont(PyObject *, PyObject *args); + +/** InputBox/changeInputBoxFontColor +* +* SYNOPSIS +* long changeInputBoxFontColor(widget, inputBox, r, g, b) +* DESCRIPTION +* This will change the color of a text of a Input Box widget. +* InputBox is the reference to the text object to change +* r, g, b are ints from 0 to 255 that represent red, green, and blue. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* * long red -- red component of color +* * long green -- green component of color +* * long blue -- blue component of color +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setInputBoxFontColor(PyObject *, PyObject *args); + +/** InputBox/getInputBoxFontColor +* +* SYNOPSIS +* tuple getInputBoxFontColor(widget, inputBox) +* DESCRIPTION +* Get current text color of a Input Box +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* (red, green, blue) +*/ +PyObject* py_getInputBoxFontColor(PyObject *, PyObject *args); + +/** InputBox/changeInputBoxSelectionColor +* +* SYNOPSIS +* long changeInputBoxSelectionColor(widget, inputBox, r, g, b) +* DESCRIPTION +* This will change the color of the selection of a Input Box widget. +* InputBox is the reference to the text object to change +* r, g, b are ints from 0 to 255 that represent red, green, and blue. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* * long red -- red component of color +* * long green -- green component of color +* * long blue -- blue component of color +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setInputBoxSelectionColor(PyObject *, PyObject *args); + +/** InputBox/getInputBoxSelectionColor +* +* SYNOPSIS +* tuple getInputBoxSelectionColor(widget, inputBox) +* DESCRIPTION +* Get current selection color of a Input Box +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* (red, green, blue) +*/ +PyObject* py_getInputBoxSelectionColor(PyObject *, PyObject *args); + +/** InputBox/changeInputBoxBackgroundColor +* +* SYNOPSIS +* long changeInputBoxBackgroundColor(widget, inputBox, r, g, b) +* DESCRIPTION +* This will change the background color of a Input Box widget. +* InputBox is the reference to the text object to change +* r, g, b are ints from 0 to 255 that represent red, green, and blue. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* * long red -- red component of color +* * long green -- green component of color +* * long blue -- blue component of color +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setInputBoxBGColor(PyObject *, PyObject *args); + +/** InputBox/getInputBoxBackgroundColor +* +* SYNOPSIS +* tuple getInputBoxBackgroundColor(widget, inputBox) +* DESCRIPTION +* Get current background color of a Input Box +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* (red, green, blue) +*/ +PyObject* py_getInputBoxBGColor(PyObject *, PyObject *args); + +/** InputBox/changeInputBoxFrameColor +* +* SYNOPSIS +* long changeInputBoxFrameColor(widget, inputBox, r, g, b) +* DESCRIPTION +* This will change the frame color of a Input Box widget. +* InputBox is the reference to the text object to change +* r, g, b are ints from 0 to 255 that represent red, green, and blue. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* * long red -- red component of color +* * long green -- green component of color +* * long blue -- blue component of color +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setInputBoxFrameColor(PyObject *, PyObject *args); + +/** InputBox/getInputBoxFrameColor +* +* SYNOPSIS +* tuple getInputBoxFrameColor(widget, inputBox) +* DESCRIPTION +* Get current frame color of a Input Box +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* (red, green, blue) +*/ +PyObject* py_getInputBoxFrameColor(PyObject *, PyObject *args); + +/** InputBox/changeInputBoxSelectedTextColor +* +* SYNOPSIS +* long changeInputBoxSelectedTextColor(widget, inputBox, r, g, b) +* DESCRIPTION +* This will change the selected text color of a Input Box widget. +* InputBox is the reference to the text object to change +* r, g, b are ints from 0 to 255 that represent red, green, and blue. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* * long red -- red component of color +* * long green -- green component of color +* * long blue -- blue component of color +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setInputBoxSelectedTextColor(PyObject *, PyObject *args); + +/** InputBox/getInputBoxSelectedTextColor +* +* SYNOPSIS +* tuple getInputBoxSelectedTextColor(widget, inputBox) +* DESCRIPTION +* Get current selected text color of a Input Box +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* (red, green, blue) +*/ +PyObject* py_getInputBoxSelectedTextColor(PyObject *, PyObject *args); + +/** InputBox/changeInputBoxFontSize +* +* SYNOPSIS +* long changeInputBoxFontSize(widget, text, size) +* DESCRIPTION +* This will change the font size of a Input Box widget. +* InputBox is the reference to the text object to change. +* Size is the new font point size. +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* * long size -- new size for text +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setInputBoxFontSize(PyObject *, PyObject *args); + +/** InputBox/getInputBoxFontSize +* +* SYNOPSIS +* long getInputBoxFontSize(widget, inputBox) +* DESCRIPTION +* Get current text font size +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* text font size +*/ +PyObject* py_getInputBoxFontSize(PyObject *, PyObject *args); + +/** InputBox/setInputFocus +* +* SYNOPSIS +* long setInputFocus(widget, inputBox) +* DESCRIPTION +* Sets the Input Focus to the Input Box +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setInputFocus(PyObject *, PyObject *args); + +/** InputBox/clearInputFocus +* +* SYNOPSIS +* long clearInputFocus(widget, inputBox) +* DESCRIPTION +* releases the Input Focus from the Input Box +* ARGUMENTS +* * long widget -- karamba +* * long inputBox -- pointer to Input Box +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_clearInputFocus(PyObject *, PyObject *args); + +/** InputBox/getInputFocus +* +* SYNOPSIS +* long getInputFocus(widget) +* DESCRIPTION +* Get the Input Box currently focused +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* the input box or 0 +*/ +PyObject* py_getInputFocus(PyObject *, PyObject *args); + +#endif diff --git a/superkaramba/src/karamba.cpp b/superkaramba/src/karamba.cpp new file mode 100644 index 0000000..b112af0 --- /dev/null +++ b/superkaramba/src/karamba.cpp @@ -0,0 +1,2098 @@ +/* + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (C) 2003 Hans Karlsson + * Copyright (C) 2004,2005 Luke Kenneth Casson Leighton + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "karamba_python.h" +#include "dcopinterface_stub.h" +#include "richtextlabel.h" +#include "karamba.h" +#include "karambaapp.h" +#include "themesdlg.h" +#include "lineparser.h" +#include "themelocale.h" +#include "superkarambasettings.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +// Menu IDs +#define EDITSCRIPT 1 +#define THEMECONF 2 + +karamba::karamba(QString fn, QString name, bool reloading, int instance, + bool sub_theme): + QWidget(0,"karamba", Qt::WGroupLeader | WStyle_Customize | + WRepaintNoErase| WStyle_NoBorder | WDestructiveClose ), + meterList(0), imageList(0), clickList(0), kpop(0), widgetMask(0), + config(0), kWinModule(0), tempUnit('C'), m_instance(instance), + sensorList(0), timeList(0), + themeConfMenu(0), toDesktopMenu(0), kglobal(0), clickPos(0, 0), accColl(0), + menuAccColl(0), toggleLocked(0), pythonIface(0), defaultTextField(0), + trayMenuSeperatorId(-1), trayMenuQuitId(-1), trayMenuToggleId(-1), + trayMenuThemeId(-1), + m_sysTimer(NULL) +{ + themeStarted = false; + want_right_button = false; + want_meter_wheel_event = false; + prettyName = name; + m_sub_theme = sub_theme; + + KURL url; + + if(fn.find('/') == -1) + url.setFileName(fn); + else + url = fn; + if(!m_theme.set(url)) + { + setFixedSize(0, 0); + QTimer::singleShot(100, this, SLOT(killWidget())); + return; + } + // Add self to list of open themes + // This also updates instance number + karambaApp->addKaramba(this, reloading); + + if(prettyName.isEmpty()) + prettyName = QString("%1 - %2").arg(m_theme.name()).arg(m_instance); + + kdDebug() << "Starting theme: " << m_theme.name() + << " pretty name: " << prettyName << endl; + QString qName = "karamba - " + prettyName; + setName(qName.ascii()); + + KDirWatch *dirWatch = KDirWatch::self(); + connect(dirWatch, SIGNAL( dirty( const QString & ) ), + SLOT( slotFileChanged( const QString & ) ) ); + + if(!dirWatch->contains(m_theme.file())) + dirWatch->addFile(m_theme.file()); + + if(!m_theme.isZipTheme() && m_theme.pythonModuleExists()) + { + QString pythonFile = m_theme.path() + "/" + m_theme.pythonModule() + ".py"; + if(!dirWatch->contains(pythonFile)) + dirWatch->addFile(pythonFile); + } + + widgetUpdate = true; + + // Creates KConfig Object + QString instanceString; + if(m_instance > 1) + instanceString = QString("-%1").arg(m_instance); + QString cfg = QDir::home().absPath() + "/.superkaramba/" + + m_theme.id() + instanceString + ".rc"; + kdDebug() << cfg << endl; + QFile themeConfigFile(cfg); + // Tests if config file Exists + if (!QFileInfo(themeConfigFile).exists()) + { + // Create config file + themeConfigFile.open(IO_ReadWrite); + themeConfigFile.close(); + } + + config = new KConfig(cfg, false, false); + config -> sync(); + config -> setGroup("internal"); + + m_reloading = reloading; + if(m_theme.pythonModuleExists()) + { + kdDebug() << "Loading python module: " << m_theme.pythonModule() << endl; + QTimer::singleShot(0, this, SLOT(initPythonInterface())); + } + + widgetMask = 0; + info = new NETWinInfo( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMState ); + + // could be replaced with TaskManager + kWinModule = new KWinModule(); + desktop = 0; + + connect( kWinModule,SIGNAL(currentDesktopChanged(int)), this, + SLOT(currentDesktopChanged(int)) ); + connect( kapp, SIGNAL(backgroundChanged(int)), this, + SLOT(currentWallpaperChanged(int))); + + // Setup of the Task Manager Callbacks + connect(&taskManager, SIGNAL(activeTaskChanged(Task*)), this, + SLOT(activeTaskChanged(Task*)) ); + connect(&taskManager, SIGNAL(taskAdded(Task*)), this, + SLOT(taskAdded(Task*)) ); + connect(&taskManager, SIGNAL(taskRemoved(Task*)), this, + SLOT(taskRemoved(Task*)) ); + connect(&taskManager, SIGNAL(startupAdded(Startup*)), this, + SLOT(startupAdded(Startup*)) ); + connect(&taskManager, SIGNAL(startupRemoved(Startup*)), this, + SLOT(startupRemoved(Startup*)) ); + + themeConfMenu = new KPopupMenu( this); + themeConfMenu -> setCheckable(true); + + /* XXX - need to be able to delete all these DesktopChangeSlot objects */ + DesktopChangeSlot *dslot; + + int mid; + + toDesktopMenu = new KPopupMenu (this); + toDesktopMenu -> setCheckable(true); + mid = toDesktopMenu -> insertItem (i18n("&All Desktops"), + dslot = new DesktopChangeSlot(this,0), + SLOT(receive())); + dslot->setMenuId(mid); + + toDesktopMenu -> insertSeparator(); + for (int ndesktop=1; ndesktop <= kWinModule->numberOfDesktops(); ndesktop++) + { + QString name = i18n("Desktop &"); + name += ('0' + ndesktop); + + mid = toDesktopMenu -> insertItem (name, + dslot = new DesktopChangeSlot(this, ndesktop), SLOT(receive())); + dslot->setMenuId(mid); + } + + + kpop = new KPopupMenu( this ); + kpop -> setCheckable(true); + + accColl = new KActionCollection( this ); + menuAccColl = new KActionCollection( this ); + + kpop->insertItem( SmallIconSet("reload"),i18n("Update"), this, + SLOT(updateSensors()), Key_F5 ); + toggleLocked = new KToggleAction ( i18n("Toggle &Locked Position"), + SmallIconSet("locked"), + CTRL+Key_L, this, + SLOT( slotToggleLocked() ), + accColl, "Locked position" ); + accColl->insert(toggleLocked); + toggleLocked -> setChecked(true); + + toggleLocked->plug(kpop); + + toggleFastTransforms = new KToggleAction(i18n("Use &Fast Image Scaling"), + CTRL+Key_F, this, + SLOT( slotToggleFastTransforms() ), + accColl, "Fast transformations"); + + accColl->insert(toggleFastTransforms); + toggleFastTransforms -> setChecked(true); + + toggleFastTransforms -> plug(kpop); + + kpop->insertSeparator(); + + kpop->insertItem(i18n("Configure &Theme"), themeConfMenu, THEMECONF); + kpop->setItemEnabled(THEMECONF, false); + kpop->insertItem(i18n("To Des&ktop"), toDesktopMenu); + + kpop->insertItem( SmallIconSet("reload3"),i18n("&Reload Theme"),this, + SLOT(reloadConfig()), CTRL+Key_R ); + kpop->insertItem( SmallIconSet("fileclose"),i18n("&Close This Theme"), this, + SLOT(killWidget()), CTRL+Key_C ); + + if(!SuperKarambaSettings::showSysTray()) + showMenuExtension(); + + kpop->polish(); + + numberOfConfMenuItems = 0; + + systray = 0; + foundKaramba = false; + onTop = false; + managed = false; + fixedPosition = false; + defaultTextField = new TextField(); + + meterList = new QObjectList(); + meterList->setAutoDelete( true ); + sensorList = new QObjectList(); + sensorList->setAutoDelete( true ); + clickList = new QObjectList(); + timeList = new QObjectList(); + imageList = new QObjectList(); + menuList = new QObjectList(); + menuList->setAutoDelete( true ); + + client = kapp->dcopClient(); + if (!client->isAttached()) + client->attach(); + appId = client->registerAs(qApp->name()); + + + setBackgroundMode( NoBackground); + if( !(onTop || managed)) + KWin::lowerWindow( winId() ); + + if( !parseConfig() ) + { + setFixedSize(0,0); + QTimer::singleShot( 100, this, SLOT(killWidget()) ); + qWarning("Could not read config file."); + } + else + { + kroot = new KarambaRootPixmap((QWidget*)this); + kroot->start(); + } + + // Karamba specific Config Entries + bool locked = toggleLocked->isChecked(); + locked = config->readBoolEntry("lockedPosition", locked); + toggleLocked->setChecked(locked); + slotToggleLocked(); + + if (!config -> readBoolEntry("fastTransforms", true)) + { + toggleFastTransforms -> setChecked(false); + slotToggleFastTransforms(); + } + + desktop = config -> readNumEntry("desktop", desktop); + if (desktop > kWinModule->numberOfDesktops()) + { + desktop = 0; + } + + if (desktop) + { + info->setDesktop( desktop ); + } + else + info->setDesktop( NETWinInfo::OnAllDesktops); + + // Read Themespecific Config Entries + config -> setGroup("theme"); + if (config -> hasKey("widgetPosX") && config -> hasKey("widgetPosY")) + { + int xpos = config -> readNumEntry("widgetPosX"); + int ypos = config -> readNumEntry("widgetPosY"); + + if (xpos < 0) + xpos = 0; + if (ypos < 0) + ypos = 0; + move(xpos, ypos); + } + + haveUpdated = 0; + this->setMouseTracking(true); + + + setFocusPolicy(QWidget::StrongFocus); +} + +karamba::~karamba() +{ + //qDebug("karamba::~karamba"); + //Remove self from list of open themes + karambaApp->deleteKaramba(this, m_reloading); + + widgetClosed(); + if(m_theme.isValid()) + writeConfigData(); + + delete config; + + if(meterList != 0) + { + meterList->clear(); + delete meterList; + } + + if( sensorList != 0 ) + { + sensorList->clear(); + delete sensorList; + } + + if( imageList != 0 ) + { + imageList->clear(); + delete imageList; + } + + if( clickList != 0 ) + { + clickList->clear(); + delete clickList; + } + + if( timeList != 0 ) + { + timeList->clear(); + delete timeList; + } + + delete toggleLocked; + delete accColl; + delete menuAccColl; + delete themeConfMenu; + delete kpop; + delete widgetMask; + delete kWinModule; + delete defaultTextField; + if (pythonIface != NULL) + delete pythonIface; +} + +bool karamba::parseConfig() +{ + //qDebug("karamba::parseConfig"); + bool passive = true; + + if(m_theme.open()) + { + QValueStack offsetStack; + LineParser lineParser; + int x=0; + int y=0; + int w=0; + int h=0; + + offsetStack.push(QPoint(0,0)); + + while(m_theme.nextLine(lineParser)) + { + x = lineParser.getInt("X") + offsetStack.top().x(); + y = lineParser.getInt("Y") + offsetStack.top().y(); + w = lineParser.getInt("W"); + h = lineParser.getInt("H"); + + if(lineParser.meter() == "KARAMBA" && !foundKaramba ) + { + //qDebug("karamba found"); + toggleLocked->setChecked(lineParser.getBoolean("LOCKED")); + slotToggleLocked(); + + x = ( x < 0 ) ? 0:x; + y = ( y < 0 ) ? 0:y; + + if( w == 0 || h == 0) + { + w = 300; + h = 300; + } + setFixedSize(w,h); + + if(lineParser.getBoolean("RIGHT")) + { + QDesktopWidget *d = QApplication::desktop(); + x = d->width() - w; + } + else if(lineParser.getBoolean("LEFT")) + { + x = 0; + } + + if(lineParser.getBoolean("BOTTOM")) + { + QDesktopWidget *d = QApplication::desktop(); + y = d->height() - h; + } + else if(lineParser.getBoolean("TOP")) + { + y = 0; + } + + move(x,y); + //pm = QPixmap(size()); + + if(lineParser.getBoolean("ONTOP")) + { + onTop = true; + KWin::setState( winId(), NET::StaysOnTop ); + } + + if(lineParser.getBoolean("MANAGED")) + { + managed = true; + reparent(0, Qt::WType_Dialog | WStyle_Customize | WStyle_NormalBorder + | WRepaintNoErase | WDestructiveClose, pos()); + } + else + { + info->setState( NETWinInfo::SkipTaskbar + | NETWinInfo::SkipPager,NETWinInfo::SkipTaskbar + | NETWinInfo::SkipPager ); + if (onTop) + { + KWin::setState( winId(), NET::StaysOnTop ); + + } + } + + if (lineParser.getBoolean("ONALLDESKTOPS")) + { + desktop = 200; // ugly + } + + + bool dfound=false; + //int desktop = lineParser.getInt("DESKTOP", line, dfound); + if (dfound) + { + info->setDesktop( dfound ); + } + if(lineParser.getBoolean("TOPBAR")) + { + move(x,0); + KWin::setStrut( winId(), 0, 0, h, 0 ); + toggleLocked->setChecked( true ); + slotToggleLocked(); + toggleLocked->setEnabled(false); + } + + if(lineParser.getBoolean("BOTTOMBAR")) + { + int dh = QApplication::desktop()->height(); + move( x, dh - h ); + KWin::setStrut( winId(), 0, 0, 0, h ); + toggleLocked->setChecked( true ); + slotToggleLocked(); + toggleLocked->setEnabled(false); + } + + if(lineParser.getBoolean("RIGHTBAR")) + { + int dw = QApplication::desktop()->width(); + move( dw - w, y ); + KWin::setStrut( winId(), 0, w, 0, 0 ); + toggleLocked->setChecked( true ); + slotToggleLocked(); + toggleLocked->setEnabled(false); + } + + if(lineParser.getBoolean("LEFTBAR")) + { + move( 0, y ); + KWin::setStrut( winId(), w, 0, 0, 0 ); + toggleLocked->setChecked( true ); + slotToggleLocked(); + toggleLocked->setEnabled(false); + } + + QString path = lineParser.getString("MASK"); + + QFileInfo info(path); + QString absPath; + QBitmap bmMask; + QByteArray ba; + if( info.isRelative() ) + { + absPath.setAscii(m_theme.path().ascii()); + absPath.append(path.ascii()); + ba = m_theme.readThemeFile(path); + } + else + { + absPath.setAscii(path.ascii()); + ba = m_theme.readThemeFile(info.fileName()); + } + if(m_theme.isZipTheme()) + { + bmMask.loadFromData(ba); + } + else + { + bmMask.load(absPath); + } + setMask(bmMask); + + m_interval = lineParser.getInt("INTERVAL"); + m_interval = (m_interval == 0) ? 1000 : m_interval; + + QString temp = lineParser.getString("TEMPUNIT", "C").upper(); + tempUnit = temp.ascii()[0]; + foundKaramba = true; + } + + if(lineParser.meter() == "THEME") + { + QString path = lineParser.getString("PATH"); + QFileInfo info(path); + if( info.isRelative()) + path = m_theme.path() +"/" + path; + (new karamba( path, QString() ))->show(); + } + + if(lineParser.meter() == "") + { + int offsetX = offsetStack.top().x(); + int offsetY = offsetStack.top().y(); + offsetStack.push( QPoint( offsetX + lineParser.getInt("X"), + offsetY + lineParser.getInt("Y"))); + } + + if(lineParser.meter() == "") + { + offsetStack.pop(); + } + + if(lineParser.meter() == "CLICKAREA") + { + if( !hasMouseTracking() ) + setMouseTracking(true); + ClickArea *tmp = new ClickArea(this, x, y, w, h ); + tmp->setOnClick(lineParser.getString("ONCLICK")); + + setSensor(lineParser, (Meter*)tmp); + clickList->append( tmp ); + if( lineParser.getBoolean("PREVIEW")) + meterList->append( tmp ); + } + + // program sensor without a meter + if(lineParser.meter() == "SENSOR=PROGRAM") + { + setSensor(lineParser, 0 ); + } + + if(lineParser.meter() == "IMAGE") + { + QString file = lineParser.getString("PATH"); + QString file_roll = lineParser.getString("PATHROLL"); + int xon = lineParser.getInt("XROLL"); + int yon = lineParser.getInt("YROLL"); + QString tiptext = lineParser.getString("TOOLTIP"); + QString name = lineParser.getString("NAME"); + bool bg = lineParser.getBoolean("BACKGROUND"); + xon = ( xon <= 0 ) ? x:xon; + yon = ( yon <= 0 ) ? y:yon; + + ImageLabel *tmp = new ImageLabel(this, x, y, 0, 0); + tmp->setValue(file); + if(!file_roll.isEmpty()) + tmp->parseImages(file, file_roll, x,y, xon, yon); + tmp->setBackground(bg); + if (!name.isEmpty()) + tmp->setName(name.ascii()); + if (!tiptext.isEmpty()) + tmp->setTooltip(tiptext); + + connect(tmp, SIGNAL(pixmapLoaded()), this, SLOT(externalStep())); + setSensor(lineParser, (Meter*) tmp ); + meterList->append (tmp ); + imageList->append (tmp ); + } + + if(lineParser.meter() == "DEFAULTFONT" ) + { + delete defaultTextField; + defaultTextField = new TextField( ); + + defaultTextField->setColor(lineParser.getColor("COLOR", + QColor("black"))); + defaultTextField->setBGColor(lineParser.getColor("BGCOLOR", + QColor("white"))); + defaultTextField->setFont(lineParser.getString("FONT", "Helvetica")); + defaultTextField->setFontSize(lineParser.getInt("FONTSIZE", 12)); + defaultTextField->setAlignment(lineParser.getString("ALIGN", + "LEFT")); + defaultTextField->setFixedPitch(lineParser.getBoolean("FIXEDPITCH", + false)); + defaultTextField->setShadow(lineParser.getInt("SHADOW", 0)); + } + + if(lineParser.meter() == "TEXT" || + lineParser.meter() == "CLICKMAP" || + lineParser.meter() == "RICHTEXT" || + lineParser.meter() == "INPUT") + { + TextField defTxt; + + if(defaultTextField) + defTxt = *defaultTextField; + + TextField* tmpText = new TextField(); + + tmpText->setColor(lineParser.getColor("COLOR", defTxt.getColor())); + tmpText->setBGColor(lineParser.getColor("BGCOLOR", + defTxt.getBGColor())); + tmpText->setFont(lineParser.getString("FONT", defTxt.getFont())); + tmpText->setFontSize(lineParser.getInt("FONTSIZE", + defTxt.getFontSize())); + tmpText->setAlignment(lineParser.getString("ALIGN", + defTxt.getAlignmentAsString())); + tmpText->setFixedPitch(lineParser.getInt("FIXEDPITCH", + defTxt.getFixedPitch())); + + tmpText->setShadow(lineParser.getInt("SHADOW", defTxt.getShadow())); + + // //////////////////////////////////////////////////// + // Now handle the specifics + if(lineParser.meter() == "TEXT") + { + + TextLabel *tmp = new TextLabel(this, x, y, w, h ); + tmp->setTextProps(tmpText); + tmp->setValue( + m_theme.locale()->translate(lineParser.getString("VALUE"))); + + QString name = lineParser.getString("NAME"); + if (!name.isEmpty()) + tmp->setName(name.ascii()); + + setSensor(lineParser, (Meter*)tmp); + meterList->append ( tmp ); + } + + if(lineParser.meter() == "CLICKMAP") + { + if( !hasMouseTracking() ) + setMouseTracking(true); + ClickMap *tmp = new ClickMap(this, x, y, w, h); + tmp->setTextProps( tmpText ); + + setSensor(lineParser, (Meter*)tmp); + // set all params + clickList -> append(tmp); + meterList->append( tmp ); + + } + + if(lineParser.meter() == "RICHTEXT") + { + RichTextLabel *tmp = new RichTextLabel(this, x, y, w, h); + + bool dUl = lineParser.getBoolean("UNDERLINE"); + + tmp->setText( + m_theme.locale()->translate(lineParser.getString("VALUE").ascii()), dUl); + tmp->setTextProps( tmpText ); + tmp->setWidth(w); + tmp->setHeight(h); + + QString name = lineParser.getString("NAME"); + if (!name.isEmpty()) + tmp->setName(name.ascii()); + + setSensor(lineParser, (Meter*)tmp); + clickList -> append(tmp); + meterList->append ( tmp ); + } + + if(lineParser.meter() == "INPUT") + { + Input *tmp = new Input(this, x, y, w, h); + + QString name = lineParser.getString("NAME"); + if (!name.isEmpty()) + tmp->setName(name.ascii()); + + tmp->setTextProps(tmpText); + tmp->setValue( + m_theme.locale()->translate(lineParser.getString("VALUE").ascii())); + + meterList->append(tmp); + passive = false; + } + } + + if(lineParser.meter() == "BAR") + { + Bar *tmp = new Bar(this, x, y, w, h ); + tmp->setImage(lineParser.getString("PATH").ascii()); + tmp->setVertical(lineParser.getBoolean("VERTICAL")); + tmp->setMax(lineParser.getInt("MAX", 100)); + tmp->setMin(lineParser.getInt("MIN", 0)); + tmp->setValue(lineParser.getInt("VALUE")); + QString name = lineParser.getString("NAME"); + if (!name.isEmpty()) + tmp->setName(name.ascii()); + setSensor(lineParser, (Meter*)tmp ); + meterList->append ( tmp ); + } + + if(lineParser.meter() == "GRAPH") + { + int points = lineParser.getInt("POINTS"); + + Graph *tmp = new Graph(this, x, y, w, h, points); + tmp->setMax(lineParser.getInt("MAX", 100)); + tmp->setMin(lineParser.getInt("MIN", 0)); + QString name = lineParser.getString("NAME"); + if (!name.isEmpty()) + tmp->setName(name.ascii()); + + tmp->setColor(lineParser.getColor("COLOR")); + + setSensor(lineParser, (Graph*)tmp); + meterList->append ( tmp ); + } + } + + if(passive && !managed) + { + // Matthew Kay: set window type to "dock" + // (plays better with taskbar themes this way) + KWin::setType(winId(), NET::Dock); + #if defined(KDE_MAKE_VERSION) + #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,9) + //KDE 3.2 addition for the always on top issues + KWin::setState(winId(), NET::KeepBelow); + #endif + #endif + } + + m_theme.close(); + } + //qDebug("parseConfig ok: %d", foundKaramba); + if( !foundKaramba ) + { + // interval = initKaramba( "", 0, 0, 0, 0 ); + // this->close(true); + //delete this; + return false; + } + else + { + return true; + } +} + +void karamba::start() +{ + m_sysTimer = new QTimer(this); + + connect(m_sysTimer, SIGNAL(timeout()), SLOT(step())); + + m_sysTimer->start(m_interval); + + //Start the widget running + QTimer::singleShot( 0, this, SLOT(step()) ); + + if( !(onTop || managed) ) + lowerTimer.start(); +} + +void karamba::makeActive() +{ + KWin::setType(winId(), NET::Normal); + + #if defined(KDE_MAKE_VERSION) + #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,9) + //KDE 3.2 addition for the always on top issues + KWin::setState(winId(), NET::Modal); + #endif + #endif +} + +void karamba::makePassive() +{ + if(managed) + return; + + QObject *meter; + for (meter = meterList->first(); meter; meter = meterList->next()) + { + if((meter)->isA("Input")) + return; + } + + // Matthew Kay: set window type to "dock" (plays better with taskbar themes + // this way) + KWin::setType(winId(), NET::Dock); + #if defined(KDE_MAKE_VERSION) + #if KDE_VERSION >= KDE_MAKE_VERSION(3,1,9) + //KDE 3.2 addition for the always on top issues + KWin::setState(winId(), NET::KeepBelow); + #endif + #endif +} + +void karamba::popupNotify(int) +{ + //qDebug("karamba::popupNotify"); +} + +void karamba::reloadConfig() +{ + //qDebug("karamba::reloadConfig: %s", m_theme.file().ascii()); + writeConfigData(); + if(m_theme.exists()) + { + QFileInfo fileInfo( m_theme.file() ); + (new karamba(m_theme.file(), fileInfo.baseName(), true, m_instance))->show(); + } + closeTheme(true); +} + +void karamba::closeTheme(bool reloading) +{ + m_reloading = reloading; + close(); +} + +void karamba::killWidget() +{ + closeTheme(); +} + +void karamba::initPythonInterface() +{ + pythonIface = new KarambaPython(m_theme, m_reloading); +} + +void karamba::editConfig() +{ + //qDebug("karamba::editConfig"); + QFileInfo fileInfo( m_theme.file() ); + QString path; + + if( fileInfo.isRelative() ) + { + path = m_theme.path() + "/" + m_theme.file(); + } + else + { + path = m_theme.file(); + } + + KRun::runURL( KURL( path ), "text/plain" ); +} + +void karamba::editScript() +{ + //qDebug("karamba::editScript"); + QFileInfo fileInfo( m_theme.file() ); + QString path; + + if( fileInfo.isRelative() ) + { + path = m_theme.path() + "/" + m_theme.name() + ".py"; + } + else + { + path = QFileInfo(m_theme.file()).dirPath() + "/" + m_theme.name() + ".py"; + } + KRun::runURL( KURL( path ), "text/plain" ); +} + +QString karamba::findSensorFromMap(Sensor* sensor) +{ + //qDebug("karamba::findSensorFromMap"); + QMap::ConstIterator it; + QMap::ConstIterator end( sensorMap.end() ); + for ( it = sensorMap.begin(); it != end; ++it ) + { + if (it.data() == sensor) + return it.key(); + } + return ""; +} + +Sensor* karamba::findSensorFromList(Meter* meter) +{ + //qDebug("karamba::findSensorFromList"); + QObjectListIt it( *sensorList ); // iterate over meters + + while ( it != 0 ) + { + if (((Sensor*) *it)->hasMeter(meter)) + return ((Sensor*)*it); + ++it; + } + return NULL; +} + +QString karamba::getSensor(Meter* meter) +{ + //qDebug("karamba::getSensor"); + QString s; + Sensor* sensor = findSensorFromList(meter); + if (sensor) + s = findSensorFromMap(sensor); + return s; +} + +void karamba::deleteMeterFromSensors(Meter* meter) +{ + //qDebug("karamba::deleteMeterFromSensors"); + Sensor* sensor = findSensorFromList(meter); + + if (sensor) + { + sensor->deleteMeter(meter); + if (sensor->isEmpty()) + { + QString s = findSensorFromMap(sensor); + sensorMap.erase(s); + sensorList->removeRef(sensor); + } + } +} + +void karamba::setSensor(const LineParser& lineParser, Meter* meter) +{ + //qDebug("karamba::setSensor"); + Sensor* sensor = 0; + + deleteMeterFromSensors(meter); + + QString sens = lineParser.getString("SENSOR").upper(); + + if( sens == "CPU" ) + { + QString cpuNbr = lineParser.getString("CPU"); + sensor = sensorMap["CPU"+cpuNbr]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0)?1000:interval; + sensor = ( sensorMap["CPU"+cpuNbr] = new CPUSensor( cpuNbr, interval ) ); + sensorList->append( sensor ); + } + SensorParams *sp = new SensorParams(meter); + sp->addParam("FORMAT", + m_theme.locale()->translate(lineParser.getString("FORMAT").ascii())); + sp->addParam("DECIMALS",lineParser.getString("DECIMALS")); + + sensor->addMeter(sp); + sensor->setMaxValue(sp); + + } + + if( sens == "MEMORY" ) + { + sensor = sensorMap["MEMORY"]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0)?3000:interval; + sensor = ( sensorMap["MEMORY"] = new MemSensor( interval ) ); + sensorList->append( sensor ); + } + SensorParams *sp = new SensorParams(meter); + sp->addParam("FORMAT", + m_theme.locale()->translate(lineParser.getString("FORMAT").ascii())); + + sensor->addMeter(sp); + sensor->setMaxValue(sp); + } + + + if( sens == "DISK" ) + { + sensor = sensorMap["DISK"]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0)?5000:interval; + sensor = ( sensorMap["DISK"] = new DiskSensor( interval ) ); + connect( sensor, SIGNAL(initComplete()), this, SLOT(externalStep()) ); + sensorList->append( sensor ); + } + // meter->setMax( ((DiskSensor*)sensor)->getTotalSpace(mntPt)/1024 ); + SensorParams *sp = new SensorParams(meter); + QString mntPt = lineParser.getString("MOUNTPOINT"); + if( mntPt.isEmpty() ) + { + mntPt = "/"; + } + // remove any trailing '/' from mount points in the .theme config, our + // mntMap doesn't like trailing '/'s for matching in DiskSensor + if( mntPt.length() > 1 && mntPt.endsWith("/") ) + { + mntPt.remove( mntPt.length()-1, 1 ); + } + sp->addParam("MOUNTPOINT",mntPt); + sp->addParam("FORMAT", + m_theme.locale()->translate(lineParser.getString("FORMAT").ascii())); + sensor->addMeter(sp); + sensor->setMaxValue(sp); + } + + if( sens == "NETWORK") + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0)?2000:interval; + QString device = lineParser.getString("DEVICE"); + sensor = sensorMap["NETWORK"+device]; + if (sensor == 0) + { + sensor = ( sensorMap["NETWORK"+device] = + new NetworkSensor(device, interval)); + sensorList->append( sensor ); + } + SensorParams *sp = new SensorParams(meter); + sp->addParam("FORMAT", + m_theme.locale()->translate(lineParser.getString("FORMAT").ascii())); + sp->addParam("DECIMALS", lineParser.getString("DECIMALS")); + sensor->addMeter(sp); + } + + if( sens == "UPTIME" ) + { + sensor = sensorMap["UPTIME"]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0)?60000:interval; + sensor = ( sensorMap["UPTIME"] = new UptimeSensor( interval )); + sensorList->append( sensor ); + + } + SensorParams *sp = new SensorParams(meter); + sp->addParam("FORMAT", + m_theme.locale()->translate(lineParser.getString("FORMAT").ascii())); + sensor->addMeter(sp); + } + + if( sens == "SENSOR" ) + { + sensor = sensorMap["SENSOR"]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0)?30000:interval; + sensor = (sensorMap["SENSOR"] = new SensorSensor(interval, tempUnit)); + sensorList->append( sensor ); + } + SensorParams *sp = new SensorParams(meter); + sp->addParam("FORMAT", + m_theme.locale()->translate(lineParser.getString("FORMAT").ascii())); + sp->addParam("TYPE", lineParser.getString("TYPE")); + sensor->addMeter(sp); + } + + + if( sens == "TEXTFILE" ) + { + QString path = lineParser.getString("PATH"); + bool rdf = lineParser.getBoolean("RDF"); + sensor = sensorMap["TEXTFILE"+path]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = ( interval == 0 )?60000:interval; + QString encoding = lineParser.getString("ENCODING"); + + sensor = ( sensorMap["TEXTFILE"+path] = + new TextFileSensor( path, rdf, interval, encoding ) ); + sensorList->append( sensor ); + } + SensorParams *sp = new SensorParams(meter); + sp->addParam("LINE",QString::number(lineParser.getInt("LINE"))); + sensor->addMeter(sp); + } + + + if( sens == "TIME") + { + sensor = sensorMap["DATE"]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0)?60000:interval; + sensor = ( sensorMap["DATE"] = new DateSensor( interval ) ); + sensorList->append( sensor ); + timeList->append( sensor ); + } + SensorParams *sp = new SensorParams(meter); + sp->addParam("FORMAT", + m_theme.locale()->translate(lineParser.getString("FORMAT").ascii())); + sp->addParam("CALWIDTH",lineParser.getString("CALWIDTH")); + sp->addParam("CALHEIGHT",lineParser.getString("CALHEIGHT")); + sensor->addMeter(sp); + } + +#ifdef HAVE_XMMS + + if( sens == "XMMS" ) + { + sensor = sensorMap["XMMS"]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0)?1000:interval; + QString encoding = lineParser.getString("ENCODING"); + + sensor = ( sensorMap["XMMS"] = new XMMSSensor( interval, encoding ) ); + sensorList->append( sensor ); + } + SensorParams *sp = new SensorParams(meter); + sp->addParam("FORMAT", + m_theme.locale()->translate(lineParser.getString("FORMAT").ascii())); + sensor->addMeter(sp); + sensor->setMaxValue(sp); + } +#endif // HAVE_XMMS + + + if( sens == "NOATUN" ) + { + sensor = sensorMap["NOATUN"]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0)?1000:interval; + sensor = ( sensorMap["NOATUN"] = new NoatunSensor( interval, client ) ); + sensorList->append( sensor ); + } + SensorParams *sp = new SensorParams(meter); + sp->addParam("FORMAT", + m_theme.locale()->translate(lineParser.getString("FORMAT").ascii())); + sensor->addMeter(sp); + sensor->setMaxValue(sp); + } + + if( sens == "PROGRAM") + { + QString progName = lineParser.getString("PROGRAM"); + sensor = sensorMap["PROGRAM"+progName]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0)?3600000:interval; + QString encoding = lineParser.getString("ENCODING"); + + sensor = (sensorMap["PROGRAM"+progName] = + new ProgramSensor( progName, interval, encoding ) ); + sensorList->append( sensor ); + } + SensorParams *sp = new SensorParams(meter); + sp->addParam( "LINE", QString::number(lineParser.getInt("LINE"))); + sp->addParam( "THEMAPATH", m_theme.path() ); + sensor->addMeter(sp); + } + + if( sens == "RSS" ) + { + QString source = lineParser.getString("SOURCE"); + QString format = + m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()); + + sensor = sensorMap["RSS"+source]; + if (sensor == 0) + { + int interval = lineParser.getInt( "INTERVAL"); + interval = ( interval == 0 )?60000:interval; + QString encoding = lineParser.getString("ENCODING"); + + sensor = ( sensorMap["RSS"+source] = + new RssSensor( source, interval, format, encoding ) ); + sensorList->append( sensor ); + } + SensorParams *sp = new SensorParams(meter); + sp->addParam("SOURCE",lineParser.getString("SOURCE")); + sensor->addMeter(sp); + } + + if (sensor != 0) + { + QTimer::singleShot( 0, sensor, SLOT(update()) ); + sensor->start(); + } +} + +void karamba::slotFileChanged( const QString & file) +{ + //kdDebug() << "fileChanged: " << file << endl; + + QString pythonFile = m_theme.path() + "/" + m_theme.pythonModule() + ".py"; + + if(file == m_theme.file() || file == pythonFile) + reloadConfig(); +} + +void karamba::passMenuOptionChanged(QString key, bool value) +{ + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->menuOptionChanged(this, key, value); +} + +void karamba::setIncomingData(QString theme, QString obj) +{ + KarambaApplication* app = (KarambaApplication*)qApp; + + kdDebug() << "karamba::setIncomingData " << theme << obj << endl; + //QByteArray data; + //QDataStream dataStream( data, IO_WriteOnly ); + //dataStream << theme; + //dataStream << txt; + + //kapp->dcopClient()->send( app->dcopClient()->appId(), "KarambaIface", "themeNotify(QString,QString)", data ); + + DCOPClient *c = kapp->dcopClient(); + if (!c->isAttached()) + c->attach(); + + if(app->dcopStub()) + app->dcopStub()->setIncomingData(theme, obj); +} + +void karamba::callTheme(QString theme, QString txt) +{ + KarambaApplication* app = (KarambaApplication*)qApp; + kdDebug() << "karamba::callTheme " << theme << txt << endl; + //qWarning("karamba::callTheme"); + //QByteArray data; + //QDataStream dataStream( data, IO_WriteOnly ); + //dataStream << theme; + //dataStream << txt; + + //kapp->dcopClient()->send( app->dcopClient()->appId(), "KarambaIface", "themeNotify(QString,QString)", data ); + + DCOPClient *c = kapp->dcopClient(); + if (!c->isAttached()) + c->attach(); + + if(app->dcopStub()) + app->dcopStub()->themeNotify(theme, txt); +} + +void karamba::themeNotify(QString theme, QString txt) +{ + kdDebug() << "karamba::themeNotify" << theme << txt << endl; + if (pythonIface->isExtensionLoaded()) + { + pythonIface->themeNotify(this, theme.ascii(), txt.ascii()); + } +} + +void karamba::meterClicked(QMouseEvent* e, Meter* meter) +{ + //qWarning("karamba::meterClicked"); + if (pythonIface && pythonIface->isExtensionLoaded() && haveUpdated) + { + int button = 0; + + if( e->button() == Qt::LeftButton ) + button = 1; + else if( e->button() == Qt::MidButton ) + button = 2; + else if( e->button() == Qt::RightButton ) + button = 3; + + if (RichTextLabel* richText = dynamic_cast(meter)) + { + pythonIface->meterClicked(this, richText->anchorAt(e->x(), e->y()), + button); + } + else + { + pythonIface->meterClicked(this, meter, button); + } + } +} + +void karamba::changeInterval(int interval) +{ + if (m_sysTimer != NULL) + m_sysTimer->changeInterval(interval); +} + +void karamba::passClick(QMouseEvent *e) +{ + //qDebug("karamba::passClick"); + QObjectListIt it2( *timeList ); // iterate over meters + while ( it2 != 0 ) + { + (( DateSensor* ) *it2)->toggleCalendar( e ); + ++it2; + } + + + // We create a temporary click list here because original + // can change during the loop (infinite loop Bug 994359) + QObjectList clickListTmp(*clickList); + QObjectListIt it(clickListTmp); + while (it != 0) + { + Meter* meter = (Meter*)(*it); + // Check if meter is still in list + if (clickList->containsRef(meter) && meter->click(e)) + { + // callback + meterClicked(e, meter); + } + ++it; + } + + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded() && haveUpdated) + { + int button = 0; + + if( e->button() == Qt::LeftButton ) + button = 1; + else if( e->button() == Qt::MidButton ) + button = 2; + else if( e->button() == Qt::RightButton ) + button = 3; + + pythonIface->widgetClicked(this, e->x(), e->y(), button); + } +} + +void karamba::passWheelClick( QWheelEvent *e ) +{ + //qDebug("karamba::passWheelClick"); + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded() && haveUpdated) + { + int button = 0; + + if( e->delta() > 0 ) + button = 4; + else + button = 5; + + // We create a temporary click list here because original + // can change during the loop (infinite loop Bug 994359) + if (want_meter_wheel_event) + { + QObjectList clickListTmp(*clickList); + QObjectListIt it(clickListTmp); + + QMouseEvent fakeEvent(QEvent::MouseButtonPress, e->pos(), e->globalPos(), button, e->state()); + + while (it != 0) + { + Meter* meter = (Meter*)(*it); + // Check if meter is still in list + if (clickList->containsRef(meter) && meter->click(&fakeEvent)) + { + if (RichTextLabel* richText = dynamic_cast(meter)) + { + pythonIface->meterClicked(this, richText->anchorAt(fakeEvent.x(), fakeEvent.y()), + button); + } + else + { + pythonIface->meterClicked(this, meter, button); + } + } + ++it; + } + } + + pythonIface->widgetClicked(this, e->x(), e->y(), button); + } +} + +void karamba::management_popup( void ) +{ + kpop->popup(QCursor::pos()); +} + +void karamba::mousePressEvent( QMouseEvent *e ) +{ + //qDebug("karamba::mousePressEvent"); + if( e->button() == RightButton && !want_right_button ) + { + management_popup(); + } + else + { + clickPos = e->pos(); + if( toggleLocked -> isChecked() ) + passClick( e ); + if( !(onTop || managed)) + KWin::lowerWindow( winId() ); + } +} + +void karamba::wheelEvent( QWheelEvent *e ) +{ + //qDebug("karamba::wheelEvent"); + passWheelClick( e ); +} + +void karamba::mouseReleaseEvent( QMouseEvent *e ) +{ + //qDebug("karamba::mouseReleaseEvent"); + clickPos = e->pos(); +} + +void karamba::mouseDoubleClickEvent( QMouseEvent *e ) +{ + //qDebug("karamba::mouseDoubleClickEvent"); + if( !toggleLocked -> isChecked() ) + { + passClick( e ); + } +} + +void karamba::keyPressEvent(QKeyEvent *e) +{ + //qDebug("karamba::keyPressEvent"); + keyPressed(e->text(), 0); +} + +void karamba::keyPressed(const QString& s, const Meter* meter) +{ + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->keyPressed(this, meter, s); +} + +void karamba::mouseMoveEvent( QMouseEvent *e ) +{ + //qDebug("karamba::mouseMoveEvent"); + if( e->state() != 0 && e->state() < 16 && !toggleLocked -> isChecked() ) + { + move( e->globalPos() - clickPos ); + } + else + { + // Change cursor over ClickArea + QObjectListIt it(*clickList); + bool insideArea = false; + + while (it != 0) + { + insideArea = ((Meter*)(*it)) -> insideActiveArea(e -> x(), e ->y()); + if (insideArea) + { + break; + } + ++it; + } + + if(insideArea) + { + if( cursor().shape() != PointingHandCursor ) + setCursor( PointingHandCursor ); + } + else + { + if( cursor().shape() != ArrowCursor ) + setCursor( ArrowCursor ); + } + + QObjectListIt image_it( *imageList); // iterate over image sensors + while ( image_it != 0 ) + { + ((ImageLabel*) *image_it)->rolloverImage(e); + ++image_it; + } + } + + if (pythonIface && pythonIface->isExtensionLoaded()) + { + int button = 0; + + //Modified by Ryan Nickell (p0z3r@mail.com) 03/16/2004 + // This will work now, but only when you move at least + // one pixel in any direction with your mouse. + //if( e->button() == Qt::LeftButton ) + if( e->state() == LeftButton) + button = 1; + //else if( e->button() == Qt::MidButton ) + else if( e->state() == MidButton ) + button = 2; + //else if( e->button() == Qt::RightButton ) + else if( e->state() == RightButton ) + button = 3; + + pythonIface->widgetMouseMoved(this, e->x(), e->y(), button); + } +} + +void karamba::closeEvent ( QCloseEvent * qc) +{ + //qDebug("karamba::closeEvent"); + qc->accept(); + // close(true); + // delete this; +} + +void karamba::paintEvent ( QPaintEvent *e) +{ + //kdDebug() << k_funcinfo << pm.size() << endl; + if(pm.width() == 0) + return; + if( !(onTop || managed)) + { + if( lowerTimer.elapsed() > 100 ) + { + KWin::lowerWindow( winId() ); + lowerTimer.restart(); + } + } + QRect rect = e->rect(); + bitBlt(this,rect.topLeft(),&pm,rect,Qt::CopyROP); +} + +void karamba::updateSensors() +{ + //qDebug("karamba::updateSensors"); + QObjectListIt it( *sensorList ); // iterate over meters + while ( it != 0 ) + { + ((Sensor*) *it)->update(); + ++it; + } + QTimer::singleShot( 500, this, SLOT(step()) ); +} + +void karamba::updateBackground(KSharedPixmap* kpm) +{ + //kdDebug() << k_funcinfo << pm.size() << endl; + // if pm width == 0 this is the first time we come here and we should start + // the theme. This is because we need the background before starting. + //if(pm.width() == 0) + if( !themeStarted ) + { + themeStarted = true; + start(); + } + background = QPixmap(*kpm); + + QPixmap buffer = QPixmap(size()); + + pm = QPixmap(size()); + buffer.fill(Qt::black); + + QObjectListIt it( *imageList ); // iterate over meters + p.begin(&buffer); + bitBlt(&buffer,0,0,&background,0,Qt::CopyROP); + + while ( it != 0 ) + { + if (((ImageLabel*) *it)->background == 1) + { + ((ImageLabel*) *it)->mUpdate(&p, 1); + } + ++it; + } + p.end(); + + bitBlt(&pm,0,0,&buffer,0,Qt::CopyROP); + background = pm; + + QPixmap buffer2 = QPixmap(size()); + + pm = QPixmap(size()); + buffer2.fill(Qt::black); + + QObjectListIt it2( *meterList ); // iterate over meters + p.begin(&buffer2); + bitBlt(&buffer2,0,0,&background,0,Qt::CopyROP); + + while ( it2 != 0 ) + { + ((Meter*) *it2)->mUpdate(&p); + ++it2; + } + p.end(); + + bitBlt(&pm,0,0,&buffer2,0,Qt::CopyROP); + if (systray != 0) + { + systray->updateBackgroundPixmap(buffer2); + } + repaint(); +} + +void karamba::currentDesktopChanged( int i ) +{ + //qDebug("karamba::currentDesktopChanged"); + kroot->repaint( true ); + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->desktopChanged(this, i); +} + +void karamba::currentWallpaperChanged(int i ) +{ + //qDebug("karamba::currentWallpaperChanged"); + kroot->repaint( true ); + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->wallpaperChanged(this, i); +} + +void karamba::externalStep() +{ + //kdDebug() << k_funcinfo << pm.size() << endl; + if (widgetUpdate) + { + QPixmap buffer = QPixmap(size()); + + pm = QPixmap(size()); + buffer.fill(Qt::black); + + QObjectListIt it( *meterList ); // iterate over meters + p.begin(&buffer); + bitBlt(&buffer,0,0,&background,0,Qt::CopyROP); + + while ( it != 0 ) + { + ((Meter*) *it)->mUpdate(&p); + ++it; + } + p.end(); + + bitBlt(&pm,0,0,&buffer,0,Qt::CopyROP); + repaint(); + } +} + +void karamba::step() +{ + //kdDebug() << k_funcinfo << pm.size() << endl; + if (widgetUpdate && haveUpdated) + { + pm = QPixmap(size()); + QPixmap buffer = QPixmap(size()); + buffer.fill(Qt::black); + + QObjectListIt it( *meterList ); // iterate over meters + p.begin(&buffer); + + bitBlt(&buffer,0,0,&background,0,Qt::CopyROP); + + while (it != 0) + { + ((Meter*) *it)->mUpdate(&p); + ++it; + } + p.end(); + + bitBlt(&pm,0,0,&buffer,0,Qt::CopyROP); + update(); + } + + if (pythonIface && pythonIface->isExtensionLoaded()) + { + if (haveUpdated == 0) + pythonIface->initWidget(this); + else + pythonIface->widgetUpdated(this); + } + + if (haveUpdated == 0) + haveUpdated = 1; +} + +void karamba::widgetClosed() +{ + //qDebug("karamba::widgetClosed"); + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->widgetClosed(this); +} + +void karamba::slotToggleLocked() +{ + //qDebug("karamba::slotToggleLocked"); + if(toggleLocked->isChecked()) + { + toggleLocked->setIconSet(SmallIconSet("lock")); + } + else + { + toggleLocked->setIconSet(SmallIconSet("move")); + } +} + +void karamba::slotToggleFastTransforms() +{ + //qDebug("karamba::slotToggleFastTransforms"); + // bool fastTransforms = toggleFastTransforms -> isChecked(); + // if (toggleFastTransforms -> isChecked()) + // { + // toggleFastTransforms -> setIconSet(SmallIconSet("ok")); + // } + // else + // { + // QPixmap ok_disabled; + // toggleFastTransforms -> setIconSet(ok_disabled); + // } + //config.setGroup("internal"); + //config.writeEntry("fastTransforms", toggleFastTransforms -> isChecked()); +} + + +bool karamba::useSmoothTransforms() +{ + //qDebug("karamba::useSmoothTransforms"); + return !toggleFastTransforms -> isChecked(); +} + +void karamba::writeConfigData() +{ + //qDebug("karamba::writeConfigData"); + config -> setGroup("internal"); + config -> writeEntry("lockedPosition", toggleLocked -> isChecked() ); + config -> writeEntry("fastTransforms", toggleFastTransforms -> isChecked() ); + config -> writeEntry("desktop", desktop ); + config -> setGroup("theme"); + // Widget Position + config -> writeEntry("widgetPosX", x()); + config -> writeEntry("widgetPosY", y()); + // Widget Size + config -> writeEntry("widgetWidth", width()); + config -> writeEntry("widgetHeight", height()); + + // write changes to DiskSensor + config -> sync(); + //qWarning("Config File ~/.superkaramba/%s.rc written.", + // m_theme.name().ascii()); +} + +void karamba::slotToggleConfigOption(QString key, bool value) +{ + //qDebug("karamba::slotToggleConfigOption"); + config -> setGroup("config menu"); + config -> writeEntry(key, value); + passMenuOptionChanged(key, value); +} + +void karamba::addMenuConfigOption(QString key, QString name) +{ + //qDebug("karamba::addMenuConfigOption"); + kpop -> setItemEnabled(THEMECONF, true); + + SignalBridge* action = new SignalBridge(this, key, menuAccColl); + KToggleAction* confItem = new KToggleAction (name, KShortcut::null(), + action, SLOT(receive()), + menuAccColl, key.ascii()); + confItem -> setName(key.ascii()); + + menuAccColl -> insert(confItem); + + connect(action, SIGNAL( enabled(QString, bool) ), + this, SLOT( slotToggleConfigOption(QString, bool) )); + + config -> setGroup("config menu"); + confItem -> setChecked(config -> readBoolEntry(key)); + + confItem -> plug(themeConfMenu); + + numberOfConfMenuItems++; +} + +bool karamba::setMenuConfigOption(QString key, bool value) +{ + //qDebug("karamba::setMenuConfigOption"); + KToggleAction* menuAction = ((KToggleAction*)menuAccColl -> action(key.ascii())); + if (menuAction == NULL) + { + qWarning("Menu action %s not found.", key.ascii()); + return false; + } + else + { + menuAction -> setChecked(value); + return true; + } +} + +bool karamba::readMenuConfigOption(QString key) +{ + //qDebug("karamba::readMenuConfigOption"); + KToggleAction* menuAction = ((KToggleAction*)menuAccColl -> action(key.ascii())); + if (menuAction == NULL) + { + qWarning("Menu action %s not found.", key.ascii()); + return false; + } + else + { + return menuAction -> isChecked(); + } +} + +void karamba::passMenuItemClicked(int id) +{ + //qDebug("karamba::passMenuItemClicked"); + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded()) + { + KPopupMenu* menu = 0; + for(int i = 0; i < (int)menuList->count(); i++) + { + KPopupMenu* tmp; + if(i==0) + { + tmp = (KPopupMenu*) menuList->first(); + } + else + { + tmp = (KPopupMenu*) menuList->next(); + } + if(tmp != 0) + { + if(tmp->isItemVisible(id)) + { + menu = tmp; + break; + } + } + } + pythonIface->menuItemClicked(this, menu, id); + } +} + +void karamba::activeTaskChanged(Task* t) +{ + //qDebug("karamba::activeTaskChanged"); + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->activeTaskChanged(this, t); +} + +void karamba::taskAdded(Task* t) +{ + //qDebug("karamba::taskAdded"); + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->taskAdded(this, t); +} + +void karamba::taskRemoved(Task* t) +{ + //qDebug("karamba::taskRemoved"); + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->taskRemoved(this, t); +} + +void karamba::startupAdded(Startup* t) +{ + //qDebug("karamba::startupAdded"); + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->startupAdded(this, t); +} + +void karamba::startupRemoved(Startup* t) +{ + //qDebug("karamba::startupRemoved"); + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->startupRemoved(this, t); +} + +void karamba::processExited (KProcess* proc) +{ + //qDebug("karamba::processExited"); + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->commandFinished(this, (int)proc->pid()); +} + +void karamba::receivedStdout (KProcess *proc, char *buffer, int) +{ + //qDebug("karamba::receivedStdout"); + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->commandOutput(this, (int)proc->pid(), buffer); +} + +//For KDE session management +void karamba::saveProperties(KConfig* config) +{ + //qDebug("karamba::saveProperties"); + config->setGroup("session"); + config->writeEntry("theme", m_theme.file()); + writeConfigData(); +} + +//For KDE session management +void karamba::readProperties(KConfig* config) +{ + //qDebug("karamba::readProperties"); + config->setGroup("session"); + QString atheme = config->readEntry("theme"); +} + +//Register types of events that can be dragged on our widget +void karamba::dragEnterEvent(QDragEnterEvent* event) +{ + //qDebug("karamba::dragEnterEvent"); + event->accept(QTextDrag::canDecode(event)); +} + +//Handle the drop part of a drag and drop event. +void karamba::dropEvent(QDropEvent* event) +{ + //qDebug("karamba::dropEvent"); + QString text; + + if ( QTextDrag::decode(event, text) ) + { + //Everything below is to call the python callback function + if (pythonIface && pythonIface->isExtensionLoaded()) + { + const QPoint &p = event->pos(); + pythonIface->itemDropped(this, text, p.x(), p.y()); + } + } +} + +void karamba::toDesktop(int id, int menuid) +{ + //qDebug("karamba::toDesktop"); + int i; + + desktop = id; + for (i=0; ; i++) + { + int mid = toDesktopMenu->idAt(i); + if (mid == -1) + break; + + toDesktopMenu->setItemChecked(mid, false); + } + toDesktopMenu->setItemChecked(menuid, true); + + if (desktop) + info->setDesktop( desktop); + else + info->setDesktop( NETWinInfo::OnAllDesktops ); +} + +void karamba::systrayUpdated() +{ + //qDebug("karamba::systrayUpdated"); + if (pythonIface && pythonIface->isExtensionLoaded()) + pythonIface->systrayUpdated(this); +} + +void karamba::toggleWidgetUpdate( bool b) +{ + //qDebug("karamba::toggleWidgetUpdate"); + if (pythonIface && pythonIface->isExtensionLoaded()) + widgetUpdate = b; +} + +SignalBridge::SignalBridge(QObject* parent, QString name, KActionCollection* ac) + : QObject(parent, name.ascii()), collection(ac) +{ + setName(name.ascii()); +} + +void SignalBridge::receive() +{ + emit enabled(name(), ((KToggleAction*)collection -> action(name())) -> +isChecked()); +} + +DesktopChangeSlot::DesktopChangeSlot(QObject *parent, int id) + : QObject(parent, "") +{ + desktopid = id; +} + +void DesktopChangeSlot::receive() +{ + karamba *k = (karamba *)parent(); + + // XXX - check type cast + + k->toDesktop(desktopid, menuid); +} + +void DesktopChangeSlot::setMenuId(int id) +{ + menuid = id; +} + +int DesktopChangeSlot::menuId() +{ + return menuid; +} + +void karamba::showMenuExtension() +{ + kglobal = new KPopupMenu(this); + + trayMenuToggleId = kglobal->insertItem(SmallIconSet("superkaramba"), + i18n("Show System Tray Icon"), this, + SLOT(slotToggleSystemTray()), + CTRL+Key_S); + + trayMenuThemeId = kglobal->insertItem(SmallIconSet("knewstuff"), + i18n("&Manage Themes..."), this, + SLOT(slotShowTheme()), CTRL+Key_M); + + trayMenuQuitId = kglobal->insertItem(SmallIconSet("exit"), + i18n("&Quit SuperKaramba"), this, + SLOT(slotQuit()), CTRL+Key_Q); + + kglobal->polish(); + + trayMenuSeperatorId = kpop->insertSeparator(); + kpop->insertItem("SuperKaramba", kglobal); +} + +void karamba::hideMenuExtension() +{ + if(kglobal) + { + kpop->removeItem(trayMenuSeperatorId); + kglobal->removeItem(trayMenuToggleId); + kglobal->removeItem(trayMenuThemeId); + kglobal->removeItem(trayMenuQuitId); + + delete kglobal; + kglobal = 0; + } +} + +void karamba::slotToggleSystemTray() +{ + karambaApp->globalHideSysTray(false); +} + +void karamba::slotQuit() +{ + karambaApp->globalQuitSuperKaramba(); +} + +void karamba::slotShowTheme() +{ + karambaApp->globalShowThemeDialog(); +} + +void karamba::setAlwaysOnTop(bool stay) +{ + if(stay) + { + onTop = true; + KWin::setState( winId(), NET::KeepAbove ); + } + else + { + onTop = false; + KWin::setState( winId(), NET::KeepBelow ); + } +} + +#include "karamba.moc" diff --git a/superkaramba/src/karamba.h b/superkaramba/src/karamba.h new file mode 100644 index 0000000..a81b11b --- /dev/null +++ b/superkaramba/src/karamba.h @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2003 Hans Karlsson + * Copyright (C) 2004,2005 Luke Kenneth Casson Leighton + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#ifndef _KARAMBA_H_ +#define _KARAMBA_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +//#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "karambarootpixmap.h" + +#include "bar.h" +#include "textlabel.h" +#include "imagelabel.h" +#include "graph.h" +#include "input.h" + +#include "clickarea.h" + +#include "sensorparams.h" +#include "memsensor.h" +#include "datesensor.h" +#include "uptimesensor.h" +#include "memsensor.h" +#include "cpusensor.h" +#include "networksensor.h" +#include "xmmssensor.h" +#include "noatunsensor.h" +#include "programsensor.h" +#include "disksensor.h" +#include "sensorsensor.h" +#include "textfilesensor.h" + +#include "clickmap.h" +#include "rsssensor.h" +//#include "clickable.h" +#include "taskmanager.h" +#include "showdesktop.h" +#include "systemtray.h" +#include "themefile.h" + +/** + * @short Application Main Window + * @author Adam Geitgey + * @author Hans Karlsson + * @author Luke Kenneth Casson Leighton + * @version 0.26 + */ + +class KarambaPython; +class LineParser; + +class karamba : public QWidget +{ + Q_OBJECT + +public: + karamba(QString fn, QString name, bool reloading = false, + int instance = -1, bool sub_theme = false); + QObjectList *menuList; + + virtual ~karamba(); + const ThemeFile& theme() const { return m_theme; }; + + QObjectList *meterList; + QObjectList *imageList; + QObjectList *clickList; + void setSensor(const LineParser& lineParser, Meter* meter); + QString getSensor(Meter* meter); + QString findSensorFromMap(Sensor* sensor); + void deleteMeterFromSensors(Meter* meter); + Sensor* findSensorFromList(Meter* meter); + KPopupMenu* keditpop; + KPopupMenu *kpop; + QBitmap* widgetMask; + KarambaRootPixmap *kroot; + TaskManager taskManager; + Systemtray* systray; + KProcess* currProcess; + bool useSmoothTransforms(); + + void changeInterval(int interval); + void setWidgetUpdate(bool wu) { widgetUpdate = wu; }; + bool getWidgetUpdate() { return widgetUpdate; }; + bool hasMeter(Meter* meter) { return meterList->containsRef(meter) > 0; }; + char getTempUnit() { return tempUnit; }; + void addMenuConfigOption(QString key, QString name); + bool setMenuConfigOption(QString key, bool value); + bool readMenuConfigOption(QString key); + void writeConfigData(); + TextField* getDefaultTextProps() { return defaultTextField; }; + int instance() const { return m_instance; }; + void setInstance(int instance) { m_instance = instance; }; + void closeTheme(bool reloading = false); + void keyPressed(const QString& s, const Meter* meter); + + int numberOfConfMenuItems; + KConfig* config; + QString prettyName; + bool m_sub_theme; + bool isSubTheme() { return m_sub_theme; } + + void toggleWidgetUpdate( bool ); + + KWinModule* kWinModule; + + QString incomingData; + QString getIncomingData() { return incomingData; } + void _setIncomingData(QString data) { incomingData = data; } + void setIncomingData(QString theme, QString data); + + void themeNotify(QString theme, QString txt); + void callTheme(QString theme, QString txt); + + double getUpdateTime() { return update_time; } + void setUpdateTime(double time) { update_time = time; } + + void makeActive(); + void makePassive(); + + void showMenuExtension(); + void hideMenuExtension(); + +protected: + void mousePressEvent( QMouseEvent *); + void wheelEvent( QWheelEvent *); + void mouseReleaseEvent( QMouseEvent *); + void mouseDoubleClickEvent( QMouseEvent *); + void mouseMoveEvent( QMouseEvent *); + void keyPressEvent ( QKeyEvent * e ); + void closeEvent ( QCloseEvent *); + void paintEvent ( QPaintEvent *); + void saveProperties(KConfig *); + void readProperties(KConfig *); + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); + +private: + bool widgetUpdate; + bool repaintInProgress; + //bool reloading; + bool want_right_button; + bool want_meter_wheel_event; + + NETWinInfo* info; + bool onTop; + bool managed; + bool fixedPosition; + bool haveUpdated; + char tempUnit; + double update_time; + int m_instance; + + bool parseConfig(); + + void passClick( QMouseEvent* ); + void passWheelClick( QWheelEvent* ); + void meterClicked(QMouseEvent*, Meter*); + + QMap sensorMap; + QObjectList *sensorList; + QObjectList *timeList; + + QTime lowerTimer; + // use only the first occurance of KARAMBA in a config file + bool foundKaramba; + + KPopupMenu* themeConfMenu; + KPopupMenu* toDesktopMenu; + KPopupMenu* kglobal; + + DCOPClient *client; + QCString appId; + + QPixmap pm; + QPixmap background; + QPainter p; + + QPoint clickPos; + KActionCollection* accColl; + KActionCollection* menuAccColl; + KToggleAction *toggleLocked; + // use highquality scale and rotate algorithms + KToggleAction *toggleFastTransforms; + + // Python module references + KarambaPython* pythonIface; + TextField *defaultTextField; + + int desktop; + ThemeFile m_theme; + + int trayMenuSeperatorId; + int trayMenuQuitId; + int trayMenuToggleId; + int trayMenuThemeId; + void start(); + +public slots: + void step(); + void externalStep(); + void widgetClosed(); + void updateSensors(); + void currentDesktopChanged(int); + void currentWallpaperChanged(int); + void slotToggleConfigOption(QString key, bool); + void updateBackground(KSharedPixmap*); + void passMenuOptionChanged(QString key, bool); + void passMenuItemClicked(int); + void processExited (KProcess *proc); + void receivedStdout (KProcess *proc, char *buffer, int buflen); + void toDesktop(int desktopid, int menuid); + const char *getPrettyName() { return prettyName.ascii(); } + + // Systray + void systrayUpdated(); + + // Task Manager + void startupAdded(Startup*); + void startupRemoved(Startup*); + + void taskAdded(Task*); + void taskRemoved(Task*); + void activeTaskChanged(Task*); + void reloadConfig(); + + void setAlwaysOnTop(bool stay); + + /** + * If true, then when a right button is pressed on the theme, + * the theme's python widgetMouseMoved function is called. + */ + void setWantRightButton(bool yesno) { want_right_button = yesno; } + + void setWantMeterWheelEvent(bool yesno) { want_meter_wheel_event = yesno; } + + /** + * can be used to fire up the karamba management popup menu + */ + void management_popup( void ); + +private: + bool m_reloading; + bool themeStarted; + QTimer *m_sysTimer; + int m_interval; + +private slots: + void initPythonInterface(); + void killWidget(); + void editConfig(); + void editScript(); + void slotToggleLocked(); + void slotToggleFastTransforms(); + void popupNotify(int); + void slotFileChanged( const QString & ); + + void slotToggleSystemTray(); + void slotQuit(); + void slotShowTheme(); +}; + +/* + * Slot to receive the event of moving the karamba object + * to a new desktop. Generated by karamba::toDesktopMenu items + */ +class DesktopChangeSlot : public QObject +{ + Q_OBJECT + + public: + DesktopChangeSlot(QObject *parent, int desktop_id); + /* Parent should be the karamba object + * desktop id of 0 indicates all desktops */ + void setMenuId(int id); + int menuId(); + + public slots: + void receive(); + + protected: + int desktopid; + int menuid; +}; + +/** SignalBridge is an ungulate that lives in the forests of wild Wisconsin. */ +class SignalBridge : public QObject +{ + Q_OBJECT + + public: + SignalBridge(QObject* parent, QString, KActionCollection*); + + signals: + void enabled(QString, bool); + + public slots: + void receive(); + + private: + KActionCollection* collection; +}; + +#endif // _KARAMBA_H_ diff --git a/superkaramba/src/karamba_python.cpp b/superkaramba/src/karamba_python.cpp new file mode 100644 index 0000000..ab0034a --- /dev/null +++ b/superkaramba/src/karamba_python.cpp @@ -0,0 +1,635 @@ +/**************************************************************************** +* karamba_python.cpp - Functions for calling python scripts +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damst� +* Copyright (c) 2004 Luke Kenneth Casson Leighton +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include "karambaapp.h" +#include "themefile.h" + +#include "karamba_python.h" +#include "meter_python.h" +#include "bar_python.h" +#include "graph_python.h" +#include "textlabel_python.h" +#include "richtextlabel_python.h" +#include "imagelabel_python.h" +#include "widget_python.h" +#include "menu_python.h" +#include "config_python.h" +#include "task_python.h" +#include "systray_python.h" +#include "svcgrp_python.h" +#include "misc_python.h" +#include "input_python.h" + +/******************************************* + * Python methods are defined here. + * Each method accessible from python should have: + * - A wrapper function that returns a PyObject or appropriate python type + * - A C++ implementation of the python method, named the same as the python call + * - An entry in the python methods array so the call is accessible from python + * + * Example: + * py_move_systay - wrapper function + * moveSystray - actual implementation of method + * {"moveSystray", py_move_systray, METH_VARARGS, "Move the Systray"} - array entry + */ + +static PyMethodDef karamba_methods[] = { + // Bar - bar_python.cpp + {(char*)"createBar", py_createBar, METH_VARARGS, (char*)"Create new Bar."}, + {(char*)"deleteBar", py_deleteBar, METH_VARARGS, (char*)"Delete Bar."}, + {(char*)"getThemeBar", py_getThemeBar, METH_VARARGS, (char*)"Get Bar from .theme using it's name."}, + {(char*)"getBarSize", py_getBarSize, METH_VARARGS, (char*)"Get Bar size."}, + {(char*)"resizeBar", py_resizeBar, METH_VARARGS, (char*)"Resize Bar."}, + {(char*)"getBarPos", py_getBarPos, METH_VARARGS, (char*)"Get Bar position."}, + {(char*)"moveBar", py_moveBar, METH_VARARGS, (char*)"Move Bar."}, + {(char*)"hideBar", py_hideBar, METH_VARARGS, (char*)"Hide Bar."}, + {(char*)"showBar", py_showBar, METH_VARARGS, (char*)"Show Bar."}, + {(char*)"getBarSensor", py_getBarSensor, METH_VARARGS, (char*)"Get Bar sensor."}, + {(char*)"setBarSensor", py_setBarSensor, METH_VARARGS, (char*)"Set Bar sensor."}, + {(char*)"setBarImage", py_setBarImage, METH_VARARGS, (char*)"Set bar image"}, + {(char*)"getBarImage", py_getBarImage, METH_VARARGS, (char*)"Get bar image"}, + {(char*)"setBarVertical", py_setBarVertical, METH_VARARGS, (char*)"Set bar orientation"}, + {(char*)"getBarVertical", py_getBarVertical, METH_VARARGS, (char*)"Get bar orientation"}, + {(char*)"setBarValue", py_setBarValue, METH_VARARGS, (char*)"Set bar value"}, + {(char*)"getBarValue", py_getBarValue, METH_VARARGS, (char*)"Get bar value"}, + {(char*)"setBarMinMax", py_setBarMinMax, METH_VARARGS, (char*)"Set bar min & max"}, + {(char*)"getBarMinMax", py_getBarMinMax, METH_VARARGS, (char*)"Get bar min & max"}, + {(char*)"getIncomingData", py_get_incoming_data, METH_VARARGS, (char*)"Get incoming data passed from another theme"}, + {(char*)"setIncomingData", py_set_incoming_data, METH_VARARGS, (char*)"Set incoming data passed in another theme"}, + + // Graph - graph_python.cpp + {(char*)"createGraph", py_createGraph, METH_VARARGS, (char*)"Create new Graph."}, + {(char*)"deleteGraph", py_deleteGraph, METH_VARARGS, (char*)"Delete Graph."}, + {(char*)"getThemeGraph", py_getThemeGraph, METH_VARARGS, (char*)"Get Graph from .theme using it's name."}, + {(char*)"getGraphSize", py_getGraphSize, METH_VARARGS, (char*)"Get Graph size."}, + {(char*)"resizeGraph", py_resizeGraph, METH_VARARGS, (char*)"Resize Graph."}, + {(char*)"getGraphPos", py_getGraphPos, METH_VARARGS, (char*)"Get Graph position."}, + {(char*)"moveGraph", py_moveGraph, METH_VARARGS, (char*)"Move Graph."}, + {(char*)"hideGraph", py_hideGraph, METH_VARARGS, (char*)"Hide Graph."}, + {(char*)"showGraph", py_showGraph, METH_VARARGS, (char*)"Show Graph."}, + {(char*)"getGraphSensor", py_getGraphSensor, METH_VARARGS, (char*)"Get Graph sensor."}, + {(char*)"setGraphSensor", py_setGraphSensor, METH_VARARGS, (char*)"Set Graph sensor."}, + {(char*)"setGraphValue", py_setGraphValue, METH_VARARGS, (char*)"Set graph value"}, + {(char*)"getGraphValue", py_getGraphValue, METH_VARARGS, (char*)"Get graph value"}, + {(char*)"setGraphMinMax", py_setGraphMinMax, METH_VARARGS, (char*)"Set graph min & max"}, + {(char*)"getGraphMinMax", py_getGraphMinMax, METH_VARARGS, (char*)"Get graph min & max"}, + {(char*)"setGraphColor", py_setGraphColor, METH_VARARGS, (char*)"Change a Graph Sensor's Color"}, + {(char*)"getGraphColor", py_getGraphColor, METH_VARARGS, (char*)"Get a Graph Sensor's Color"}, + + // TextLabel - textlabel_python.cpp + {(char*)"createText", py_createText, METH_VARARGS, (char*)"Create new Text."}, + {(char*)"deleteText", py_deleteText, METH_VARARGS, (char*)"Delete Text."}, + {(char*)"getThemeText", py_getThemeText, METH_VARARGS, (char*)"Get Text from .theme using it's name."}, + {(char*)"getTextSize", py_getTextSize, METH_VARARGS, (char*)"Get Text size."}, + {(char*)"resizeText", py_resizeText, METH_VARARGS, (char*)"Resize Text."}, + {(char*)"getTextPos", py_getTextPos, METH_VARARGS, (char*)"Get Text position."}, + {(char*)"moveText", py_moveText, METH_VARARGS, (char*)"Move Text."}, + {(char*)"hideText", py_hideText, METH_VARARGS, (char*)"Hide Text."}, + {(char*)"showText", py_showText, METH_VARARGS, (char*)"Show Text."}, + {(char*)"getTextSensor", py_getTextSensor, METH_VARARGS, (char*)"Get Text sensor."}, + {(char*)"setTextSensor", py_setTextSensor, METH_VARARGS, (char*)"Set Text sensor."}, + {(char*)"changeText", py_setTextValue, METH_VARARGS, (char*)"Change a Text Sensor's Text"}, + {(char*)"getTextValue", py_getTextValue, METH_VARARGS, (char*)"Get Text value"}, + {(char*)"changeTextShadow", py_setTextShadow, METH_VARARGS, (char*)"Change a Text Shadow size"}, + {(char*)"getTextShadow", py_getTextShadow, METH_VARARGS, (char*)"Get a Text Shadow size"}, + {(char*)"changeTextFont", py_setTextFont, METH_VARARGS, (char*)"Change a Text Sensor's Font"}, + {(char*)"getTextFont", py_getTextFont, METH_VARARGS, (char*)"Get a Text Sensor's Font"}, + {(char*)"changeTextColor", py_setTextColor, METH_VARARGS, (char*)"Change a Text Sensor's Color"}, + {(char*)"getTextColor", py_getTextColor, METH_VARARGS, (char*)"Get a Text Sensor's Color"}, + {(char*)"changeTextSize", py_setTextFontSize, METH_VARARGS, (char*)"Change a Text Sensor's Font Size"}, + {(char*)"getTextFontSize", py_getTextFontSize, METH_VARARGS, (char*)"Get a Text Sensor's Font Size"}, + {(char*)"getTextAlign", py_getTextAlign, METH_VARARGS, (char*)"Get Text alignment."}, + {(char*)"setTextAlign", py_setTextAlign, METH_VARARGS, (char*)"Set Text alignment."}, + {(char*)"setTextScroll", py_setTextScroll, METH_VARARGS, (char*)"Set Text scroll."}, + + // RichTextLabel - richtextlabel_python.cpp + {(char*)"createRichText", py_createRichText, METH_VARARGS, (char*)"Create a Rich Text Sensor"}, + {(char*)"deleteRichText", py_deleteRichText, METH_VARARGS, (char*)"Deletes a Rich Text Sensor"}, + {(char*)"getThemeRichText", py_getThemeRichText, METH_VARARGS, (char*)"Get Rich Text from .theme using it's name."}, + {(char*)"getRichTextSize", py_getRichTextSize, METH_VARARGS, (char*)"Get the (width, height) of a Rich Text Sensor"}, + {(char*)"resizeRichText", py_resizeRichText, METH_VARARGS, (char*)"Resize Rich Text."}, + {(char*)"setRichTextWidth", py_set_rich_text_width, METH_VARARGS, (char*)"Sets the width of a Rich Text Sensor"}, + {(char*)"getRichTextPos", py_getRichTextPos, METH_VARARGS, (char*)"Get Rich Text position."}, + {(char*)"moveRichText", py_moveRichText, METH_VARARGS, (char*)"Moves a Rich Text Sensor"}, + {(char*)"hideRichText", py_hideRichText, METH_VARARGS, (char*)"hides a Rich Text Sensor"}, + {(char*)"showRichText", py_showRichText, METH_VARARGS, (char*)"shows a Rich Text Sensor"}, + {(char*)"getRichTextSensor", py_getRichTextSensor, METH_VARARGS, (char*)"Get Rich Text sensor."}, + {(char*)"setRichTextSensor", py_setRichTextSensor, METH_VARARGS, (char*)"Set Rich Text sensor."}, + {(char*)"changeRichText", py_setRichTextValue, METH_VARARGS, (char*)"Change the content of a Rich Text Sensor"}, + {(char*)"getRichTextValue", py_getRichTextValue, METH_VARARGS, (char*)"Get Rich Text value"}, + {(char*)"changeRichTextFont", py_setRichTextFont, METH_VARARGS, (char*)"Change a Rich Text Sensor's Font"}, + {(char*)"getRichTextFont", py_getRichTextFont, METH_VARARGS, (char*)"Get a Rich Text Sensor's Font"}, + {(char*)"changeRichTextSize", py_setRichTextFontSize, METH_VARARGS, (char*)"Change a Rich Text Sensor's Font Size"}, + {(char*)"getRichTextFontSize", py_getRichTextFontSize, METH_VARARGS, (char*)"Get a Rich Text Sensor's Font Size"}, + + // ImageLabel - imagelabel_python.cpp + {(char*)"createImage", py_createImage, METH_VARARGS, (char*)"Create an Image"}, + {(char*)"createTaskIcon", py_createTaskIcon, METH_VARARGS, (char*)"Create an Image of the Icon for a Task"}, + {(char*)"createBackgroundImage", py_createBackgroundImage, METH_VARARGS, (char*)"Create an Image (only redraw it when background changes)"}, + {(char*)"deleteImage", py_deleteImage, METH_VARARGS, (char*)"Delete an Image"}, + {(char*)"getThemeImage", py_getThemeImage, METH_VARARGS, (char*)"Get image meter from .theme using it's name"}, + {(char*)"getImageSize", py_getImageSize, METH_VARARGS, (char*)"Get Image size."}, + {(char*)"getImageWidth", py_getImageWidth, METH_VARARGS, (char*)"Get the width of an Image"}, + {(char*)"getImageHeight", py_getImageHeight, METH_VARARGS, (char*)"Get the height of an Image"}, + {(char*)"getImagePos", py_getImagePos, METH_VARARGS, (char*)"Get Image position."}, + {(char*)"moveImage", py_moveImage, METH_VARARGS, (char*)"Move an Image"}, + {(char*)"hideImage", py_hideImage, METH_VARARGS, (char*)"Hide an Image"}, + {(char*)"showImage", py_showImage, METH_VARARGS, (char*)"Show an Image"}, + {(char*)"getImagePath", py_getImageValue, METH_VARARGS, (char*)"Get Image path."}, + {(char*)"setImagePath", py_setImageValue, METH_VARARGS, (char*)"Set Image path."}, + {(char*)"getImageSensor", py_getImageSensor, METH_VARARGS, (char*)"Get Image sensor."}, + {(char*)"setImageSensor", py_setImageSensor, METH_VARARGS, (char*)"Set Image sensor."}, + {(char*)"addImageTooltip", py_addImageTooltip, METH_VARARGS, (char*)"Create a Tooltip for an Image"}, + {(char*)"resizeImage", py_resizeImage, METH_VARARGS, (char*)"Scale an Image"}, + {(char*)"resizeImageSmooth", py_resizeImageSmooth, METH_VARARGS, (char*)"Scale an Image (slower, better looking)"}, + {(char*)"rotateImage", py_rotateImage, METH_VARARGS, (char*)"Rotate an Image"}, + {(char*)"removeImageTransformations", py_removeImageTransformations, METH_VARARGS, (char*)"Restore original size and orientation of an Image"}, + {(char*)"removeImageEffects", py_removeImageEffects, METH_VARARGS, (char*)"Remove Effects of an Image"}, + {(char*)"changeImageIntensity", py_changeImageIntensity, METH_VARARGS, (char*)"Change Intensity of an Image"}, + {(char*)"changeImageChannelIntensity", py_changeImageChannelIntensity, METH_VARARGS, (char*)"Change Intensity of an Image Channel"}, + {(char*)"changeImageToGray", py_changeImageToGray, METH_VARARGS, (char*)"Converts an Image to Grayscale"}, + + // Menu - menu_python.cpp + {(char*)"createMenu", py_create_menu, METH_VARARGS, (char*)"Create a popup menu"}, + {(char*)"deleteMenu", py_delete_menu, METH_VARARGS, (char*)"Delete a popup menu"}, + {(char*)"addMenuItem", py_add_menu_item, METH_VARARGS, (char*)"Add a popup menu entry"}, + {(char*)"addMenuSeparator", py_add_menu_separator, METH_VARARGS, (char*)"Add a popup menu seperator item"}, + {(char*)"removeMenuItem", py_remove_menu_item, METH_VARARGS, (char*)"Remove a popup menu entry"}, + {(char*)"popupMenu", py_popup_menu, METH_VARARGS, (char*)"Popup a menu at a specified location"}, + + // Config - config_python.cpp + {(char*)"addMenuConfigOption", py_add_menu_config_option, METH_VARARGS, (char*)"Add a configuration entry to the menu"}, + {(char*)"setMenuConfigOption", py_set_menu_config_option, METH_VARARGS, (char*)"Set a configuration entry in the menu"}, + {(char*)"readMenuConfigOption", py_read_menu_config_option, METH_VARARGS, (char*)"Read a configuration entry in the menu"}, + {(char*)"readConfigEntry", py_read_config_entry, METH_VARARGS, (char*)"Read a configuration entry"}, + {(char*)"writeConfigEntry", py_write_config_entry, METH_VARARGS, (char*)"Writes a configuration entry"}, + + // Widget - widget_python.cpp + {(char*)"moveWidget", py_move_widget, METH_VARARGS, (char*)"Move Widget to x,y"}, + {(char*)"resizeWidget", py_resize_widget, METH_VARARGS, (char*)"Resize Widget to width,height"}, + {(char*)"createWidgetMask", py_create_widget_mask, METH_VARARGS, (char*)"Create a clipping mask for this widget"}, + {(char*)"redrawWidget", py_redraw_widget, METH_VARARGS, (char*)"Update Widget to reflect your changes"}, + {(char*)"redrawWidgetBackground", py_redraw_widget_background, METH_VARARGS, (char*)"Update Widget to reflect background image changes"}, + {(char*)"getWidgetPosition", py_get_widget_position, METH_VARARGS, (char*)"Get Widget Position"}, + {(char*)"toggleWidgetRedraw", py_toggle_widget_redraw, METH_VARARGS, (char*)"Toggle Widget redrawing"}, + + // Task - task_python.cpp + {(char*)"getStartupList", py_get_startup_list, METH_VARARGS, (char*)"Get the system startup list"}, + {(char*)"getStartupInfo", py_get_startup_info, METH_VARARGS, (char*)"Get all the info for a startup"}, + {(char*)"getTaskList", py_get_task_list, METH_VARARGS, (char*)"Get the system task list"}, + {(char*)"getTaskNames", py_get_task_names, METH_VARARGS, (char*)"Get the system task list in name form"}, + {(char*)"getTaskInfo", py_get_task_info, METH_VARARGS, (char*)"Get all the info for a task"}, + {(char*)"performTaskAction", py_perform_task_action, METH_VARARGS, (char*)"Do something with a task, such as minimize it"}, + + // System Tray - systray_python.cpp + {(char*)"createSystray", py_create_systray, METH_VARARGS, (char*)"Create a Systray"}, + {(char*)"hideSystray", py_hide_systray, METH_VARARGS, (char*)"Hide the Systray"}, + {(char*)"showSystray", py_show_systray, METH_VARARGS, (char*)"Show the Systray"}, + {(char*)"moveSystray", py_move_systray, METH_VARARGS, (char*)"Move the Systray"}, + {(char*)"getCurrentWindowCount", py_get_current_window_count, METH_VARARGS, (char*)"Get current Window count"}, + {(char*)"updateSystrayLayout", py_update_systray_layout, METH_VARARGS, (char*)"Update Systray layout"}, + + // Misc - misc_python.cpp + {(char*)"getThemePath", py_get_theme_path, METH_VARARGS, (char*)"Get the file path of the theme"}, + {(char*)"readThemeFile", py_read_theme_file, METH_VARARGS, + (char*)"Read file from theme."}, + {(char*)"language", py_language, METH_VARARGS, + (char*)"Return default language of a translation file."}, + {(char*)"userLanguage", py_userLanguage, METH_VARARGS, + (char*)"Return user language."}, + {(char*)"userLanguages", py_userLanguages, METH_VARARGS, + (char*)"Return preferred user languages."}, + {(char*)"openTheme", py_open_theme, METH_VARARGS, + (char*)"Open a new theme"}, + {(char*)"reloadTheme", py_reload_theme, METH_VARARGS, + (char*)"Reload current theme"}, + {(char*)"acceptDrops", py_accept_drops, METH_VARARGS, + (char*)"Allows widget to receive Drop (I.E. Drag and Drop) events"}, + {(char*)"toggleShowDesktop", py_toggle_show_desktop, METH_VARARGS, + (char*)"Show/Hide the desktop"}, + {(char*)"execute", py_execute_command, METH_VARARGS, (char*)"Execute a command"}, + {(char*)"executeInteractive", py_execute_command_interactive, METH_VARARGS, (char*)"Execute a command and get it's output (stdout)"}, + {(char*)"attachClickArea", (PyCFunction)py_attach_clickArea, METH_VARARGS|METH_KEYWORDS, (char*)"Add a clickArea to the given text or image"}, + {(char*)"createClickArea", py_create_click_area, METH_VARARGS, (char*)"Create a Click Area Sensor"}, + {(char*)"getNumberOfDesktops", py_get_number_of_desktops, METH_VARARGS, (char*)"Get current number of virtual desktops"}, + {(char*)"getIp", py_get_ip, METH_VARARGS, (char*)"Get current host's IP address"}, + {(char*)"translateAll", py_translate_all, METH_VARARGS, (char*)"Translate all widgets in a theme"}, + {(char*)"show", py_show, METH_VARARGS, (char*)"Show theme"}, + {(char*)"hide", py_hide, METH_VARARGS, (char*)"Hide theme"}, + + // Input Box - input_python.cpp + {(char*)"createInputBox", py_createInputBox, METH_VARARGS, + (char*)"Create new Input Box."}, + {(char*)"deleteInputBox", py_deleteInputBox, METH_VARARGS, + (char*)"Delete Input Box."}, + {(char*)"getThemeInputBox", py_getThemeInputBox, METH_VARARGS, + (char*)"Get Input Box from .theme using it's name."}, + {(char*)"getInputBoxValue", py_getInputBoxValue, METH_VARARGS, + (char*)"Get Input Box value"}, + {(char*)"changeInputBox", py_setInputBoxValue, METH_VARARGS, + (char*)"Change a Input Box Text"}, + {(char*)"hideInputBox", py_hideInputBox, METH_VARARGS, + (char*)"Hide Input Box."}, + {(char*)"showInputBox", py_showInputBox, METH_VARARGS, + (char*)"Show Input Box."}, + {(char*)"getInputBoxPos", py_getInputBoxPos, METH_VARARGS, + (char*)"Get InputBox position."}, + {(char*)"moveInputBox", py_moveInputBox, METH_VARARGS, + (char*)"Moves a Input Box"}, + {(char*)"getInputBoxSize", py_getInputBoxSize, METH_VARARGS, + (char*)"Get the (width, height) of a Input Box"}, + {(char*)"resizeInputBox", py_resizeInputBox, METH_VARARGS, + (char*)"Resize Input Box."}, + {(char*)"changeInputBoxFont", py_setInputBoxFont, METH_VARARGS, + (char*)"Change a Input Box Font"}, + {(char*)"getInputBoxFont", py_getInputBoxFont, METH_VARARGS, + (char*)"Get a Input Box Font"}, + {(char*)"changeInputBoxFontColor", py_setInputBoxFontColor, METH_VARARGS, + (char*)"Change a Input Box Font Color"}, + {(char*)"getInputBoxFontColor", py_getInputBoxFontColor, METH_VARARGS, + (char*)"Get a Input Box Font Color"}, + {(char*)"changeInputBoxSelectionColor", py_setInputBoxSelectionColor, + METH_VARARGS, (char*)"Change a Input Box Selection Color"}, + {(char*)"getInputBoxSelectionColor", py_getInputBoxSelectionColor, + METH_VARARGS, (char*)"Get a Input Box Selection Color"}, + {(char*)"changeInputBoxBackgroundColor", py_setInputBoxBGColor, + METH_VARARGS, (char*)"Change a Input Box Background Color"}, + {(char*)"getInputBoxBackgroundColor", py_getInputBoxBGColor, METH_VARARGS, + (char*)"Get a Input Box Background Color"}, + {(char*)"changeInputBoxFrameColor", py_setInputBoxFrameColor, METH_VARARGS, + (char*)"Change a Input Box Frame Color"}, + {(char*)"getInputBoxFrameColor", py_getInputBoxFrameColor, METH_VARARGS, + (char*)"Get a Input Box Frame Color"}, + {(char*)"changeInputBoxSelectedTextColor", py_setInputBoxSelectedTextColor, + METH_VARARGS, (char*)"Change a Input Box Selected Text Color"}, + {(char*)"getInputBoxSelectedTextColor", py_getInputBoxSelectedTextColor, + METH_VARARGS, (char*)"Get a Input Box Selected Text Color"}, + {(char*)"changeInputBoxFontSize", py_setInputBoxFontSize, METH_VARARGS, + (char*)"Change a Input Box Font Size"}, + {(char*)"getInputBoxFontSize", py_getInputBoxFontSize, METH_VARARGS, + (char*)"Get a Input Box Font Size"}, + {(char*)"setInputFocus", py_setInputFocus, METH_VARARGS, + (char*)"Set the Input Focus to the Input Box"}, + {(char*)"clearInputFocus", py_clearInputFocus, METH_VARARGS, + (char*)"Clear the Input Focus of the Input Box"}, + {(char*)"getInputFocus", py_getInputFocus, METH_VARARGS, + (char*)"Get the Input Box currently focused"}, + + {(char*)"setWidgetOnTop", py_set_widget_on_top, METH_VARARGS, + (char*)"changes 'on top' status"}, + {(char*)"getSystraySize", py_get_systray_size, METH_VARARGS, + (char*)"Get the size of the Systray"}, + {(char*)"getPrettyThemeName", py_get_pretty_name, METH_VARARGS, + (char*)"Get the pretty name of the theme"}, + {(char*)"openNamedTheme", py_open_named_theme, METH_VARARGS, + (char*)"Open a new theme giving it a new name"}, + {(char*)"callTheme", py_call_theme, METH_VARARGS, + (char*)"Pass a string to another theme"}, + {(char*)"changeInterval", py_change_interval, METH_VARARGS, + (char*)"Change the refresh interval"}, + {(char*)"run", py_run_command, METH_VARARGS, + (char*)"Execute a command with KRun"}, + {(char*)"createServiceClickArea", py_create_service_click_area, METH_VARARGS, + (char*)"Create a Service-named Click Area Sensor"}, + {(char*)"removeClickArea", py_remove_click_area, METH_VARARGS, + (char*)"Remove a Click Area Sensor"}, + {(char*)"setUpdateTime", py_set_update_time, METH_VARARGS, + (char*)"Set last updated time"}, + {(char*)"getUpdateTime", py_get_update_time, METH_VARARGS, + (char*)"Get last updated time"}, + {(char*)"setWantRightButton", py_want_right_button, METH_VARARGS, + (char*)"Set to 1 to deactivate management popups"}, + {(char*)"setWantMeterWheelEvent", py_want_wheel_event, METH_VARARGS, + (char*)"Enables wheel events over meters."}, + {(char*)"managementPopup", py_management_popup, METH_VARARGS, + (char*)"Activates the Management Popup menu"}, + + // service groups + {(char*)"getServiceGroups", py_get_service_groups, METH_VARARGS, + (char*)"Get KDE Service Groups"}, + + {NULL, NULL, 0 ,NULL} +}; + +PyThreadState* KarambaPython::mainThreadState = 0; + +KarambaPython::KarambaPython(const ThemeFile& theme, bool reloading): + pythonThemeExtensionLoaded(false), pName(0), pModule(0), pDict(0) +{ + PyThreadState* myThreadState; + char pypath[1024]; + + getLock(&myThreadState); + + // load the .py file for this .theme + PyRun_SimpleString((char*)"import sys"); + //Add theme path to python path so that we can find the python file + snprintf(pypath, 1023, "sys.path.insert(0, '%s')", theme.path().ascii()); + PyRun_SimpleString(pypath); + PyRun_SimpleString((char*)"sys.path.insert(0, '')"); + + PyImport_AddModule((char*)"karamba"); + Py_InitModule((char*)"karamba", karamba_methods); + + pName = PyString_FromString(theme.pythonModule().ascii()); + pModule = PyImport_Import(pName); + + fprintf(stderr, "%s\n", pypath); + + //Make sure the module is up to date. + if (reloading) + PyImport_ReloadModule(pModule); + + if (pModule != NULL) + { + pDict = PyModule_GetDict(pModule); + if (pDict != NULL) + { + pythonThemeExtensionLoaded = true; + } + } + else + { + PyErr_Print(); + fprintf(stderr, + "------------------------------------------------------\n"); + fprintf(stderr, "What does ImportError mean?\n"); + fprintf(stderr, "\n"); + fprintf(stderr, + "It means that I couldn't load a python add-on %s.py\n", + theme.pythonModule().ascii()); + fprintf(stderr, "If this is a regular theme and doesn't use python\n"); + fprintf(stderr, "extensions, then nothing is wrong.\n"); + fprintf(stderr, + "------------------------------------------------------\n"); + } + releaseLock(myThreadState); +} + +KarambaPython::~KarambaPython() +{ + //Clean up Python references + if (pythonThemeExtensionLoaded) { + PyThreadState* myThreadState; + getLock(&myThreadState); + + //Displose of current python module so we can reload in constructor. + Py_DECREF(pModule); + Py_DECREF(pName); + + releaseLock(myThreadState); + } +} + +void KarambaPython::initPython() +{ + // initialize Python + Py_Initialize(); + + // initialize thread support + PyEval_InitThreads(); + + // save a pointer to the main PyThreadState object + mainThreadState = PyThreadState_Get(); + + // release the lock + PyEval_ReleaseLock(); +} + +void KarambaPython::shutdownPython() +{ + // shut down the interpreter + PyInterpreterState * mainInterpreterState = mainThreadState->interp; + // create a thread state object for this thread + PyThreadState * myThreadState = PyThreadState_New(mainInterpreterState); + PyThreadState_Swap(myThreadState); + PyEval_AcquireLock(); + Py_Finalize(); +} + +void KarambaPython::getLock(PyThreadState** myThreadState) +{ + // get the global lock + PyEval_AcquireLock(); + + // create a thread state object for this thread + *myThreadState = PyThreadState_New(mainThreadState->interp); + PyThreadState_Swap(*myThreadState); +} + +void KarambaPython::releaseLock(PyThreadState* myThreadState) +{ + // swap my thread state out of the interpreter + PyThreadState_Swap(NULL); + // clear out any cruft from thread state object + PyThreadState_Clear(myThreadState); + // delete my thread state object + PyThreadState_Delete(myThreadState); + // release the lock + PyEval_ReleaseLock(); +} + +PyObject* KarambaPython::getFunc(const char* function) +{ + PyObject* pFunc = PyDict_GetItemString(pDict, (char*)function); + if (pFunc && PyCallable_Check(pFunc)) + return pFunc; + return NULL; +} + +bool KarambaPython::callObject(const char* func, PyObject* pArgs, bool lock) +{ + bool result = false; + PyThreadState* myThreadState; + + //qDebug("Calling %s", func); + + if (lock) + getLock(&myThreadState); + PyObject* pFunc = getFunc(func); + + if (pFunc != NULL) + { + PyObject* pValue = PyObject_CallObject(pFunc, pArgs); + + if (pValue != NULL) + { + Py_DECREF(pValue); + result = true; + } + else + { + qWarning("Call to %s failed", func); + PyErr_Print(); + } + } + Py_DECREF(pArgs); + if (lock) + releaseLock(myThreadState); + return result; +} + +bool KarambaPython::initWidget(karamba* k) +{ + PyObject* pArgs = Py_BuildValue((char*)"(l)", k); + return callObject("initWidget", pArgs); +} + +bool KarambaPython::widgetUpdated(karamba* k) +{ + PyObject* pArgs = Py_BuildValue((char*)"(l)", k); + return callObject("widgetUpdated", pArgs); +} + +bool KarambaPython::widgetClosed(karamba* k) +{ + PyObject* pArgs = Py_BuildValue((char*)"(l)", k); + return callObject("widgetClosed", pArgs); +} + +bool KarambaPython::menuOptionChanged(karamba* k, QString key, bool value) +{ + PyObject* pArgs = Py_BuildValue((char*)"(lsi)", k, key.ascii(), (int)value); + return callObject("menuOptionChanged", pArgs); +} + +bool KarambaPython::menuItemClicked(karamba* k, KPopupMenu* menu, long id) +{ + PyObject* pArgs = Py_BuildValue((char*)"(lll)", k, menu, id); + return callObject("menuItemClicked", pArgs); +} + +bool KarambaPython::meterClicked(karamba* k, Meter* meter, int button) +{ + PyObject* pArgs = Py_BuildValue((char*)"(lli)", k, meter, button); + return callObject("meterClicked", pArgs); +} + +bool KarambaPython::meterClicked(karamba* k, QString anchor, int button) +{ + PyObject* pArgs = Py_BuildValue((char*)"(lsi)", k, anchor.ascii(), button); + return callObject("meterClicked", pArgs); +} + +bool KarambaPython::widgetClicked(karamba* k, int x, int y, int button) +{ + PyObject* pArgs = Py_BuildValue((char*)"(liii)", k, x, y, button); + return callObject("widgetClicked", pArgs); +} + +bool KarambaPython::keyPressed(karamba* k, const Meter* meter, + const QString& text) +{ + PyObject* pArgs = Py_BuildValue((char*)"(lls)", k, meter, text.ucs2()); + return callObject("keyPressed", pArgs); +} + +bool KarambaPython::widgetMouseMoved(karamba* k, int x, int y, int button) +{ + PyObject* pArgs = Py_BuildValue((char*)"(liii)", k, x, y, button); + return callObject("widgetMouseMoved", pArgs); +} + +bool KarambaPython::activeTaskChanged(karamba* k, Task* t) +{ + PyObject* pArgs = Py_BuildValue((char*)"(ll)", k, t); + return callObject("activeTaskChanged", pArgs); +} + +bool KarambaPython::taskAdded(karamba* k, Task* t) +{ + PyObject* pArgs = Py_BuildValue((char*)"(ll)", k, t); + return callObject("taskAdded", pArgs); +} + +bool KarambaPython::taskRemoved(karamba* k, Task* t) +{ + PyObject* pArgs = Py_BuildValue((char*)"(ll)", k, t); + return callObject("taskRemoved", pArgs); +} + +bool KarambaPython::startupAdded(karamba* k, Startup* t) +{ + PyObject* pArgs = Py_BuildValue((char*)"(ll)", k, t); + return callObject("startupAdded", pArgs); +} + +bool KarambaPython::startupRemoved(karamba* k, Startup* t) +{ + PyObject* pArgs = Py_BuildValue((char*)"(ll)", k, t); + return callObject("startupRemoved", pArgs); +} + +bool KarambaPython::commandOutput(karamba* k, int pid, char *buffer) +{ + PyObject* pArgs = Py_BuildValue((char*)"(lis)", k, pid, buffer); + return callObject("commandOutput", pArgs); +} + +bool KarambaPython::commandFinished(karamba* k, int pid) +{ + PyObject* pArgs = Py_BuildValue((char*)"(li)", k, pid); + return callObject("commandFinished", pArgs); +} + +bool KarambaPython::itemDropped(karamba* k, QString text, int x, int y) +{ + PyObject* pArgs = Py_BuildValue((char*)"(lOii)", k, QString2PyString(text), x, y); + return callObject("itemDropped", pArgs); +} + +bool KarambaPython::themeNotify(karamba* k, const char *from, const char *str) +{ + // WARNING WARNING WARNING i had to switch off thread locking to get + // this to work. callNotify is called from INSIDE another locked thread, + // so can never complete because themeNotify will expect locking to be + // released... + // + PyObject* pArgs = Py_BuildValue((char*)"(lss)", k, from, str); + return callObject("themeNotify", pArgs, false); +} + +bool KarambaPython::systrayUpdated(karamba* k) +{ + PyObject* pArgs = Py_BuildValue((char*)"(l)", k); + return callObject("systrayUpdated", pArgs); +} + +bool KarambaPython::desktopChanged(karamba* k, int desktop) +{ + PyObject* pArgs = Py_BuildValue((char*)"(li)", k, desktop); + return callObject("desktopChanged", pArgs); +} + +bool KarambaPython::wallpaperChanged(karamba* k, int desktop) +{ + PyObject* pArgs = Py_BuildValue((char*)"(li)", k, desktop); + return callObject("wallpaperChanged", pArgs); +} diff --git a/superkaramba/src/karamba_python.h b/superkaramba/src/karamba_python.h new file mode 100644 index 0000000..5f2032e --- /dev/null +++ b/superkaramba/src/karamba_python.h @@ -0,0 +1,85 @@ +/**************************************************************************** +* karamba_python.h - Functions for calling python scripts +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef KARAMBA_PYTHON_H +#define KARAMBA_PYTHON_H + +class QString; +class KPopupMenu; +class Task; +class Startup; +class karamba; +class Meter; +struct _object; +typedef struct _object PyObject; +struct _ts; +typedef struct _ts PyThreadState; +class ThemeFile; + +class KarambaPython +{ +protected: + bool pythonThemeExtensionLoaded; + PyObject *pName, *pModule; + PyObject *pDict; + static PyThreadState* mainThreadState; + + void getLock(PyThreadState** myThreadState); + PyObject* getFunc(const char* function); + void releaseLock(PyThreadState* myThreadState); + bool callObject(const char* func, PyObject* pArgs, bool lock=true); + +public: + KarambaPython(const ThemeFile& theme, bool reloading); + ~KarambaPython(); + + static void initPython(); + static void shutdownPython(); + + bool isExtensionLoaded() { return pythonThemeExtensionLoaded; }; + bool initWidget(karamba* k); + bool widgetUpdated(karamba* k); + bool widgetClosed(karamba* k); + bool menuOptionChanged(karamba* k, QString key, bool value); + bool meterClicked(karamba* k, Meter* meter, int button); + bool meterClicked(karamba* k, QString anchor, int button); + bool widgetClicked(karamba* k, int x, int y, int button); + bool keyPressed(karamba* k, const Meter* meter, const QString& text); + bool widgetMouseMoved(karamba* k, int x, int y, int button); + bool menuItemClicked(karamba* k, KPopupMenu* menu, long id); + bool activeTaskChanged(karamba* k, Task* t); + bool taskAdded(karamba* k, Task* t); + bool taskRemoved(karamba* k, Task* t); + bool startupAdded(karamba* k, Startup* t); + bool startupRemoved(karamba* k, Startup* t); + bool commandOutput(karamba* k, int pid, char *buffer); + bool commandFinished(karamba* k, int pid); + bool itemDropped(karamba* k, QString text, int x, int y); + bool themeNotify(karamba* k, const char *from, const char *txt); + bool systrayUpdated(karamba* k); + bool desktopChanged(karamba* k, int desktop); + bool wallpaperChanged(karamba* k, int desktop); +}; + +#endif // KARAMBA_PYTHON_H diff --git a/superkaramba/src/karambaapp.cpp b/superkaramba/src/karambaapp.cpp new file mode 100644 index 0000000..5357b01 --- /dev/null +++ b/superkaramba/src/karambaapp.cpp @@ -0,0 +1,427 @@ +/*************************************************************************** + * Copyright (C) 2003-2004 Adam Geitgey * + * Copyright (C) 2003 Hans Karlsson * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "themesdlg.h" +#include "karambainterface.h" +#include "karambaapp.h" +#include "dcopinterface_stub.h" +#include "karamba.h" +#include "superkarambasettings.h" +#include "qwidgetlist.h" + +int KarambaApplication::fd = -1; + +KarambaApplication::KarambaApplication() : + m_helpMenu(0), iface(0), themeListWindow(0), dcopIfaceStub(0), + karambaList(0), sysTrayIcon(0) +{ + iface = new KarambaIface(); + karambaList = new QObjectList(); + // register ourselves as a dcop client + dcopClient()->registerAs(name()); + dcopClient()->setDefaultObject(dcopIface()->objId()); +} + +KarambaApplication::~KarambaApplication() +{ + delete iface; + delete karambaList; + delete themeListWindow; + delete dcopIfaceStub; + //delete m_helpMenu; +} + +void KarambaApplication::initDcopStub(QCString app) +{ + if(app.isEmpty()) + app = dcopClient()->appId(); + dcopIfaceStub = new dcopIface_stub(app, iface->objId()); +} + +QString KarambaApplication::getMainKaramba() +{ + QStringList karambas = getKarambas(); + QStringList::Iterator it; + + for (it = karambas.begin(); it != karambas.end(); ++it) + { + if((*it).ascii() == dcopClient()->appId()) + continue; + dcopIface_stub dcop((*it).ascii(), iface->objId()); + if (dcop.isMainKaramba()) + return *it; + } + return QString::null; +} + +bool KarambaApplication::themeExists(QString pretty_name) +{ + QWidgetList *list = QApplication::allWidgets(); + QWidgetListIt it( *list ); // iterate over the widgets + QWidget * w; + while ( (w=it.current()) != 0 ) // for each widget... + { + ++it; + if (QString(w->name()).startsWith("karamba")) + { + karamba* k = (karamba*) w; + if (k->getPrettyName() == pretty_name) + return true; + } + } + delete list; // delete the list, not the widgets + return false; +} + +QStringList KarambaApplication::getKarambas() +{ + QCStringList applst = dcopClient()->registeredApplications(); + QCStringList::Iterator it; + QCString s; + QStringList result; + + for (it = applst.begin(); (s = *it) != 0; ++it) + { + if (s.left(strlen(name())) == name()) + result.append(s); + } + return result; +} + +void KarambaApplication::checkSuperKarambaDir() +{ + // Create ~/.superkaramba if necessary + QDir configDir(QDir::home().absPath() + "/.superkaramba"); + if (!configDir.exists()) + { + qWarning("~/.superkaramba doesn't exist"); + if(!configDir.mkdir(QDir::home().absPath() + "/.superkaramba")) + { + qWarning("Couldn't create Directory ~/.superkaramba"); + } + else + { + qWarning("created ~/.superkaramba"); + } + } +} + +void KarambaApplication::setUpSysTray(KAboutData* about) +{ + //kdDebug() << k_funcinfo << endl; + KAction* action; + + //Create theme list window. + //This will function as the main window for the tray icon + themeListWindow = new ThemesDlg(); + + //Set up systray icon + sysTrayIcon = new KSystemTray(themeListWindow); + + KPopupMenu *menu = sysTrayIcon->contextMenu(); + menu->insertItem(SmallIconSet("superkaramba"), + i18n("Hide System Tray Icon"), this, + SLOT(globalHideSysTray())); + menu->insertSeparator(); + + m_helpMenu = new KHelpMenu(themeListWindow, about); + action = KStdAction::help(m_helpMenu, SLOT(appHelpActivated()), + sysTrayIcon->actionCollection()); + action->plug(menu); + action = KStdAction::aboutApp(m_helpMenu, SLOT(aboutApplication()), + sysTrayIcon->actionCollection()); + action->plug(menu); + action = KStdAction::aboutKDE(m_helpMenu, SLOT(aboutKDE()), + sysTrayIcon->actionCollection()); + action->plug(menu); + + sysTrayIcon->setPixmap(sysTrayIcon->loadIcon("superkaramba")); + setToolTip(); + + if(SuperKarambaSettings::showSysTray()) + sysTrayIcon->show(); + else + sysTrayIcon->hide(); + + //Connect Systray icon's quit event + QObject::connect(sysTrayIcon, SIGNAL(quitSelected()), + this, SLOT(globalQuitSuperKaramba())); +} + +void KarambaApplication::showKarambaMenuExtension(bool show) +{ + QObject *k; + + if(show) + { + for (k = karambaList->first(); k; k = karambaList->next()) + { + ((karamba*)k)->showMenuExtension(); + } + } + else + { + for (k = karambaList->first(); k; k = karambaList->next()) + { + ((karamba*)k)->hideMenuExtension(); + } + } +} + +void KarambaApplication::setToolTip(const QString &tip) +{ + QToolTip::remove(sysTrayIcon); + if(tip.isNull()) + QToolTip::add(sysTrayIcon, i18n("SuperKaramba")); + else + QToolTip::add(sysTrayIcon, tip); +} + +void KarambaApplication::buildToolTip() +{ + if(!sysTrayIcon || !themeListWindow) + return; + + QStringList list = themeListWindow->runningThemes(); + + if(list.isEmpty()) + { + setToolTip(); + return; + } + + QString toolTip("
    " + i18n("SuperKaramba") + "
    "); + toolTip += ""; + + bool firstRun = true; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + { + if(firstRun) + { + toolTip += + ""; + firstRun = false; + } + else + { + toolTip += ""; + } + } + + toolTip += "
    " + + i18n("1 Running Theme:", "%n Running Themes:", list.count()) + + "" + (*it) + "
    " + (*it) + "
    "; + + setToolTip(toolTip); +} + +void KarambaApplication::checkPreviousSession(KApplication &app, + QStringList &lst) +{ + /****** + Try to restore a previous session if applicable. + */ + if (app.isSessionRestored()) + { + KConfig* config = app.sessionConfig(); + config->setGroup("General Options"); + QString restartThemes = config->readEntry("OpenThemes"); + + //Get themes that were running + lst = QStringList::split(QString(";"), restartThemes); + } +} + +void KarambaApplication::checkCommandLine(KCmdLineArgs *args, QStringList &lst) +{ + /****** + Not a saved session - check for themes given on command line + */ + if(args->count() > 0) + { + for(int i = 0; i < (args->count()); i++) + { + if( args->arg(i) && *args->arg(i) ) + { + KURL url = args->url(i); + + lst.push_back(url.path()); + } + } + } +} + +bool KarambaApplication::startThemes(QStringList &lst) +{ + bool result = false; + + for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) + { + karamba *mainWin = 0; + + mainWin = new karamba(*it , QString()); + mainWin->show(); + result = true; + } + + buildToolTip(); + return result; +} + +void KarambaApplication::addKaramba(karamba* k, bool reloading) +{ + if(!reloading && karambaApp->dcopStub()) + { + int instance = karambaApp->dcopStub()->themeAdded( + karambaApp->dcopClient()->appId(), k->theme().file()); + k->setInstance(instance); + } + karambaList->append(k); +} + +void KarambaApplication::deleteKaramba(karamba* k, bool reloading) +{ + if(!reloading && karambaApp->dcopStub()) + karambaApp->dcopStub()->themeClosed( + karambaApp->dcopClient()->appId(), k->theme().file(), k->instance()); + karambaList->removeRef(k); +} + +bool KarambaApplication::hasKaramba(karamba* k) +{ + return karambaList->containsRef(k) > 0; +} + +// XXX: I guess this should be made with mutex/semaphores +// but this is good for now... + +bool KarambaApplication::lockKaramba() +{ + QString file = QDir::home().absPath() + "/.superkaramba/.lock"; + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; + + fd = open(file.ascii(), O_CREAT | O_RDWR | O_TRUNC, mode); + if (fd < 0) + { + qWarning("Open failed in lock."); + return false; + } + //qDebug("lock %d", getpid()); + if(lockf(fd, F_LOCK, 0)) + { + qWarning("Lock failed."); + return false; + } + return true; +} + +void KarambaApplication::unlockKaramba() +{ + if(fd > 0) + { + lockf(fd, F_ULOCK, 0); + //qDebug("Unlock %d", getpid()); + close(fd); + fd = -1; + } +} + +void KarambaApplication::hideSysTray(bool hide) +{ + //kdDebug() << k_funcinfo << endl; + if(hide) + { + if(sysTrayIcon) + { + KMessageBox::information(0, + i18n("Hiding the system tray icon will keep SuperKaramba running " + "in background. To show it again use the theme menu."), + i18n("Hiding System Tray Icon"), "hideIcon"); + sysTrayIcon->hide(); + } + showKarambaMenuExtension(); + } + else + { + showKarambaMenuExtension(false); + if(sysTrayIcon) + sysTrayIcon->show(); + } +} + +void KarambaApplication::showThemeDialog() +{ + //kdDebug() << k_funcinfo << endl; + if(themeListWindow) + themeListWindow->show(); +} + +void KarambaApplication::quitSuperKaramba() +{ + if(themeListWindow) + themeListWindow->saveUserAddedThemes(); + qApp->closeAllWindows(); + qApp->quit(); +} + +void KarambaApplication::globalQuitSuperKaramba() +{ + QStringList apps = getKarambas(); + QStringList::Iterator it; + + for (it = apps.begin(); it != apps.end(); ++it) + { + dcopIface_stub dcop((*it).ascii(), dcopIface()->objId()); + dcop.quit(); + } +} + +void KarambaApplication::globalShowThemeDialog() +{ + QStringList apps = getKarambas(); + QStringList::Iterator it; + + for (it = apps.begin(); it != apps.end(); ++it) + { + dcopIface_stub dcop((*it).ascii(), dcopIface()->objId()); + dcop.showThemeDialog(); + } +} + +void KarambaApplication::globalHideSysTray(bool hide) +{ + //kdDebug() << k_funcinfo << endl; + QStringList apps = getKarambas(); + QStringList::Iterator it; + + SuperKarambaSettings::setShowSysTray(!hide); + SuperKarambaSettings::writeConfig(); + + for (it = apps.begin(); it != apps.end(); ++it) + { + dcopIface_stub dcop((*it).ascii(), dcopIface()->objId()); + dcop.hideSystemTray(hide); + } +} + +#include "karambaapp.moc" diff --git a/superkaramba/src/karambaapp.h b/superkaramba/src/karambaapp.h new file mode 100644 index 0000000..ef92244 --- /dev/null +++ b/superkaramba/src/karambaapp.h @@ -0,0 +1,95 @@ +/*************************************************************************** + * Copyright (C) 2003-2004 Adam Geitgey * + * Copyright (C) 2003 Hans Karlsson * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef KARAMBAAPP_H +#define KARAMBAAPP_H + +#include "kapplication.h" +#include +#include + +#undef KDE_3_2 +#undef KDE_3_3 +#if defined(KDE_MAKE_VERSION) +#if KDE_VERSION >= KDE_MAKE_VERSION(3,2,0) +#define KDE_3_2 +#endif +#if KDE_VERSION >= KDE_MAKE_VERSION(3,3,0) +#define KDE_3_3 +#endif +#endif + +#define karambaApp ((KarambaApplication*)qApp) + +class karamba; +class KarambaIface; +class KCmdLineArgs; +class ThemesDlg; +class dcopIface_stub; +class KHelpMenu; +class KAboutData; + +class KarambaApplication : public KApplication +{ + Q_OBJECT + + friend class KarambaIface; + + private: + static int fd; + KHelpMenu* m_helpMenu; + + void showKarambaMenuExtension(bool show = true); + void setToolTip(const QString &tip = QString::null); + + protected: + KarambaIface* iface; + ThemesDlg* themeListWindow; + dcopIface_stub* dcopIfaceStub; + QObjectList *karambaList; + KSystemTray* sysTrayIcon; + + public: + KarambaApplication(); + ~KarambaApplication(); + + QString getMainKaramba(); + QStringList getKarambas(); + bool themeExists(QString pretty_name); + void initDcopStub(QCString app = ""); + void setUpSysTray(KAboutData* about); + void checkPreviousSession(KApplication &app, QStringList &lst); + void checkCommandLine(KCmdLineArgs *args, QStringList &lst); + bool startThemes(QStringList &lst); + KarambaIface* dcopIface() { return iface; }; + dcopIface_stub* dcopStub() { return dcopIfaceStub; }; + QWidget* parentWindow() { return (QWidget*)themeListWindow; }; + + void addKaramba(karamba* k, bool reloading = false); + void deleteKaramba(karamba* k, bool reloading = false); + bool hasKaramba(karamba* k); + + static bool lockKaramba(); + static void unlockKaramba(); + static void checkSuperKarambaDir(); + + public slots: + void buildToolTip(); + void globalQuitSuperKaramba(); + void globalShowThemeDialog(); + void globalHideSysTray(bool hide = true); + + protected slots: + void quitSuperKaramba(); + void showThemeDialog(); + void hideSysTray(bool hide = true); +}; + +#endif // KARAMBAAPP_H diff --git a/superkaramba/src/karambainterface.cpp b/superkaramba/src/karambainterface.cpp new file mode 100644 index 0000000..7a201d8 --- /dev/null +++ b/superkaramba/src/karambainterface.cpp @@ -0,0 +1,153 @@ +/*************************************************************************** + * Copyright (C) 2004 by Petri Damsten * + * petri.damsten@iki.fi * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "karamba.h" +#include "karambainterface.h" +#include +#include "qwidgetlist.h" +#include "themesdlg.h" + +KarambaIface::KarambaIface(): DCOPObject("KarambaIface") +{ +} + +KarambaIface::~KarambaIface() +{ +} + +karamba* KarambaIface::getKaramba(QString name) +{ + QWidgetList *list = QApplication::allWidgets(); + QWidgetListIt it(*list); // iterate over the widgets + QWidget* w; + karamba* result = 0; + + while ( (w=it.current()) != 0 ) // for each widget... + { + ++it; + if (QString(w->name()).startsWith("karamba")) + { + karamba* k = (karamba*) w; + //if(k->prettyName == name) + if(k->theme().name() == name) + { + result = k; + break; + } + } + } + delete list; + return result; +} + +ThemesDlg* KarambaIface::getThemeWnd() +{ + QWidgetList *list = QApplication::allWidgets(); + QWidgetListIt it( *list ); // iterate over the widgets + QWidget* w; + ThemesDlg* result = 0; + + while ( (w=it.current()) != 0 ) // for each widget... + { + ++it; + if (QString(w->name()) == "ThemesLayout") + { + result = (ThemesDlg*) w; + break; + } + } + delete list; // delete the list, not the widgets + return result; +} + +void KarambaIface::openTheme(QString filename) +{ + QFileInfo file(filename); + if(file.exists()) + { + (new karamba(filename, QString()))->show(); + } +} + +void KarambaIface::openNamedTheme(QString filename, QString name, bool is_sub_theme) +{ + QFileInfo file(filename); + if(file.exists()) + { + (new karamba(filename, name, false, -1, is_sub_theme))->show(); + } +} + +void KarambaIface::closeTheme(QString name) +{ + kdDebug() << "KarambaIface::closeTheme: " << name << endl; + karamba* k; + + while((k = getKaramba(name))) + { + k->writeConfigData(); + k->close(true); + } +} + +int KarambaIface::themeAdded(QString appId, QString file) +{ + ThemesDlg* tw = getThemeWnd(); + if(tw) + return tw->addTheme(appId, file); + return -1; +} + +void KarambaIface::themeNotify(QString name, QString text) +{ + karamba* k = getKaramba(name); + if(k) + { + k->themeNotify(name, text); + } +} + +void KarambaIface::setIncomingData(QString name, QString text) +{ + karamba* k = getKaramba(name); + if(k) + { + k->_setIncomingData(text); + } +} + +void KarambaIface::themeClosed(QString appId, QString file, int instance) +{ + ThemesDlg* tw = getThemeWnd(); + if(tw) + tw->removeTheme(appId, file, instance); +} + +bool KarambaIface::isMainKaramba() +{ + if(getThemeWnd()) + return true; + return false; +} + +void KarambaIface::quit() +{ + karambaApp->quitSuperKaramba(); +} + +void KarambaIface::hideSystemTray(bool hide) +{ + karambaApp->hideSysTray(hide); +} + +void KarambaIface::showThemeDialog() +{ + karambaApp->showThemeDialog(); +} diff --git a/superkaramba/src/karambainterface.h b/superkaramba/src/karambainterface.h new file mode 100644 index 0000000..1202cc5 --- /dev/null +++ b/superkaramba/src/karambainterface.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2004 by Petri Damsten * + * petri.damsten@iki.fi * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef KARAMBAINTERFACE_H +#define KARAMBAINTERFACE_H + +#include "dcopinterface.h" + +class karamba; +class ThemeListWindow; + +class KarambaIface: virtual public dcopIface +{ +public: + KarambaIface(); + ~KarambaIface(); + karamba* getKaramba(QString name); + ThemesDlg* getThemeWnd(); + +public slots: + virtual void openTheme(QString filename); + virtual void openNamedTheme(QString filename, QString name, bool is_sub_theme); + virtual void closeTheme(QString name); + virtual void quit(); + virtual void hideSystemTray(bool show); + virtual void showThemeDialog(); + + virtual int themeAdded(QString appId, QString file); + virtual void themeClosed(QString appId, QString file, int instance); + virtual void themeNotify(QString name, QString text); + virtual void setIncomingData(QString name, QString text); + virtual bool isMainKaramba(); +}; + +#endif // KARAMBAINTERFACE_H diff --git a/superkaramba/src/karambalistboxitem.cpp b/superkaramba/src/karambalistboxitem.cpp new file mode 100644 index 0000000..703e3ef --- /dev/null +++ b/superkaramba/src/karambalistboxitem.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#include "karambalistboxitem.h" + +KarambaListBoxItem::KarambaListBoxItem( QListBox* listbox, const QString & text ) : QListBoxText(listbox, text) { + +} diff --git a/superkaramba/src/karambalistboxitem.h b/superkaramba/src/karambalistboxitem.h new file mode 100644 index 0000000..76427c2 --- /dev/null +++ b/superkaramba/src/karambalistboxitem.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#include "karamba.h" +#include + +class KarambaListBoxItem : public QListBoxText +{ + +public: + QString appId; + KarambaListBoxItem( QListBox* listbox, const QString & text=QString::null ); + +}; diff --git a/superkaramba/src/karambarootpixmap.cpp b/superkaramba/src/karambarootpixmap.cpp new file mode 100644 index 0000000..b733624 --- /dev/null +++ b/superkaramba/src/karambarootpixmap.cpp @@ -0,0 +1,36 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "karambarootpixmap.h" +#include "karamba.h" + +KarambaRootPixmap::KarambaRootPixmap(QWidget *w) : + KRootPixmap( w) +{ + widget = w; +} + +/*KarambaRootPixmap::KarambaRootPixmap() + : KRootPixmap(0) + { + +//widget = w; +} +*/ + +KarambaRootPixmap::~KarambaRootPixmap() +{ +} + +void KarambaRootPixmap::updateBackground (KSharedPixmap *kpm) +{ + ((karamba*)widget)->updateBackground(kpm); +} + diff --git a/superkaramba/src/karambarootpixmap.h b/superkaramba/src/karambarootpixmap.h new file mode 100644 index 0000000..9445528 --- /dev/null +++ b/superkaramba/src/karambarootpixmap.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef KARAMBAROOTPIXMAP_H +#define KARAMBAROOTPIXMAP_H + +#include +#include +#include + +//#include "karamba.h" + +/** +@author Hans Karlsson +*/ +class KarambaRootPixmap : public KRootPixmap +{ +public: + //KarambaRootPixmap(); + KarambaRootPixmap( QWidget *); + + ~KarambaRootPixmap(); + + +void updateBackground ( KSharedPixmap * ); + +private: +QWidget *widget; + + +}; + +#endif diff --git a/superkaramba/src/karambasessionmanaged.cpp b/superkaramba/src/karambasessionmanaged.cpp new file mode 100644 index 0000000..eccff7e --- /dev/null +++ b/superkaramba/src/karambasessionmanaged.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +* karambasessionmanaged.cpp - Karamba session management +* +* Copyright (C) 2004 - +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#include +#include +#include "karambasessionmanaged.h" +#include "karamba.h" +#include "qwidgetlist.h" + +bool KarambaSessionManaged::saveState(QSessionManager&) +{ + KConfig* config = kapp->sessionConfig(); + + config->setGroup("General Options"); + + QString openThemes=""; + + QWidgetList *list = QApplication::allWidgets(); + QWidgetListIt it( *list ); // iterate over the widgets + QWidget * w; + while ( (w=it.current()) != 0 ) // for each widget... + { + ++it; + if (QString(w->name()).startsWith("karamba")) + { + karamba* k = (karamba*) w; + if (k->isSubTheme()) + continue; + openThemes += QFileInfo(k->theme().file()).absFilePath(); + k->writeConfigData(); + openThemes += ";"; + } + } + delete list; // delete the list, not the widgets + + qDebug("Open themes %s", openThemes.ascii()); + config->writeEntry("OpenThemes", openThemes); + return true; +} + +bool KarambaSessionManaged::commitData(QSessionManager&) +{ + return true; +} diff --git a/superkaramba/src/karambasessionmanaged.h b/superkaramba/src/karambasessionmanaged.h new file mode 100644 index 0000000..9024549 --- /dev/null +++ b/superkaramba/src/karambasessionmanaged.h @@ -0,0 +1,30 @@ +/**************************************************************************** +* karambasessionmanaged.h - Karamba session management +* +* Copyright (C) 2004 - +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +class KarambaSessionManaged : public KSessionManaged +{ +public: + KarambaSessionManaged() {}; + + virtual bool commitData( QSessionManager& ); + virtual bool saveState( QSessionManager& ); +}; diff --git a/superkaramba/src/kwidgetlistbox.cpp b/superkaramba/src/kwidgetlistbox.cpp new file mode 100644 index 0000000..4749f64 --- /dev/null +++ b/superkaramba/src/kwidgetlistbox.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2005 Petri Damstn + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#include "kwidgetlistbox.h" +#include +#include + +KWidgetListbox::KWidgetListbox(QWidget *parent, const char *name) + : QTable(parent, name) +{ + setNumRows(0); + setNumCols(1); + setColumnStretchable(0, true); + setLeftMargin(0); + setTopMargin(0); + horizontalHeader()->hide(); + verticalHeader()->hide(); + setSelectionMode(QTable::NoSelection); + setFocusStyle(QTable::FollowStyle); + connect(this, SIGNAL(currentChanged(int, int)), + this, SLOT(selectionChanged(int, int))); + setHScrollBarMode(QScrollView::AlwaysOff); + setVScrollBarMode(QScrollView::Auto); +} + +KWidgetListbox::~KWidgetListbox() +{ + clear(); +} + +void KWidgetListbox::clear() +{ + for(int i = 0; i < numRows(); ++i) + clearCellWidget(i, 0); + setNumRows(0); +} + +int KWidgetListbox::insertItem(QWidget* item, int index) +{ + int row; + + if(index == -1) + { + row = numRows(); + setNumRows(row + 1); + } + else + return -1; + + setRowHeight(row, item->height()); + setCellWidget(row, 0, item); + setItemColors(row, even(row)); + return row; +} + +void KWidgetListbox::setSelected(QWidget* item) +{ + setSelected(index(item)); +} + +void KWidgetListbox::selectionChanged(int row, int col) +{ + ensureCellVisible(row, col); + updateColors(); + emit selected(row); +} + +void KWidgetListbox::removeItem(QWidget* item) +{ + removeItem(index(item)); +} + +void KWidgetListbox::removeItem(int index) +{ + removeRow(index); + updateColors(); +} + +void KWidgetListbox::setSelected(int index) +{ + setCurrentCell(index, 0); +} + +int KWidgetListbox::selected() const +{ + return currentRow(); +} + +QWidget* KWidgetListbox::selectedItem() const +{ + return item(selected()); +} + +QWidget* KWidgetListbox::item(int index) const +{ + return cellWidget(index, 0); +} + +int KWidgetListbox::index(QWidget* itm) const +{ + for(int i = 0; i < numRows(); ++i) + if(item(i) == itm) + return i; + return -1; +} + +bool KWidgetListbox::even(int index) +{ + int v = 0; + for(int i = 0; i < numRows(); ++i) + { + if(index == i) + break; + if(!isRowHidden(i)) + ++v; + } + return (v%2 == 0); +} + +void KWidgetListbox::updateColors() +{ + int v = 0; + for(int i = 0; i < numRows(); ++i) + { + if(!isRowHidden(i)) + { + setItemColors(i, (v%2 == 0)); + ++v; + } + } +} + +void KWidgetListbox::setItemColors(int index, bool even) +{ + QWidget* itm = item(index); + + if(index == selected()) + { + itm->setPaletteBackgroundColor(KGlobalSettings::highlightColor()); + itm->setPaletteForegroundColor(KGlobalSettings::highlightedTextColor()); + } + else if(even) + { + itm->setPaletteBackgroundColor(KGlobalSettings::baseColor()); + itm->setPaletteForegroundColor(KGlobalSettings::textColor()); + } + else + { + itm->setPaletteBackgroundColor( + KGlobalSettings::alternateBackgroundColor()); + itm->setPaletteForegroundColor(KGlobalSettings::textColor()); + } +} + +void KWidgetListbox::showItems(show_callback func, void* data) +{ + for(int i = 0; i < numRows(); ++i) + { + if(func == 0) + showRow(i); + else + { + if(func(i, item(i), data)) + showRow(i); + else + hideRow(i); + } + } + updateColors(); +} + +void KWidgetListbox::showEvent(QShowEvent*) +{ + //kdDebug() << k_funcinfo << endl; + repaintContents(false); +} + +void KWidgetListbox::paintCell(QPainter*, int, int, const QRect&, + bool, const QColorGroup&) +{ + //kdDebug() << k_funcinfo << endl; +} + +#include "kwidgetlistbox.moc" diff --git a/superkaramba/src/kwidgetlistbox.h b/superkaramba/src/kwidgetlistbox.h new file mode 100644 index 0000000..62a52a8 --- /dev/null +++ b/superkaramba/src/kwidgetlistbox.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2005 Petri Damstn + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#ifndef KWIDGETLISTBOX_H +#define KWIDGETLISTBOX_H + +#include + +/** +@author See README for the list of authors +*/ + +typedef bool (*show_callback) (int index, QWidget* widget, void* data); + +class KWidgetListbox : public QTable +{ + Q_OBJECT + + public: + KWidgetListbox(QWidget *parent = 0, const char *name = 0); + ~KWidgetListbox(); + + int insertItem(QWidget* item, int index = -1); + void setSelected(QWidget* item); + void setSelected(int index); + void removeItem(QWidget* item); + void removeItem(int index); + void clear(); + int selected() const; + QWidget* selectedItem() const; + QWidget* item(int index) const; + int index(QWidget* itm) const; + uint count() const { return numRows(); }; + + void showItems(show_callback func = 0, void* data = 0); + + void paintCell(QPainter* p, int row, int col, const QRect& cr, + bool selected, const QColorGroup& cg); + protected: + void setItemColors(int index, bool even); + void updateColors(); + bool even(int index); + virtual void showEvent(QShowEvent* e); + + protected slots: + void selectionChanged(int row, int col); + + signals: + void selected(int index); +}; + +#endif diff --git a/superkaramba/src/lineparser.cpp b/superkaramba/src/lineparser.cpp new file mode 100644 index 0000000..d923b6c --- /dev/null +++ b/superkaramba/src/lineparser.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (C) 2003 Hans Karlsson + * Copyright (c) 2005 Ryan Nickell + * Copyright (c) 2005 Petri Damsten + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#include "lineparser.h" +#include + +LineParser::LineParser(const QString& line) +{ + set(line); +} + +LineParser::~LineParser() +{ +} + +void LineParser::set(const QString& line) +{ + QRegExp rx("^\\s*(\\S+)"); + m_line = line; + + rx.search(m_line); + m_meter = rx.cap(1).upper(); +} + +int LineParser::getInt(QString w, int def) const +{ + QRegExp rx( "\\W+" + w +"=([-]?\\d+)", false ); + if (rx.search(m_line) != -1) + return rx.cap(1).toInt(); + else + return def; +} + +QColor LineParser::getColor(QString w, QColor def) const +{ + QRegExp rx( "\\W+" + w + "=([-]?\\d+),([-]?\\d+),([-]?\\d+)", false ); + if (rx.search(m_line) != -1) + return QColor(rx.cap(1).toInt(), rx.cap(2).toInt(), rx.cap(3).toInt()); + else + return def; +} + +QString LineParser::getString(QString w, QString def) const +{ + QString result; + QRegExp rx( "\\W+" + w + "=\"([^\"]*)\"", false ); + + bool found = (rx.search(m_line)==-1)?false:true; + if (rx.cap(1).isEmpty()) + { + rx = QRegExp(w + "=(\\S+)", false); + found = (rx.search(m_line)==-1)?false:true; + result = rx.cap(1); + } + else + { + result = rx.cap(1); + } + if(found) + return result; + else + return def; +} + +bool LineParser::getBoolean(QString w, bool def) const +{ + QString boolean = getString(w, "-").lower(); + if(boolean == "-") + return def; + else if (boolean == "true") // true / false + return true; + else if (boolean == "1") // 1 / 0 + return true; + else if (boolean == "on") // on / off + return true; + return false; +} diff --git a/superkaramba/src/lineparser.h b/superkaramba/src/lineparser.h new file mode 100644 index 0000000..b877e6c --- /dev/null +++ b/superkaramba/src/lineparser.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (C) 2003 Hans Karlsson + * Copyright (c) 2005 Ryan Nickell + * Copyright (c) 2005 Petri Damsten + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#ifndef LINEPARSER_H +#define LINEPARSER_H + +/** +@author See README for the list of authors +*/ + +#include +#include + +class LineParser +{ + public: + LineParser(const QString& line = QString::null); + ~LineParser(); + + void set(const QString& line); + + int getInt(QString w, int def = 0) const; + QColor getColor(QString w, QColor def = QColor()) const; + QString getString(QString w, QString def = QString()) const; + bool getBoolean(QString w, bool def = false) const; + + const QString& meter() const { return m_meter; }; + + private: + QString m_line; + QString m_meter; +}; + +#endif diff --git a/superkaramba/src/main.cpp b/superkaramba/src/main.cpp new file mode 100644 index 0000000..14c651c --- /dev/null +++ b/superkaramba/src/main.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2003 Hans Karlsson + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "karamba.h" +#include "karambasessionmanaged.h" +#include "karambainterface.h" +#include "karamba_python.h" + +static const char *description = + I18N_NOOP("A KDE Eye-candy Application"); + +static const char *version = "0.42"; + +static KCmdLineOptions options[] = +{ + // { "+[URL]", I18N_NOOP( "Document to open" ), 0 }, + // { "!nosystray", I18N_NOOP("Disable systray icon"), 0 }, + { "+file", I18N_NOOP("A required argument 'file'"), 0 }, + { 0, 0, 0 } +}; + +// This is for redirecting all qWarning, qDebug,... messages to file. +// Usefull when testing session management issues etc. +// #define KARAMBA_LOG 1 + +#ifdef KARAMBA_LOG + +void karambaMessageOutput(QtMsgType type, const char *msg) +{ + FILE* fp = fopen("/tmp/karamba.log", "a"); + if(fp) + { + pid_t pid = getpid(); + + switch ( type ) + { + case QtDebugMsg: + fprintf( fp, "Debug (%d): %s\n", pid, msg ); + break; + case QtWarningMsg: + if (strncmp(msg, "X Error", 7) != 0) + fprintf( fp, "Warning (%d): %s\n", pid, msg ); + break; + case QtFatalMsg: + fprintf( fp, "Fatal (%d): %s\n", pid, msg ); + abort(); // deliberately core dump + } + fclose(fp); + } +} + +#endif + +int main(int argc, char **argv) +{ +#ifdef KARAMBA_LOG + qInstallMsgHandler(karambaMessageOutput); +#endif + KAboutData about("superkaramba", I18N_NOOP("SuperKaramba"), + version, description, + KAboutData::License_GPL, + "(c) 2003-2006 The SuperKaramba developers"); + about.addAuthor("Adam Geitgey", 0, "adam@rootnode.org"); + about.addAuthor("Hans Karlsson", 0, "karlsson.h@home.se"); + about.addAuthor("Ryan Nickell", 0, "p0z3r@earthlink.net"); + about.addAuthor("Petri Damstén", 0, "petri.damsten@iki.fi"); + about.addAuthor("Alexander Wiedenbruch", 0, "mail@wiedenbruch.de"); + about.addAuthor("Luke Kenneth Casson Leighton", 0, "lkcl@lkcl.net"); + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions(options); + KarambaSessionManaged ksm; + //karamba *mainWin = 0; + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + QStringList lst; + int ret = 0; + + // Create ~/.superkaramba if necessary + KarambaApplication::checkSuperKarambaDir(); + + KarambaApplication::lockKaramba(); + + KarambaApplication app; + + QString mainAppId = app.getMainKaramba(); + if(!mainAppId.isEmpty()) + { + app.initDcopStub(mainAppId.ascii()); + } + else + { + //Set up systray icon + app.setUpSysTray(&about); + app.initDcopStub(); + } + + KarambaApplication::unlockKaramba(); + + app.connect(qApp,SIGNAL(lastWindowClosed()),qApp,SLOT(quit())); + + // Try to restore a previous session if applicable. + app.checkPreviousSession(app, lst); + if( (lst.size() == 0) && !app.isRestored() ) + { + //Not a saved session - check for themes given on command line + app.checkCommandLine(args, lst); + + if(lst.size() == 0) + { + //No themes given on command line and no saved session. + //Show welcome dialog. + app.globalShowThemeDialog(); + } + } + + args->clear(); + + KarambaPython::initPython(); + //qDebug("startThemes"); + if(app.startThemes(lst) || mainAppId.isEmpty()) + ret = app.exec(); + KarambaPython::shutdownPython(); + return ret; +} diff --git a/superkaramba/src/memsensor.cpp b/superkaramba/src/memsensor.cpp new file mode 100644 index 0000000..21d9f35 --- /dev/null +++ b/superkaramba/src/memsensor.cpp @@ -0,0 +1,359 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "memsensor.h" +#include +#include +#include +#include +#include + +#ifdef Q_OS_FREEBSD +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if defined(Q_OS_NETBSD) +#include +#include +#include +#include +#endif + +#include + +#if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD) +/* define pagetok in terms of pageshift */ +#define pagetok(size) ((size) << pageshift) +#endif + +MemSensor::MemSensor(int msec) : Sensor(msec) +{ +#if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD) + /* get the page size with "getpagesize" and calculate pageshift from it */ + int pagesize = getpagesize(); + pageshift = 0; + while (pagesize > 1) + { + pageshift++; + pagesize >>= 1; + } + + /* we only need the amount of log(2)1024 for our conversion */ + pageshift -= 10; +# if defined(Q_OS_FREEBSD) && defined(__FreeBSD_version) && __FreeBSD_version >= 500018 + kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY, "kvm_open"); +# elif defined Q_OS_FREEBSD + connect(&ksp, SIGNAL(receivedStdout(KProcess *, char *, int )), + this,SLOT(receivedStdout(KProcess *, char *, int ))); + connect(&ksp, SIGNAL(processExited(KProcess *)), + this,SLOT(processExited( KProcess * ))); + + swapTotal = swapUsed = 0; + + MaxSet = false; + + readValues(); +# endif +#else + readValues(); +#endif +} + +MemSensor::~MemSensor() +{} + +#ifdef Q_OS_FREEBSD +void MemSensor::receivedStdout(KProcess *, char *buffer, int len ) +{ + buffer[len] = 0; + sensorResult += QString( QCString(buffer) ); +} +#else +void MemSensor::receivedStdout(KProcess *, char *, int) +{ +} +#endif + +void MemSensor::processExited(KProcess *) +{ +#ifdef Q_OS_FREEBSD + QStringList stringList = QStringList::split('\n',sensorResult); + sensorResult = ""; + QStringList itemsList = QStringList::split(' ', stringList[1]); + + swapUsed = itemsList[2].toInt(); + swapTotal = itemsList[1].toInt(); +#endif +} + +int MemSensor::getMemTotal() +{ +#if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD) + static int mem = 0; + size_t size = sizeof(mem); + + sysctlbyname("hw.physmem", &mem, &size, NULL, 0); + return (mem / 1024); +#else + QRegExp rx( "MemTotal:\\s*(\\d+)" ); + rx.search( meminfo ); + return ( rx.cap(1).toInt() ); +#endif +} + +int MemSensor::getMemFree() +{ +#ifdef Q_OS_FREEBSD + static int mem = 0; + size_t size = sizeof(mem); + + sysctlbyname("vm.stats.vm.v_free_count", &mem, &size, NULL, 0); + return (pagetok(mem)); +#elif defined(Q_OS_NETBSD) + struct uvmexp_sysctl uvmexp; + int mib[2]; + size_t ssize; + mib[0] = CTL_VM; + mib[1] = VM_UVMEXP2; + ssize = sizeof(uvmexp); + sysctl(mib,2,&uvmexp,&ssize,NULL,0); + return pagetok(uvmexp.free); +#else + QRegExp rx( "MemFree:\\s*(\\d+)" ); + rx.search( meminfo ); + return ( rx.cap(1).toInt() ); +#endif +} + +int MemSensor::getBuffers() +{ +#ifdef Q_OS_FREEBSD + static int mem = 0; + size_t size = sizeof(mem); + + sysctlbyname("vfs.bufspace", &mem, &size, NULL, 0); + return (mem / 1024); +#elif defined(Q_OS_NETBSD) + static int buf_mem = 0; + size_t size = sizeof(buf_mem); + + sysctlbyname("vm.bufmem", &buf_mem, &size, NULL, 0); + return (buf_mem / 1024); +#else + QRegExp rx( "Buffers:\\s*(\\d+)" ); + rx.search( meminfo ); + return ( rx.cap(1).toInt() ); +#endif +} + +int MemSensor::getCached() +{ +#ifdef Q_OS_FREEBSD + static int mem = 0; + size_t size = sizeof(mem); + + sysctlbyname("vm.stats.vm.v_cache_count", &mem, &size, NULL, 0); + return (pagetok(mem)); +#elif defined(Q_OS_NETBSD) + return 0; +#else + QRegExp rx1( "Cached:\\s*(\\d+)" ); + QRegExp rx2( "SwapCached:\\s*(\\d+)" ); + rx1.search( meminfo ); + rx2.search( meminfo ); + return ( rx1.cap(1).toInt() + rx2.cap(1).toInt() ); +#endif +} + + +int MemSensor::getSwapTotal() +{ +#ifdef Q_OS_FREEBSD +# if defined(__FreeBSD_version) && __FreeBSD_version >= 500018 + int n = -1; + int pagesize = getpagesize(); + int retavail = 0; + + if (kd != NULL) + n = kvm_getswapinfo(kd, &swapinfo, 1, 0); + + if (n < 0 || swapinfo.ksw_total == 0) + return(0); + + retavail = swapinfo.ksw_total * pagesize / 1024; + + return(retavail); +#else + return(swapTotal); +# endif +#elif defined(Q_OS_NETBSD) + struct uvmexp_sysctl uvmexp; + int STotal = 0; + int pagesize = 1; + int mib[2]; + size_t ssize; + mib[0] = CTL_VM; + mib[1] = VM_UVMEXP; + ssize = sizeof(uvmexp); + + if (sysctl(mib,2,&uvmexp,&ssize,NULL,0) != -1) { + pagesize = uvmexp.pagesize; + STotal = (pagesize*uvmexp.swpages) >> 10; + } + return STotal; +#else + QRegExp rx( "SwapTotal:\\s*(\\d+)" ); + rx.search( meminfo ); + return ( rx.cap(1).toInt() ); +#endif +} + +int MemSensor::getSwapFree() +{ +#ifdef Q_OS_FREEBSD +# if defined(__FreeBSD_version) && __FreeBSD_version >= 500018 + int n = -1; + int pagesize = getpagesize(); + int retfree = 0; + + if (kd != NULL) + n = kvm_getswapinfo(kd, &swapinfo, 1, 0); + if (n < 0 || swapinfo.ksw_total == 0) + return(0); + + retfree = (swapinfo.ksw_total - swapinfo.ksw_used) * pagesize / 1024; + + return(retfree); +# else + return(swapTotal - swapUsed); +# endif +#elif defined(Q_OS_NETBSD) + struct uvmexp_sysctl uvmexp; + int STotal = 0; + int SFree = 0; + int SUsed = 0; + int pagesize = 1; + int mib[2]; + size_t ssize; + mib[0] = CTL_VM; + mib[1] = VM_UVMEXP; + ssize = sizeof(uvmexp); + + if (sysctl(mib,2,&uvmexp,&ssize,NULL,0) != -1) { + pagesize = uvmexp.pagesize; + STotal = (pagesize*uvmexp.swpages) >> 10; + SUsed = (pagesize*uvmexp.swpginuse) >> 10; + SFree = STotal - SUsed; + } + return SFree; +#else + QRegExp rx( "SwapFree:\\s*(\\d+)" ); + rx.search( meminfo ); + return ( rx.cap(1).toInt() ); +#endif +} + +void MemSensor::readValues() +{ +#if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD) +# if defined(Q_OS_FREEBSD) && !(defined(__FreeBSD_version) && __FreeBSD_version >= 500018) + ksp.clearArguments(); + ksp << "swapinfo"; + ksp.start( KProcess::NotifyOnExit,KProcIO::Stdout); +# endif +#else + QFile file("/proc/meminfo"); + QString line; + if ( file.open(IO_ReadOnly | IO_Translate) ) + { + QTextStream t( &file ); // use a text stream + meminfo = t.read(); + file.close(); + } +#endif +} + +void MemSensor::update() +{ + readValues(); + QString format; + SensorParams *sp; + Meter *meter; + QObjectListIt it( *objList ); +#if defined(Q_OS_FREEBSD) && !(defined(__FreeBSD_version) && __FreeBSD_version >= 500018) + bool set = false; +#endif + int totalMem = getMemTotal(); + int usedMem = totalMem - getMemFree(); + int usedMemNoBuffers = usedMem - getBuffers() - getCached(); + int totalSwap = getSwapTotal(); + int usedSwap = totalSwap - getSwapFree(); + + while (it != 0) + { + sp = (SensorParams*)(*it); +#if defined(Q_OS_FREEBSD) && !(defined(__FreeBSD_version) && __FreeBSD_version >= 500018) + if ( (!MaxSet) && (totalSwap > 0) ) { + setMaxValue(sp); + bool set = true; + } +#endif + meter = sp->getMeter(); + format = sp->getParam("FORMAT"); + if (format.length() == 0 ) + { + format = "%um"; + } + + format.replace( QRegExp("%fmb", false), QString::number( (int)(( totalMem - usedMemNoBuffers)/1024.0+0.5))); + format.replace( QRegExp("%fm", false), QString::number( (int)( ( totalMem - usedMem )/1024.0+0.5) )); + + format.replace( QRegExp("%umb", false), QString::number( (int)((usedMemNoBuffers)/1024.0+0.5))); + format.replace( QRegExp("%um", false), QString::number( (int)((usedMem)/1024.0+0.5 ))); + + format.replace( QRegExp("%tm", false), QString::number( (int)( (totalMem)/1024.0+0.5))); + + format.replace( QRegExp("%fs", false), QString::number( (int)((totalSwap - usedSwap)/1024.0+0.5))); + format.replace( QRegExp("%us", false), QString::number( (int)(usedSwap/1024.0+0.5))); + format.replace( QRegExp("%ts", false), QString::number( (int)(totalSwap/1024.0+0.5))); + + meter->setValue(format); + ++it; + } +#if defined(Q_OS_FREEBSD) && !(defined(__FreeBSD_version) && __FreeBSD_version >= 500018) + if (set) + MaxSet = true; +#endif +} + +void MemSensor::setMaxValue( SensorParams *sp ) +{ + Meter *meter; + meter = sp->getMeter(); + QString f; + f = sp->getParam("FORMAT"); + + if (f.length() == 0 ) + { + f = "%um"; + } + if( f=="%fm" || f== "%um" || f=="%fmb" || f=="%umb" ) + meter->setMax( getMemTotal() / 1024 ); + if( f=="%fs" || f== "%us" ) + meter->setMax( getSwapTotal() / 1024 ); +} + +#include "memsensor.moc" diff --git a/superkaramba/src/memsensor.h b/superkaramba/src/memsensor.h new file mode 100644 index 0000000..a9e425e --- /dev/null +++ b/superkaramba/src/memsensor.h @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef MEMSENSOR_H +#define MEMSENSOR_H +#include "sensor.h" +#include +#include +#include +#include + +#ifdef __FreeBSD__ +#include +#include +#include +#endif + +class MemSensor : public Sensor +{ +Q_OBJECT +public: + + MemSensor( int interval ); + ~MemSensor(); + + int getMemTotal(); + int getMemFree(); + int getBuffers(); + int getCached(); + + int getSwapTotal(); + int getSwapFree(); + + void update(); + void setMaxValue( SensorParams *sp ); + QString getMemLine(); + +private: + QString meminfo; + void readValues(); +#if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) + int pageshift; /* log base 2 of the pagesize */ + QString sensorResult; + int swapTotal; + int swapUsed; +# if defined(Q_OS_FREEBSD) && defined(__FreeBSD_version) && __FreeBSD_version >= 500018 + kvm_t *kd; + kvm_swap swapinfo; +# elif defined(Q_OS_FREEBSD) + KShellProcess ksp; + bool MaxSet; +# endif +#endif + +private slots: + void receivedStdout(KProcess *, char *buffer, int); + void processExited(KProcess *); + +}; + +#endif // MEMSENSOR_H diff --git a/superkaramba/src/menu_python.cpp b/superkaramba/src/menu_python.cpp new file mode 100644 index 0000000..0a85836 --- /dev/null +++ b/superkaramba/src/menu_python.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +* menu_python.h - Functions for menu python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "meter.h" +#include "meter_python.h" +#include "menu_python.h" + +long createMenu(long widget) +{ + karamba* currTheme = (karamba*)widget; + + KPopupMenu* tmp = new KPopupMenu(currTheme); + currTheme->menuList->append (tmp ); + + currTheme->connect(tmp, SIGNAL(activated(int)), currTheme, + SLOT(passMenuItemClicked(int))); + + return (long)tmp; +} + +PyObject* py_create_menu(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:createMenu", &widget)) + return NULL; + return Py_BuildValue((char*)"l", createMenu(widget)); +} + +bool menuExists(karamba* currTheme, KPopupMenu* menu) +{ + bool foundMenu = false; + KPopupMenu* tmp; + + for(int i = 0; i < (int)currTheme->menuList->count(); i++) + { + if(i==0) + { + tmp = (KPopupMenu*) currTheme->menuList->first(); + } + else + { + tmp = (KPopupMenu*) currTheme->menuList->next(); + } + if(tmp != 0) + { + if(tmp == menu) + { + foundMenu = true; + break; + } + } + } + return foundMenu; +} + +long deleteMenu(long widget, long menu) +{ + karamba* currTheme = (karamba*)widget; + KPopupMenu* tmp = (KPopupMenu*)menu; + + currTheme->menuList->removeRef(tmp); + + return 1; +} + +PyObject* py_delete_menu(PyObject *, PyObject *args) +{ + long widget, menu; + if (!PyArg_ParseTuple(args, (char*)"ll:deleteMenu", &widget, &menu)) + return NULL; + return Py_BuildValue((char*)"l", deleteMenu(widget, menu)); +} + +long addMenuItem(long widget, long menu, QString text, QString icon) +{ + karamba* currTheme = (karamba*)widget; + KPopupMenu* tmp = (KPopupMenu*)menu; + + long id = 0; + if(menuExists(currTheme, tmp)) + { + id = tmp->insertItem(SmallIconSet(icon), text); + } + return id; +} + +PyObject* py_add_menu_item(PyObject *, PyObject *args) +{ + long widget, menu; + char* i; + PyObject* t; + if (!PyArg_ParseTuple(args, (char*)"llOs:addMenuItem", &widget, &menu, &t, &i)) + return NULL; + QString icon; + QString text; + icon.setAscii(i); + text = PyString2QString(t); + return Py_BuildValue((char*)"l", addMenuItem(widget, menu, text, icon)); +} + +long addMenuSeparator(long widget, long menu) +{ + karamba* currTheme = (karamba*)widget; + KPopupMenu* tmp = (KPopupMenu*)menu; + + long id = 0; + if(menuExists(currTheme, tmp)) + { + id = tmp->insertSeparator(); + } + + return id; +} + +PyObject* py_add_menu_separator(PyObject *, PyObject *args) +{ + long widget, menu; + + if (!PyArg_ParseTuple(args, (char*)"ll:addMenuSeparator", &widget, &menu)) + return NULL; + + return Py_BuildValue((char*)"l", addMenuSeparator(widget, menu)); +} + +long removeMenuItem(long widget, long menu, long id) +{ + karamba* currTheme = (karamba*)widget; + KPopupMenu* tmp = (KPopupMenu*)menu; + + if(menuExists(currTheme,tmp)) + { + tmp->removeItem(id); + return 1; + } + else + { + return 0; + } +} + +PyObject* py_remove_menu_item(PyObject *, PyObject *args) +{ + long widget, menu, id; + if (!PyArg_ParseTuple(args, (char*)"lll:removeMenuItem", &widget, &menu, &id)) + return NULL; + return Py_BuildValue((char*)"l", removeMenuItem(widget, menu, id)); +} + +long popupMenu(long widget, long menu, long x, long y) +{ + karamba* currTheme = (karamba*)widget; + KPopupMenu* tmp = (KPopupMenu*)menu; + + if(menuExists(currTheme,tmp)) + { + tmp->popup(currTheme->mapToGlobal( QPoint(x,y) )); + return 1; + } + else + { + return 0; + } +} + +PyObject* py_popup_menu(PyObject *, PyObject *args) +{ + long widget, menu, x, y; + if (!PyArg_ParseTuple(args, (char*)"llll:popupMenu", &widget, &menu, &x, &y)) + return NULL; + return Py_BuildValue((char*)"l", popupMenu(widget, menu, x, y)); +} + diff --git a/superkaramba/src/menu_python.h b/superkaramba/src/menu_python.h new file mode 100644 index 0000000..88f8ea0 --- /dev/null +++ b/superkaramba/src/menu_python.h @@ -0,0 +1,124 @@ +/**************************************************************************** +* menu_python.h - Functions for menu python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef MENU_PYTHON_H +#define MENU_PYTHON_H + +/** Menu/createMenu +* +* SYNOPSIS +* long createMenu(widget) +* DESCRIPTION +* This creates an empty popup menu and returns a pointer to the menu. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* pointer to menu +*/ +PyObject* py_create_menu(PyObject *self, PyObject *args); + +/** Menu/deleteMenu +* +* SYNOPSIS +* long deleteMenu(widget, menu) +* DESCRIPTION +* This deletes the referenced menu if that menu exists. +* ARGUMENTS +* * long widget -- karamba +* * long menu -- pointer to menu +* RETURN VALUE +* 1 if menu existed and was deleted, returns 0 otherwise. +*/ +PyObject* py_delete_menu(PyObject *self, PyObject *args); + +/** Menu/addMenuItem +* +* SYNOPSIS +* long addMenuItem(widget, menu, text, icon) +* DESCRIPTION +* This adds an entry to the given menu with label text and with given icon. +* icon can be just an application name in which case the user's current +* icon set is used, or can be a path to a 16x16 png file. +* +* The function returns the id of the menu item, which identifies that popup +* menu item uniquely among popupmenu items application-wide or returns 0 +* if the given menu doesn't exist. +* ARGUMENTS +* * long widget -- karamba +* * long menu -- pointer to menu +* * string text -- text for menu item +* * string icon -- icon +* RETURN VALUE +* menu item id +*/ +PyObject* py_add_menu_item(PyObject *self, PyObject *args); + +/** Menu/addMenuSeparator +* +* SYNOPSIS +* long addMenuSeparator(widget, menu) +* DESCRIPTION +* This adds an menu separator to the given menu. +* ARGUMENTS +* * long widget -- karamba +* * long menu -- pointer to menu +* RETURN VALUE +* menu item id +*/ +PyObject* py_add_menu_separator(PyObject *self, PyObject *args); + +/** Menu/removeMenuItem +* +* SYNOPSIS +* long removeMenuItem(widget, menu, id) +* DESCRIPTION +* This removes the item with given id from given menu if that menu exists. +* ARGUMENTS +* * long widget -- karamba +* * long menu -- pointer to menu +* * long id -- menu item id +* RETURN VALUE +* 1 if the menu item existed and was removed or returns zero otherwise. +*/ +PyObject* py_remove_menu_item(PyObject *self, PyObject *args); + +/** Menu/popupMenu +* +* SYNOPSIS +* long popupMenu(widget, menu, x, y) +* DESCRIPTION +* This pops up the given menu at the given co-ordinates. The co-ordinates +* are relative to the widget, not the screen. You can use negative +* co-ordinates to make a menu appear to the right of or above your theme. +* ARGUMENTS +* * long widget -- karamba +* * long menu -- pointer to menu +* * long x -- x coordinate +* * long y -- y coordinate +* RETURN VALUE +* 1 if the menu existed and was popped up, returns 0 otherwise. +*/ +PyObject* py_popup_menu(PyObject *self, PyObject *args); + +#endif // MENU_PYTHON_H diff --git a/superkaramba/src/meter.cpp b/superkaramba/src/meter.cpp new file mode 100644 index 0000000..efc8a13 --- /dev/null +++ b/superkaramba/src/meter.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "meter.h" + +Meter::Meter(karamba* k, int ix, int iy, int iw, int ih): + boundingBox(ix, iy, iw, ih), leftButtonAction(""), middleButtonAction(""), + rightButtonAction(""), clickable(true), hidden(0), minValue(0), maxValue(0), + color(0,0,0), m_karamba(k) +{ +} + +Meter::Meter(karamba* k): + boundingBox(0, 0, 0, 0), leftButtonAction(""), middleButtonAction(""), + rightButtonAction(""), clickable(true), hidden(0), minValue(0), maxValue(0), + color(0,0,0), m_karamba(k) +{ +} + +Meter::~Meter() +{ +} + +bool Meter::click(QMouseEvent*) +{ + return false; +} + +void Meter::setSize(int ix, int iy, int iw, int ih) +{ + boundingBox.setRect(ix, iy, iw, ih); + recalculateValue(); +} + +void Meter::setThemePath( QString path ) +{ + themePath = path; +} + +int Meter::getX() +{ + return boundingBox.x(); +} + +int Meter::getY() +{ + return boundingBox.y(); +} + +void Meter::setX(int newx) +{ + int temp = boundingBox.width(); + boundingBox.setX(newx); + boundingBox.setWidth(temp); +} + +void Meter::setY(int newy) +{ + int temp = boundingBox.height(); + boundingBox.setY(newy); + boundingBox.setHeight(temp); +} + +int Meter::getWidth() +{ + return boundingBox.width(); +} +int Meter::getHeight() +{ + return boundingBox.height(); +} + +void Meter::setWidth(int width) +{ + boundingBox.setWidth(width); + recalculateValue(); +} + +void Meter::setHeight(int height) +{ + boundingBox.setHeight(height); + recalculateValue(); +} + +QRect Meter::getBoundingBox() +{ + return boundingBox; +} + +void Meter::setEnabled(bool e) +{ + clickable = e; +} + +bool Meter::isEnabled() +{ + return clickable; +} + +bool Meter::insideActiveArea(int x, int y) +{ + return boundingBox.contains(x, y) && clickable; +} + +#include "meter.moc" diff --git a/superkaramba/src/meter.h b/superkaramba/src/meter.h new file mode 100644 index 0000000..8d1aeaf --- /dev/null +++ b/superkaramba/src/meter.h @@ -0,0 +1,99 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef METER_H +#define METER_H + +#include +#include +#include +#include +#include + +#include + +class karamba; + +class Meter : public QObject +{ +Q_OBJECT +public: + + Meter(karamba* k, int ix,int iy,int iw,int ih); + Meter(karamba* k); + virtual ~Meter(); + virtual int getX(); + virtual int getY(); + virtual int getWidth(); + virtual int getHeight(); + virtual void setX(int); + virtual void setY(int); + virtual void setWidth(int); + virtual void setHeight(int); + + virtual void setSize(int ix, int iy, int iw, int ih); + + virtual void setMax(long max) { maxValue = max; }; + virtual void setMin(long min) { minValue = min; }; + virtual long getMax() { return minValue; }; + virtual long getMin() { return maxValue; }; + + void setThemePath( QString ); + + virtual void mUpdate(QPainter *)=0 ; + + virtual void setValue(long) {}; + virtual long getValue() { return -1; }; + virtual void setValue(QString) {}; + virtual QString getStringValue() const { return QString::null; }; + virtual void recalculateValue() {}; + + virtual void setColor(QColor clr) { color = clr; }; + virtual QColor getColor() { return color; }; + + virtual void show() { hidden = 0; }; + virtual void hide() { hidden = 1; }; + + QRect getBoundingBox(); + + // true when given coordinate point is inside the meters + // active reagion and meter is enabled + virtual bool insideActiveArea(int, int); + + // returns true when callback meterClicked should be called. + virtual bool click( QMouseEvent* ); + + void setEnabled(bool); + bool isEnabled(); + + /* + void setOnClick( QString ); + void setOnMiddleClick( QString ); + */ + +protected: // Protected attributes + QString themePath; + + QRect boundingBox; + + // Actions to execute when clicked on meter + QString leftButtonAction; + QString middleButtonAction; + QString rightButtonAction; + + bool clickable; + int hidden; + long minValue; + long maxValue; + + QColor color; + karamba* m_karamba; +}; + +#endif // METER_H diff --git a/superkaramba/src/meter_python.cpp b/superkaramba/src/meter_python.cpp new file mode 100644 index 0000000..029820d --- /dev/null +++ b/superkaramba/src/meter_python.cpp @@ -0,0 +1,373 @@ +/*************************************************************************** + * Copyright (C) 2003-2004 Adam Geitgey * + * Copyright (C) 2003 Hans Karlsson * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "karambaapp.h" +#include "meter.h" +#include "meter_python.h" +#include "lineparser.h" + +bool checkKaramba(long widget) +{ +/* + if (!karambaApp) + { + PyErr_SetString(PyExc_ValueError, "app pointer was 0."); + return false; + } +*/ + if (!widget) + { + PyErr_SetString(PyExc_ValueError, "widget pointer was 0."); + return false; + } + if (!karambaApp->hasKaramba((karamba*)widget)) + { + QString tmp; + + tmp.sprintf("no %x widget found.", (unsigned int)widget); + PyErr_SetString(PyExc_ValueError, tmp.ascii()); + return false; + } + return true; +} + +bool checkMeter(long widget, long meter, const char* type) +{ + if (!meter) + { + PyErr_SetString(PyExc_ValueError, "meter pointer was 0."); + return false; + } + if (!((karamba*)widget)->hasMeter((Meter*)meter)) + { + QString tmp; + + tmp.sprintf("widget does not have meter %x.", (unsigned int)meter); + PyErr_SetString(PyExc_ValueError, tmp.ascii()); + return false; + } + if (!((QObject*)meter)->isA(type)) + { + QString tmp; + + tmp.sprintf("meter is not type of %s.", type); + PyErr_SetString(PyExc_TypeError, tmp.ascii()); + return false; + } + return true; +} + +bool checkKarambaAndMeter(long widget, long meter, const char* type) +{ + return checkKaramba(widget) && checkMeter(widget, meter, type); +} + +// This just throws awya extra bytes. +// I guess there is a better way to do this... +QString fromUcs4(Q_UINT32* ucs4) +{ + QString result = ""; + while(*ucs4 != 0) + { + result += QChar((Q_UINT16)*ucs4); + ++ucs4; + } + return result; +} + +// Converts a Python String to a QString with Unicode support +QString PyString2QString(PyObject* text) +{ + QString qtext; + if (PyString_CheckExact(text)) + { + char* t = PyString_AsString(text); + qtext.setAscii(t); + } + else if (PyUnicode_CheckExact(text)) + { + Py_UNICODE* t = PyUnicode_AsUnicode(text); + if(sizeof(Py_UNICODE) == 4) + qtext = fromUcs4((Q_UINT32*)t); + else + qtext = QString::fromUcs2((Q_UINT16*)t); + } + else + { + // Error raise execption ... + } + return qtext; +} + +// Converts a QString to a Python String with Unicode support +PyObject* QString2PyString(QString string) +{ + PyObject *pyString; + + const unsigned short* tmp = string.ucs2(); + bool dofree = false; + + if(tmp) + { + #if Py_UNICODE_SIZE == 4 + + Py_UNICODE* buf = new Py_UNICODE[string.length()]; + + for(unsigned int i = 0; i < string.length(); i++) + { + buf[i] = tmp[i]; + } + dofree = true; + + #else + + Py_UNICODE* buf = (Py_UNICODE*) tmp; + + #endif + + pyString = PyUnicode_FromUnicode(buf, string.length()); + + if(dofree) + { + delete [] buf; + } + } + + else + pyString = PyString_FromString(""); + + return pyString; +} + + +long getMeter(long widget, char* name) +{ + karamba* theme = (karamba*)widget; + QObjectListIt it( *theme->meterList ); // iterate over meters + + while ( it != 0 ) + { + if (strcmp(((Meter*) *it)->name(), name) == 0) + return (long)*it; + ++it; + } + return 0; +} + +PyObject* py_getThemeMeter(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + char* name; + if (!PyArg_ParseTuple(args, (char*)"ls", &widget, &name)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + if(!name) + return NULL; + meter = getMeter(widget, name); + if (!checkMeter(widget, meter, type.ascii())) + return NULL; + return (Py_BuildValue((char*)"l", meter)); +} + +PyObject* py_getSize(PyObject *, PyObject *args, QString type) +{ + long widget; + long meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + return Py_BuildValue((char*)"(i,i)", ((Meter*)meter)->getWidth(), + ((Meter*)meter)->getHeight()); +} + +PyObject* py_resize(PyObject *, PyObject *args, QString type) +{ + long widget, meter, x, y; + if (!PyArg_ParseTuple(args, (char*)"llll", &widget, &meter, &x, &y)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + ((Meter*)meter)->setSize(((Meter*)meter)->getX(), ((Meter*)meter)->getY(), + x, y); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getPos(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + return Py_BuildValue((char*)"(i,i)", ((Meter*)meter)->getX(), + ((Meter*)meter)->getY()); +} + +PyObject* py_move(PyObject *, PyObject *args, QString type) +{ + long widget, meter, x, y; + if (!PyArg_ParseTuple(args, (char*)"llll", &widget, &meter, &x, &y)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + ((Meter*)meter)->setSize(x, y, + ((Meter*)meter)->getWidth(), + ((Meter*)meter)->getHeight()); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_hide(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + ((Meter*)meter)->hide(); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_show(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + ((Meter*)meter)->show(); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getValue(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + return Py_BuildValue((char*)"l", ((Meter*)meter)->getValue()); +} + +PyObject* py_setValue(PyObject *, PyObject *args, QString type) +{ + long widget, meter, l; + if (!PyArg_ParseTuple(args, (char*)"lll", &widget, &meter, &l)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + ((Meter*)meter)->setValue(l); + return Py_BuildValue((char*)"l", ((long)meter)); +} + +PyObject* py_getStringValue(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + return Py_BuildValue((char*)"O", + QString2PyString(((Meter*)meter)->getStringValue())); +} + +PyObject* py_setStringValue(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + PyObject* s; + if (!PyArg_ParseTuple(args, (char*)"llO", &widget, &meter, &s)) + return NULL; + if (!s) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + ((Meter*)meter)->setValue(PyString2QString(s)); + return Py_BuildValue((char*)"l", ((long)meter)); +} + +PyObject* py_getMinMax(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + return Py_BuildValue((char*)"(i,i)", ((Meter*)meter)->getMin(), + ((Meter*)meter)->getMax()); +} + +PyObject* py_setMinMax(PyObject *, PyObject *args, QString type) +{ + long widget, meter, x, y; + if (!PyArg_ParseTuple(args, (char*)"llll", &widget, &meter, &x, &y)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + ((Meter*)meter)->setMin(x); + ((Meter*)meter)->setMax(y); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getSensor(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + QString s; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + return Py_BuildValue((char*)"s", + ((karamba*)widget)->getSensor((Meter*)meter).ascii()); +} + +PyObject* py_setSensor(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + char* s; + + if (!PyArg_ParseTuple(args, (char*)"lls", &widget, &meter, &s)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + ((karamba*)widget)->setSensor(LineParser(s), (Meter*)meter); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_setColor(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + long r, g, b; + if (!PyArg_ParseTuple(args, (char*)"lllll", &widget, &meter, &r, &g, &b)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + ((Meter*)meter)->setColor(QColor(r, g, b)); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getColor(PyObject *, PyObject *args, QString type) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, type.ascii())) + return NULL; + QColor color = ((Meter*)meter)->getColor(); + return Py_BuildValue((char*)"(i,i,i)", color.red(), color.green(), color.blue()); +} + diff --git a/superkaramba/src/meter_python.h b/superkaramba/src/meter_python.h new file mode 100644 index 0000000..f064977 --- /dev/null +++ b/superkaramba/src/meter_python.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2003-2004 Adam Geitgey * + * Copyright (C) 2003 Hans Karlsson * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef METER_PYTHON_H +#define METER_PYTHON_H + +// Python uses char* where it should use const char* +#define PY_PARSE(a, b, c, d) (PyArg_ParseTuple(a, (char*)b, c, d)) +#define PY_BUILD(a, b) (Py_BuildValue((char*)a, b)) + +bool checkKaramba(long widget); +bool checkMeter(long widget, long meter, const char* type); +bool checkKarambaAndMeter(long widget, long meter, const char* type); + +QString PyString2QString(PyObject* text); +PyObject* QString2PyString(QString string); + +PyObject* py_getThemeMeter(PyObject *self, PyObject *args, QString type); +PyObject* py_getSize(PyObject *self, PyObject *args, QString type); +PyObject* py_resize(PyObject *self, PyObject *args, QString type); +PyObject* py_getPos(PyObject *self, PyObject *args, QString type); +PyObject* py_move(PyObject *self, PyObject *args, QString type); +PyObject* py_hide(PyObject *self, PyObject *args, QString type); +PyObject* py_show(PyObject *self, PyObject *args, QString type); +PyObject* py_getValue(PyObject *self, PyObject *args, QString type); +PyObject* py_setValue(PyObject *self, PyObject *args, QString type); +PyObject* py_getStringValue(PyObject *self, PyObject *args, QString type); +PyObject* py_setStringValue(PyObject *self, PyObject *args, QString type); +PyObject* py_getMinMax(PyObject *self, PyObject *args, QString type); +PyObject* py_setMinMax(PyObject *self, PyObject *args, QString type); +PyObject* py_getSensor(PyObject *self, PyObject *args, QString type); +PyObject* py_setSensor(PyObject *self, PyObject *args, QString type); +PyObject* py_getColor(PyObject *self, PyObject *args, QString type); +PyObject* py_setColor(PyObject *self, PyObject *args, QString type); + +#endif // METER_PYTHON_H + diff --git a/superkaramba/src/misc_python.cpp b/superkaramba/src/misc_python.cpp new file mode 100644 index 0000000..ba67573 --- /dev/null +++ b/superkaramba/src/misc_python.cpp @@ -0,0 +1,852 @@ +/**************************************************************************** +* misc_python.cpp - Misc Functions for python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (C) 2004 Petri Damst� +* Copyright (C) 2004, 2005 Luke Kenneth Casson Leighton +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include + +#include +#include + +#include "kdebug.h" +#include "karamba.h" +#include "karambaapp.h" +#include "themefile.h" +#include "themelocale.h" +#include "meter.h" +#include "meter_python.h" +#include "misc_python.h" + +/* now a method we need to expose to Python */ +long acceptDrops(long widget) +{ + karamba* currTheme = (karamba*)widget; + + currTheme->setAcceptDrops(true); + + return 1; +} + +PyObject* py_accept_drops(PyObject *, PyObject *args) +{ + long widget; + + if (!PyArg_ParseTuple(args, (char*)"l", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", acceptDrops(widget)); +} + +// Runs a command, returns 0 if it could not start command +PyObject* py_run_command(PyObject*, PyObject* args) +{ + char* name; + char* command; + char* icon; + PyObject *lst; + if (!PyArg_ParseTuple(args, (char*)"sssO:run", &name, &command, &icon, &lst) || + lst == NULL || !PyList_Check(lst)) + return NULL; + + QString n; + QString c; + QString i; + + n.setAscii(name); + c.setAscii(command); + i.setAscii(icon); + + KService svc(n, c, i); + KURL::List l; + + for (int i = 0; i < PyList_Size(lst); i++) + { + l.append(PyString2QString(PyList_GetItem(lst, i))); + } + KRun::run(svc, l); + return Py_BuildValue("l", 1); +} + +// Runs a command, returns 0 if it could not start command +PyObject* py_execute_command(PyObject *, PyObject* args) +{ + PyObject* s; + + if (!PyArg_ParseTuple(args, (char*)"O:execute", &s)) + return NULL; + return Py_BuildValue((char*)"l", KRun::runCommand(PyString2QString(s))); +} + +// Runs a command, returns 0 if it could not start command +PyObject* py_execute_command_interactive(PyObject *, PyObject* args) +{ + long widget; + //if (!PyArg_ParseTuple(args, (char*)"ls", &widget, &command)) + // return NULL; + + int numLines; /* how many lines we passed for parsing */ + QString line; /* pointer to the line as a string */ + + PyObject * listObj; /* the list of strings */ + PyObject * strObj; /* one string in the list */ + + /* the O! parses for a Python object (listObj) checked + to be of type PyList_Type */ + if (! PyArg_ParseTuple(args, (char*)"lO!", &widget, &PyList_Type, &listObj)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + karamba* currTheme = (karamba*)widget; + + currTheme->currProcess = new KProcess; + + /* get the number of lines passed to us */ + numLines = PyList_Size(listObj); + + /* should raise an error here. */ + if (numLines < 0) return NULL; /* Not a list */ + + /* iterate over items of the list, grabbing strings, and parsing + for numbers */ + for (int i=0; icurrProcess) << line; + + } + QApplication::connect(currTheme->currProcess, + SIGNAL(processExited(KProcess *)), + currTheme, + SLOT(processExited(KProcess *))); + QApplication::connect(currTheme->currProcess, + SIGNAL(receivedStdout(KProcess *, char *, int)), + currTheme, + SLOT(receivedStdout(KProcess *, char *, int))); + currTheme->currProcess->start(KProcess::NotifyOnExit, KProcess::Stdout); + + return Py_BuildValue((char*)"l", (int)(currTheme->currProcess->pid())); +} + +long attachClickArea(long widget, long meter, QString LeftButton, QString MiddleButton, QString RightButton) +{ + karamba* currTheme = (karamba*) widget; + Meter* currMeter = (Meter*) meter; + + // Look if currMeter has an ClickArea attached. + bool meterAlreadyClickable = currTheme->clickList->containsRef(currMeter); + + // if currMeter is of type ImageLabel* + if (ImageLabel* image = dynamic_cast(currMeter)) + { + image -> attachClickArea(LeftButton, MiddleButton, RightButton); + if (!meterAlreadyClickable) + { + //qWarning("attachClickArea : meter is image"); + currTheme -> clickList -> append(image); + } + } + // else if currMeter is of type TextLabel* + else if (TextLabel* text = dynamic_cast(currMeter)) + { + text -> attachClickArea(LeftButton, MiddleButton, RightButton); + if (!meterAlreadyClickable) + { + //qWarning("attachClickArea : meter is text"); + currTheme -> clickList -> append(text); + } + } + else + { + //The given meter does not support attached clickAreas. + qWarning("The given meter is not of type image or text"); + return 0; + } + return 1; +} + +PyObject* py_attach_clickArea(PyObject*, PyObject* args, PyObject* dict) +{ + long widget; + long meter; + char* LeftButton = NULL; + char* MiddleButton = NULL; + char* RightButton = NULL; + const char* mouseButtons[] = {"Widget", "Meter", "LeftButton", "MiddleButton", + "RightButton", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, dict, (char*)"ll|sss:attachClickArea", + (char**)mouseButtons, &widget, &meter, &LeftButton, &MiddleButton, &RightButton)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + QString lB, mB, rB; + if (LeftButton != NULL) + { + lB.setAscii(LeftButton); + } + else + { + lB.setAscii(""); + } + if (MiddleButton != NULL) + { + mB.setAscii(MiddleButton); + } + else + { + mB.setAscii(""); + } + if (RightButton != NULL) + { + rB.setAscii(RightButton); + } + else + { + rB.setAscii(""); + } + return Py_BuildValue((char*)"l", attachClickArea(widget, meter, lB, mB, rB)); +} + +/* now a method we need to expose to Python */ +long toggleShowDesktop(long) +{ + ShowDesktop *s = ShowDesktop::the(); + s->toggle(); + return 1; +} + +PyObject* py_toggle_show_desktop(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:toggleShowDesktop", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", toggleShowDesktop(widget)); +} + +/* now a method we need to expose to Python */ +const char* getPrettyName(long widget) { + karamba* currTheme = (karamba*)widget; + + return currTheme->prettyName.ascii(); +} + +PyObject* py_get_pretty_name(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:getPrettyThemeName", &widget)) + return NULL; + return Py_BuildValue((char*)"s", getPrettyName(widget)); +} + +/* now a method we need to expose to Python */ +const char* getThemePath(long widget) { + karamba* currTheme = (karamba*)widget; + + return currTheme->theme().path().ascii(); +} + +PyObject* py_get_theme_path(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:getThemePath", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"s", getThemePath(widget)); +} + +PyObject* py_language(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:language", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"s", + ((karamba*)widget)->theme().locale()->language().ascii()); +} + +PyObject* py_userLanguage(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:language", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"s", KGlobal::locale()->language().ascii()); +} + +PyObject* py_userLanguages(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:language", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + unsigned int noOfLangs = KGlobal::locale()->languageList().count(); + + PyObject *list, *item; + list = PyList_New(noOfLangs); + + for(unsigned int i = 0; i < noOfLangs; i++) + { + item = Py_BuildValue((char*)"s", KGlobal::locale()->languageList()[i].ascii()); + PyList_SetItem(list, i, item); + } + + return list; +} + +PyObject* py_read_theme_file(PyObject *, PyObject *args) +{ + long widget; + char *file; + if (!PyArg_ParseTuple(args, (char*)"ls:readThemeFile", &widget, &file)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + karamba* k = (karamba*)widget; + QByteArray ba = k->theme().readThemeFile(file); + return PyString_FromStringAndSize(ba.data(), ba.size()); +} + +/* now a method we need to expose to Python */ +long removeClickArea(long widget, long click) { + + karamba* currTheme = (karamba*)widget; + ClickArea *tmp = (ClickArea*)click; + + currTheme -> clickList -> remove(tmp); + + delete tmp; + return (long)tmp; +} + +/* now a method we need to expose to Python */ +long createServiceClickArea(long widget, long x, long y, long w, long h, char *name, char* exec, char *icon) { + + karamba* currTheme = (karamba*)widget; + ClickArea *tmp = new ClickArea( currTheme, x, y, w, h ); + QString n; + QString e; + QString i; + + n.setAscii(name); + e.setAscii(exec); + i.setAscii(icon); + + tmp->setServiceOnClick(n, e, i); + + currTheme -> clickList -> append(tmp); + return (long)tmp; +} + +long createClickArea(long widget, long x, long y, long w, long h, char* text) { + + karamba* currTheme = (karamba*)widget; + ClickArea *tmp = new ClickArea(currTheme, x, y, w, h ); + QString onclick; + + onclick.setAscii(text); + + tmp->setOnClick(onclick ); + + currTheme -> clickList -> append(tmp); + return (long)tmp; +} + +PyObject* py_remove_click_area(PyObject *, PyObject *args) +{ + long widget, click; + if (!PyArg_ParseTuple(args, (char*)"ll:removeClickArea", &widget, &click)) + return NULL; + return Py_BuildValue((char*)"l", removeClickArea(widget, click)); +} + +PyObject* py_create_service_click_area(PyObject *, PyObject *args) +{ + long widget, x, y, w, h; + char *name; + char *exec; + char *icon; + if (!PyArg_ParseTuple(args, (char*)"lllllsss:createServiceClickArea", &widget, &x, &y, + &w, &h, &name, &exec, &icon)) + return NULL; + return Py_BuildValue((char*)"l", createServiceClickArea(widget, x, y, w, h, name, exec, icon)); +} + +PyObject* py_create_click_area(PyObject *, PyObject *args) +{ + long widget, x, y, w, h; + char *text; + if (!PyArg_ParseTuple(args, (char*)"llllls:createClickArea", &widget, &x, &y, + &w, &h, &text)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", createClickArea(widget, x, y, w, h, text)); +} + +static long callTheme(long widget, char* path, char *str) +{ + karamba* currTheme = (karamba*) widget; + + if (currTheme) + currTheme->callTheme(QString(path), QString(str)); + + return (long)currTheme; +} + +static long setIncomingData(long widget, char* path, char *obj) +{ + karamba* currTheme = (karamba*) widget; + + if (currTheme) + currTheme->setIncomingData(QString(path), QString(obj)); + + return (long)currTheme; +} + +static QString getIncomingData(long widget) +{ + karamba* currTheme = (karamba*) widget; + + if (currTheme) + return currTheme->getIncomingData(); + + return QString(""); +} + +/* + * openNamedTheme. this function checks to see whether the theme + * being opened is unique or not (against all running karamba widgets). + * this is important, as loading themes with the same name causes + * grief. + */ +long openNamedTheme(char* path, char *name, bool is_sub_theme) { + + QString filename; + karamba* currTheme = 0; + + filename.setAscii(path); + + QFileInfo file( filename ); + + if( file.exists() ) + { + QCString prettyName(name); + KarambaApplication* app = (KarambaApplication*)qApp; + if (!app->themeExists(prettyName)) + { + currTheme = new karamba( filename, prettyName, false , + -1, is_sub_theme); + currTheme->show(); + } + } + return (long)currTheme; +} + +/* now a method we need to expose to Python */ +long openTheme(char* path) +{ + + QString filename; + karamba* currTheme = 0; + + filename.setAscii(path); + + QFileInfo file( filename ); + + if( file.exists() ) + { + currTheme = new karamba( filename, QString() ); + currTheme->show(); + } + + return (long)currTheme; +} + +PyObject* py_get_incoming_data(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:getIncomingData", &widget)) + return NULL; + return Py_BuildValue((char*)"O", QString2PyString(getIncomingData(widget))); +} + +PyObject* py_set_incoming_data(PyObject *, PyObject *args) +{ + char *themePath; + long widget; + char *obj; + if (!PyArg_ParseTuple(args, (char*)"lss:setIncomingData", &widget, &themePath, &obj)) + return NULL; + return Py_BuildValue((char*)"l", setIncomingData(widget, themePath, obj)); +} + +PyObject* py_call_theme(PyObject *, PyObject *args) +{ + char *themePath; + char *str; + long widget; + if (!PyArg_ParseTuple(args, (char*)"lss:callTheme", &widget, &themePath, &str)) + return NULL; + return Py_BuildValue((char*)"l", callTheme(widget, themePath, str)); +} + +PyObject* py_open_named_theme(PyObject *, PyObject *args) +{ + char *themePath; + char *themeName; + long is_sub_theme; + if (!PyArg_ParseTuple(args, (char*)"ssl:openNamedTheme", &themePath, &themeName, &is_sub_theme)) + return NULL; + return Py_BuildValue((char*)"l", openNamedTheme(themePath, themeName, is_sub_theme ? true : false)); +} + +PyObject* py_open_theme(PyObject *, PyObject *args) +{ + char *themePath; + if (!PyArg_ParseTuple(args, (char*)"s:openTheme", &themePath)) + return NULL; + return Py_BuildValue((char*)"l", openTheme(themePath)); +} + +PyObject* py_reload_theme(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:reloadTheme", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + ((karamba*)widget)->reloadConfig(); + return Py_BuildValue((char*)"l", 1); +} + +/* now a method we need to expose to Python */ +int getNumberOfDesktops(long widget) +{ + karamba* currTheme = (karamba*)widget; + + return currTheme->kWinModule->numberOfDesktops(); +} + +PyObject* py_get_number_of_desktops(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:getNumberOfDesktops", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", getNumberOfDesktops(widget)); +} + +/* now a method we need to expose to Python */ +int translateAll(long widget, int x, int y) +{ + karamba* currTheme = (karamba*)widget; + + QObjectListIt it2( *currTheme->meterList ); // iterate over meters + + while ( it2 != 0 ) + { + ((Meter*) *it2)->setSize(((Meter*) *it2)->getX()+x, + ((Meter*) *it2)->getY()+y, + ((Meter*) *it2)->getWidth(), + ((Meter*) *it2)->getHeight()); + ++it2; + } + + if (currTheme->systray != 0) + { + currTheme->systray->move(currTheme->systray->x()+x, + currTheme->systray->y()+y); + } + return 0; +} + +PyObject* py_translate_all(PyObject *, PyObject *args) +{ + long widget; + int x, y; + if (!PyArg_ParseTuple(args, (char*)"lii:translateAll", &widget, &x, &y)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"lii", translateAll(widget, x, y)); +} + +/* now a method we need to expose to Python */ +int show(long widget) +{ + karamba* currTheme = (karamba*)widget; + currTheme->show(); + return 0; +} + +PyObject* py_show(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:show", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", show(widget)); +} + +/* now a method we need to expose to Python */ +int hide(long widget) +{ + karamba* currTheme = (karamba*)widget; + currTheme->hide(); + return 0; +} + +PyObject* py_hide(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:hide", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", hide(widget)); +} + +/*Putting includes here to show the dependency for the call(s) below (if we ever decide to move the networking callbacks into a separate file*/ +#include +#include +#include +#include +#if defined(__FreeBSD__) || defined(__DragonFly__) +#include +#endif +#if defined(Q_OS_SOLARIS) +#include +#endif +/* now a method we need to expose to Python */ +QString getIp(char *device_name) +{ + int i, sd, numdevs; + struct ifconf ifc_conf; + char ifc_conf_buf[sizeof ( struct ifreq ) * 32]; + struct ifreq *devptr; + int ifc_conf_buf_size; + static struct in_addr host; + QString retval; + + retval = "Disconnected"; + + /* + * Open a socket, any type will do so we choose UDP, and ask it with + * an ioctl call what devices are behind it. + */ + if ((sd = socket(AF_INET,SOCK_DGRAM,0)) < 0) + { + qWarning("Error: Unable to create socket (socket)"); + return "Error"; + } + + /* + * Fill the buffer with our static buffer, probably big enough, and get + * the interface configuration. + */ + ifc_conf_buf_size = sizeof ifc_conf_buf; + ifc_conf.ifc_len = ifc_conf_buf_size; + ifc_conf.ifc_buf = ifc_conf_buf; + if (ioctl(sd,SIOCGIFCONF,&ifc_conf) < 0) + { + qWarning("Error: Unable to get network interface conf (ioctl)"); + close(sd); + return "Error"; + } + + /* + * An array of devices were returned. Which ones are up right now and + * have broadcast capability? + */ + numdevs = ifc_conf.ifc_len / sizeof (struct ifreq); + //qDebug("numdevs = %d", numdevs); + for (i = 0; i < numdevs; i++) + { + //qDebug("iterations: %d", i); + /* devptr points into an array of ifreq structs. */ + devptr = &ifc_conf.ifc_req[i]; + + if (ioctl(sd, SIOCGIFADDR, devptr) < 0 || devptr->ifr_addr.sa_family != AF_INET) + continue; + + if (ioctl(sd,SIOCGIFFLAGS,devptr) < 0) + { + qWarning("Error: Unable to get device interface flags (ioctl)."); + close(sd); + return "Error"; + } + + //We generally don't want probing of the loopback devices + if ((devptr->ifr_flags & IFF_LOOPBACK) != 0) + continue; + + if ((devptr->ifr_flags & IFF_UP) == 0) + continue; + + if ((devptr->ifr_flags & IFF_BROADCAST) == 0) + continue; + + /* Get the broadcast address. */ + if (ioctl(sd,SIOCGIFFLAGS,devptr) < 0) + { + qWarning("Error: Unable to get device interface flags (ioctl)."); + close(sd); + return "Error"; + } + else + { + if (!strcmp((char*)devptr->ifr_name, device_name)) + { + host.s_addr = ((struct sockaddr_in*)&devptr->ifr_addr)->sin_addr.s_addr; + retval = inet_ntoa(host); + break; + } + } + } + close(sd); + return retval; +} + +PyObject* py_set_update_time(PyObject *, PyObject *args) +{ + long widget; + double time; + if (!PyArg_ParseTuple(args, (char*)"ld:setUpdateTime", &widget, &time)) + return NULL; + karamba* currTheme = (karamba*)widget; + currTheme->setUpdateTime(time); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_get_update_time(PyObject *, PyObject *args) +{ + long widget; + double time; + if (!PyArg_ParseTuple(args, (char*)"l:getUpdateTime", &widget, &time)) + return NULL; + karamba* currTheme = (karamba*)widget; + return Py_BuildValue((char*)"d", currTheme->getUpdateTime()); +} + +PyObject* py_get_ip(PyObject *, PyObject *args) +{ + long widget; + char *interface; + if (!PyArg_ParseTuple(args, (char*)"ls:getIp", &widget, &interface)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"O", QString2PyString(getIp(interface))); +} + +static void management_popup(long widget) +{ + karamba* currTheme = (karamba*)widget; + currTheme->management_popup(); +} + +PyObject* py_management_popup(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:managementPopup", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + management_popup(widget); + return Py_BuildValue((char*)"l", 1); +} + +static void set_want_right_button(long widget, long yesno) +{ + karamba* currTheme = (karamba*)widget; + currTheme->setWantRightButton(yesno); +} + +PyObject* py_want_right_button(PyObject *, PyObject *args) +{ + long widget, i; + if (!PyArg_ParseTuple(args, (char*)"ll:setWantRightButton", &widget, &i)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + set_want_right_button(widget, i); + return Py_BuildValue((char*)"l", 1); +} + +static void set_want_wheel_event(long widget, long yesno) +{ + karamba* currTheme = (karamba*)widget; + currTheme->setWantMeterWheelEvent(yesno); +} + +PyObject* py_want_wheel_event(PyObject *, PyObject *args) +{ + long widget, i; + if (!PyArg_ParseTuple(args, (char*)"ll:setWantMeterWheelEvent", &widget, &i)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + set_want_wheel_event(widget, i); + return Py_BuildValue((char*)"l", 1); +} + +static void changeInterval(long widget, long interval) +{ + karamba* currTheme = (karamba*)widget; + currTheme->changeInterval(interval); +} + +PyObject* py_change_interval(PyObject *, PyObject *args) +{ + long widget, i; + if (!PyArg_ParseTuple(args, (char*)"ll:changeInterval", &widget, &i)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + changeInterval(widget, i); + return Py_BuildValue((char*)"l", 1); +} + + diff --git a/superkaramba/src/misc_python.h b/superkaramba/src/misc_python.h new file mode 100644 index 0000000..46c0988 --- /dev/null +++ b/superkaramba/src/misc_python.h @@ -0,0 +1,606 @@ +/* +* misc_python.h - Misc Functions for python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (C) 2004 Petri Damst� +* Copyright (C) 2004,2005 Luke Kenneth Casson Leighton +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef MISC_PYTHON_H +#define MISC_PYTHON_H + +/** @file +* +* These are global functions that are used to interpret +* certain Python calls. +*/ + +/** Misc/acceptDrops +* +* SYNOPSIS +* long acceptDrops(widget) +* DESCRIPTION +* Calling this enables your widget to receive Drop events. In other words, +* the user will be able to drag icons from her desktop and drop them on +* your widget. The "itemDropped" callback is called as a result with the +* data about the icon that was dropped on your widget. This allows, for +* example, icon bars where items are added to the icon bar by Drag and +* Drop. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_accept_drops(PyObject *self, PyObject *args); + +/** Misc/execute +* +* SYNOPSIS +* long execute(command) +* DESCRIPTION +* This command simply executes a program or command on the system. This is +* just for convience (IE you could accomplish this directly through python, +* but sometimes threading problems crop up that way). The only option is a +* string containing the command to execute. +* ARGUMENTS +* * string command -- command to execute +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_execute_command(PyObject* self, PyObject* args); + +/** Misc/executeInteractive +* +* SYNOPSIS +* long executeInteractive(widget, command) +* DESCRIPTION +* This command executes a program or command on the system. But it allows +* you to get any text that the program outputs. Futhermore, it won't freeze +* up your widget while the command executes. +* +* To use it, call executeInteractive with the reference to your widget and +* an array of command options. The array is simply a list that contains the +* command as the first entry, and each option as a seperate list entry. +* Make sure to catch the returning value from executeInteractive(); it will +* be the identifier (process number) for the command. +* +* Output from the command triggers commandOutput callback. Among other items +* commandOutput gives the process number of the command that gave the output. +* This allows you to identify the output when running more than one command +* at a time. +* +* Example: +* To run the command "ls -la *.zip" +* +* myCommand = ["ls", "-la", "*.zip"] +* procID = karamba.executeInteractive(widget, myCommand) +* +* To catch the output, screen commandOutput output for procID. +* +* ARGUMENTS +* * long widget -- karamba +* * list command -- command to execute +* RETURN VALUE +* identification number of the executed command process +*/ +PyObject* py_execute_command_interactive(PyObject* self, PyObject* args); + +/** Misc/run +* +* SYNOPSIS +* long run(name, command, icon, list_of_args) +* DESCRIPTION +* This command simply executes a program or command on the system. +* The difference between run and execute is that run takes arguments, +* and the name of the icon to be displayed. +* ARGUMENTS +* * string name -- name to be displayed +* * string command -- command to execute +* * string icon -- name of icon to be displayed +* * string list_of_args -- arguments to be passed to the command +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_run_command(PyObject* self, PyObject* args); + +/** Misc/attachClickArea +* +* SYNOPSIS +* long attachClickArea(widget, meter, lB, mB, rB) +* DESCRIPTION +* It is possible to attach a clickarea to a meter (image or text field), +* which is moved and resized correctly if the meter is moved or resized. +* +* There is also a callback meterClicked(widget, meter, button) which is +* called whenever a meter is clicked (if something is attached to it). +* Given an Image or a TextLabel, this call makes it clickable. When a mouse +* click is detected, the callback meterClicked is called. +* +* lB, mB, and rB are strings that specify what command is executed when +* this meter is clicked with the left mouse button, middle mouse button, +* and right mouse button respectively. If given, the appropriate command is +* executed when the mouse click is received. +* +* The keyword arguments are all optional. If command is an empty string +* nothing is executed. +* +* For now the command given to RightButton has obviosly no effect (because +* that brings up the SuperKaramba menu). +* +* ARGUMENTS +* * long widget -- karamba +* * long meter -- pointer to meter +* * string lB -- command to left mouse button +* * string mB -- command to middle mouse button +* * string rB -- command to right mouse button +* +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_attach_clickArea(PyObject* self, PyObject* args, PyObject* dict); + +/** Misc/toggleShowDesktop +* +* SYNOPSIS +* long toggleShowDesktop(widget) +* DESCRIPTION +* This shows/hides the current desktop just like the Show Desktop button on +* kicker. Basically, it minimizes all the windows on the current desktop. +* Call it once to show the desktop and again to hide it. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_toggle_show_desktop(PyObject *self, PyObject *args); + +/** Misc/getThemePath +* +* SYNOPSIS +* string getThemePath(widget) +* DESCRIPTION +* Returns a string containing the directory where your theme was loaded +* from. If you are running the theme from (compressed) skz (zip) file, the +* return value will be the path of that file, including the file name. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* path to theme +*/ +PyObject* py_get_theme_path(PyObject *self, PyObject *args); + +/** Misc/language +* +* SYNOPSIS +* string language(widget) +* DESCRIPTION +* Returns a string containing default language of a translation file. +* Please, see userLanguage to obtain the preferred KDE interface language. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* default language or empty string if no translation files found. +*/ +PyObject* py_language(PyObject *self, PyObject *args); + +/** Misc/userLanguage +* +* SYNOPSIS +* string userLanguage(widget) +* DESCRIPTION +* Returns a string containing the language name abbreviation for the +* language user chose for the KDE session in Region & Language settings. +* Implemented in version 0.40. Parse ~/.kde/share/config/kdeglobals +* for 'Language' directly for earlier clients. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* user language or empty string. +*/ +PyObject* py_userLanguage(PyObject *self, PyObject *args); + + +/** Misc/userLanguages +* +* SYNOPSIS +* string userLanguages(widget) +* DESCRIPTION +* Returns a list (array) containing the language name abbreviations for the +* preferred interface languages user chose for KDE session in Region & +* Language settings. +* Having the whole array of preferred languages available is important for +* cases when you cannot provide interface translation for the 1st preferred +* language, but can for consecutive languages. +* (Implemented in version 0.42.) +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* list (array) with user languages in the order of preference. +*/ +PyObject* py_userLanguages(PyObject *self, PyObject *args); + + +/** Misc/readThemeFile +* +* SYNOPSIS +* string readThemeFile(widget, file) +* DESCRIPTION +* Returns a string containing the contents of the file. +* ARGUMENTS +* * long widget -- karamba +* * string file -- name of the file to read +* RETURN VALUE +* file contents +*/ +PyObject* py_read_theme_file(PyObject *self, PyObject *args); + +/** Misc/createClickArea +* +* SYNOPSIS +* long createClickArea(widget, x, y, w, h, cmd_to_run) +* DESCRIPTION +* This creates a clickable area at x,y with width and height w,h. When +* this area is clicked, cmd_to_run will be executed. The mouse will change +* to the clickable icon while hovering over this area. +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * long w -- width +* * long h -- height +* * string cmd_to_run -- command to be run +* RETURN VALUE +* a handle to the click area +*/ +PyObject* py_create_click_area(PyObject *self, PyObject *args); + +/** Misc/openTheme +* +* SYNOPSIS +* long openTheme(theme) +* DESCRIPTION +* Opens new theme. +* ARGUMENTS +* * string theme -- path to new theme +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_open_theme(PyObject *self, PyObject *args); + +/** Misc/reloadTheme +* +* SYNOPSIS +* long reloadTheme(theme) +* DESCRIPTION +* Reloads current theme. +* ARGUMENTS +* * string theme -- path to new theme +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_reload_theme(PyObject *self, PyObject *args); + +/** Misc/getNumberOfDesktop +* +* SYNOPSIS +* long getNumberOfDesktop(widget) +* DESCRIPTION +* Returns number fo desktops +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* number of desktops +*/ +PyObject* py_get_number_of_desktops(PyObject *self, PyObject *args); + +/** Misc/translateAll +* +* SYNOPSIS +* long translateAll(widget, relative_x, relative_y) +* DESCRIPTION +* Moves all widgets within a theme in a particular direction relative to +* the previous spot without moving the parent theme widget. +* ARGUMENTS +* * long widget -- karamba +* * long translate_x -- move horizontally +* * long translate_y -- move vertically +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_translate_all(PyObject *self, PyObject *args); + +/** Misc/show +* +* SYNOPSIS +* string show(widget) +* DESCRIPTION +* show theme +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_show(PyObject *self, PyObject *args); + +/** Misc/hide +* +* SYNOPSIS +* string hide(widget) +* DESCRIPTION +* hide theme +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_hide(PyObject *self, PyObject *args); + +/** Misc/getIp +* +* SYNOPSIS +* string getIp(widget, interface_name) +* DESCRIPTION +* get current IP address of the interface_name interface. +* ARGUMENTS +* * long widget -- karamba +* * string interface_name -- name of the interface to get ip +* RETURN VALUE +* ip address +*/ +PyObject* py_get_ip(PyObject *self, PyObject *args); + +/** Misc/changeInterval +* +* SYNOPSIS +* long changeInterval(widget, interval) +* DESCRIPTION +* Calling this changes your widget's refresh rate (ms) +* ARGUMENTS +* * long widget -- karamba +* * int interval -- interval, in ms +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_change_interval(PyObject *self, PyObject *args); + +/** Misc/createServiceClickArea +* +* SYNOPSIS +* long createServiceClickArea(widget, x, y, w, h, name_of_command, cmd_to_run, icon_to_display) +* DESCRIPTION +* This creates a clickable area at x,y with width and height w,h. When +* this area is clicked, cmd_to_run will be executed. The mouse will change +* to the clickable icon when over this area. For more information on +* the difference between createClickArea and createServiceClickArea, +* see the KDE documentation about KService, and the difference +* between KRun::run and KRun::runCommand. +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * long w -- width +* * long h -- height +* * string name_of_command -- name to be displayed +* * string cmd_to_run -- command to be run +* * string icon_to_display -- name of icon to be displayed +* RETURN VALUE +* a handle to the click area +*/ +PyObject* py_create_service_click_area(PyObject *self, PyObject *args); + +/** Misc/removeClickArea +* +* SYNOPSIS +* long removeClickArea(widget, clickarea) +* DESCRIPTION +* This function deletes a clickable area. +* ARGUMENTS +* * long widget -- karamba +* * long clickarea -- handle to the click area +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_remove_click_area(PyObject *self, PyObject *args); + + +/** Misc/getPrettyThemeName +* +* SYNOPSIS +* string getPrettyThemeName(theme) +* DESCRIPTION +* When a theme is created with openNamedTheme, there is an +* option to give the theme an alternative name. +* This is useful if you open several widgets from the same theme: +* you need to give them unique names in order to contact them +* (for example, with callTheme or with setIncomingData) +* ARGUMENTS +* * string theme -- path to the theme +* RETURN VALUE +* the pretty name of the theme +*/ +PyObject* py_get_pretty_name(PyObject *self, PyObject *args); + +/** Misc/openNamedTheme +* +* SYNOPSIS +* long openNamedTheme(theme, pretty_name, is_sub_theme) +* DESCRIPTION +* Opens a new theme, giving it a pretty (alternative and by your +* own choice _unique_) name. +* If you do not want the theme to be loaded when superkaramba is +* first started up (but instead want it to only be opened by +* this function call) then set is_sub_theme to 1. +* Themes opened with openNamedTheme will be unique. If a theme +* with the same pretty name already exists, openNamedTheme will +* have no effect. If you want duplicate themes (and a bit of a +* mess), use openTheme, instead. +* ARGUMENTS +* * string theme -- path to new theme +* * string pretty_name -- the name to be associated with the new widget +* * long is_sub_theme -- sets persistence (save state) of the theme +* RETURN VALUE +* a handle to the widget created +*/ +PyObject* py_open_named_theme(PyObject *self, PyObject *args); + +/** Misc/callTheme +* +* SYNOPSIS +* long callTheme(widget, theme, info) +* DESCRIPTION +* Sends a string to the theme identified by the pretty name. +* If you need to pass complex arguments (dictionaries, lists), use python +* "repr" and "eval" functions to marshall and unmarshall the data structure. +* (themeNotify Will be called in the target theme when message is received) +* +* Note: As a bug/feature of SuperKaramba version 0.40, multiple instances of +* the same theme share global variables. If you want to communicate to other +* instances of the same theme, just communicate through global variables. +* ARGUMENTS +* * long widget -- karamba +* * string theme -- pretty name of the theme to be called +* * string info -- a string containing the info to be passed to the theme +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_call_theme(PyObject *self, PyObject *args); + +/** Misc/setIncomingData +* +* SYNOPSIS +* long setIncomingData(widget, theme, info) +* DESCRIPTION +* Contacts a theme - identified by the pretty name - and stores a string +* to be associated with the remote theme. The difference between +* setIncomingData and callTheme is that the theme is not notified +* by setIncomingData that the data has arrived. Previous information, +* if any, is overwritten. Use getIncomingData to retrieve the last +* stored information. +* setIncomingData is not very sophisticated, and could benefit from +* having info passed to it put into a queue, instead of being overwritten. +* ARGUMENTS +* * long widget -- karamba +* * string theme -- pretty name of theme the information is passed to. +* * string info -- a string containing the info to be passed to the theme +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_set_incoming_data(PyObject *self, PyObject *args); + +/** Misc/getIncomingData +* +* SYNOPSIS +* long getIncomingData(widget) +* DESCRIPTION +* Obtains the last data received by any other theme that set the +* "incoming data" of this theme. This isn't particularly sophisticated +* and could benefit from the data being placed in an FIFO queue instead. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* string containing last information received from setIncomingData +*/ +PyObject* py_get_incoming_data(PyObject *self, PyObject *args); + +/** Misc/getUpdateTime +* +* SYNOPSIS +* long getUpdateTime(widget) +* DESCRIPTION +* returns the last stored update time. Intended for use +* so that the next refresh interval can work out how long ago +* the mouse was last moved over the widget. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* last stored update time (from setUpdateTime) +*/ +PyObject* py_get_update_time(PyObject *self, PyObject *args); + +/** Misc/setWantRightButton +* +* SYNOPSIS +* long setWantRightButton(widget, want_receive_right_button) +* DESCRIPTION +* There's a management menu for SuperKaramba themes which +* allows themes to be loaded, closed, moved to other +* screens. Not all themes will want this management +* interface. call karamba.wantRightButton(widget, 1) +* if you want to receive MouseUpdate button notifications. +* ARGUMENTS +* * long widget -- karamba +* * long want_receive_right_button -- whether the widget will receive right clicks +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_want_right_button(PyObject *self, PyObject *args); + +/** Misc/setWantMeterWheelEvent +* +* SYNOPSIS +* long setWantMeterWheelEvent(widget, want_receive_wheel_event) +* DESCRIPTION +* Enabling this allows themes to receive a wheel event when +* the wheel is turned over a meter. +* This function is available after version 0.42. +* This behaviour is default in SuperKaramba 0.50 and later, +* so this function will be not available after the 0.50 version. +* ARGUMENTS +* * long widget -- karamba +* * long want_receive_wheel_event -- whether the theme will receive mouse wheel events +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_want_wheel_event(PyObject *, PyObject *args); + +/** Misc/managementPopup +* +* SYNOPSIS +* long managementPopup(widget) +* DESCRIPTION +* There's a management menu for SuperKaramba themes which +* allows themes to be loaded, closed, moved to other +* screens. If you want this popup menu to appear, call +* this function. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_management_popup(PyObject *self, PyObject *args); + +/** Misc/setUpdateTime +* +* SYNOPSIS +* long getUpdateTime(widget, updated_time) +* DESCRIPTION +* returns the last stored update time. intended for use +* so that the next refresh interval can work out how long ago +* the mouse was last moved over the widget. +* ARGUMENTS +* * long widget -- karamba +* * long updated_time -- the update time to be associated with the widget +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_set_update_time(PyObject *self, PyObject *args); + +#endif /* MISC_PYTHON_H */ + diff --git a/superkaramba/src/networksensor.cpp b/superkaramba/src/networksensor.cpp new file mode 100644 index 0000000..30f9612 --- /dev/null +++ b/superkaramba/src/networksensor.cpp @@ -0,0 +1,164 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifdef __FreeBSD__ +#include +#include +#include +#include +#endif + +#include "networksensor.h" + +NetworkSensor::NetworkSensor( QString dev, int interval ):Sensor( interval ) +{ + device = dev.lower(); + +#ifdef __FreeBSD__ + /* Determine number of interfaces */ + u_int n = 0; + size_t nlen = 0; + nlen = sizeof(n); + sysctlbyname("net.link.generic.system.ifcount", &n, &nlen, NULL, 0); + + size_t if_miblen = 0; + if_miblen = sizeof(if_mib); + static int name[] = { CTL_NET, + PF_LINK, + NETLINK_GENERIC, + IFMIB_IFDATA, + 0, + IFDATA_GENERAL }; + + /* + If the device was defined by the theme, find the right devicenumber. + If not, use the device that holds the default route. + */ + + if_number = -1; + int if_gw = -1; + + for (int i = 1; i <= n; ++i) { + name[4] = i; + /* Get data for iface-number i */ + sysctl(name, 6, (void*)&if_mib, (size_t*)&if_miblen, (void*)NULL, (size_t)0); + + /* We found the right interface? */ + if (QString(if_mib.ifmd_name) == device) { + if_number = i; + break; + } + + /* Does the interface hold the default route? */ + if ( if_mib.ifmd_flags & RTF_GATEWAY ) + if_gw = i; + } + + if ((if_number == -1) && (if_gw != -1)) + if_number = if_gw; +#else + if( device.isEmpty() ) + device = "eth0"; +#endif + getInOutBytes(receivedBytes,transmittedBytes); + netTimer.start(); + +} +NetworkSensor::~NetworkSensor() +{ +} +void NetworkSensor::getInOutBytes ( unsigned long &in,unsigned long &out) const +{ +#ifdef __FreeBSD__ + if (if_number != -1) { + size_t if_miblen = 0; + if_miblen = sizeof(if_mib); + int name[] = { CTL_NET, + PF_LINK, + NETLINK_GENERIC, + IFMIB_IFDATA, + if_number, + IFDATA_GENERAL }; + + sysctl(name, 6, (void*)&if_mib, (size_t*)&if_miblen, (void*)NULL, (size_t)0); + + in = if_mib.ifmd_data.ifi_ibytes; + out = if_mib.ifmd_data.ifi_obytes; + } + else { + in = 0; + out = 0; + } +#else + QFile file("/proc/net/dev"); + QString line; + if ( file.open(IO_ReadOnly | IO_Translate) ) + { + QTextStream t( &file ); // use a text stream + line = t.readLine(); + while(line !=0 && !line.contains(device)) + { + line = t.readLine(); + } + if ( line.contains( device ) ) + { + QRegExp rx( "\\W+"+device+":\\D*(\\d+)(?:\\D+\\d+){7}\\D+(\\d+)", false); + rx.search(line); + in = rx.cap(1).toULong(); + out = rx.cap(2).toULong(); + } + else + { + qDebug("Network sensor: can not find %s", device.ascii()); + in = 0; + out = 0; + } + file.close(); + } +#endif +} + +void NetworkSensor::update() +{ + SensorParams *sp; + Meter *meter; + QObjectListIt it( *objList ); + QString format; + int decimals; + + unsigned long inB, outB; + const double delay = (double) netTimer.elapsed(); // msec elapsed since last update + getInOutBytes( inB, outB ); + netTimer.restart(); + + while( it != 0 ) + { + sp = (SensorParams*)(*it); + meter = sp->getMeter(); + format = sp->getParam( "FORMAT" ); + decimals = ( sp->getParam( "DECIMALS" ) ).toInt(); + if (format.length() == 0 ) + { + format = "%in"; + } + + format.replace( QRegExp("%inkb", false), QString::number( ((inB - receivedBytes)*8)/delay, 'f', decimals ) ); + format.replace( QRegExp("%in", false), QString::number( (inB - receivedBytes)/delay, 'f', decimals ) ); + + format.replace( QRegExp("%outkb", false), QString::number( ((outB - transmittedBytes)*8)/delay, 'f', decimals ) ); + format.replace( QRegExp("%out", false), QString::number( (outB - transmittedBytes)/delay, 'f', decimals ) ); + + meter->setValue( format ); + ++it; + } + receivedBytes = inB; + transmittedBytes = outB; +} + +#include "networksensor.moc" diff --git a/superkaramba/src/networksensor.h b/superkaramba/src/networksensor.h new file mode 100644 index 0000000..bbdbd13 --- /dev/null +++ b/superkaramba/src/networksensor.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef NETWORKSENSOR_H +#define NETWORKSENSOR_H + +#include "sensor.h" + +#include +#include +#include +#ifdef __FreeBSD__ +#include +#include +#include +#include +#endif + +class NetworkSensor : public Sensor +{ + Q_OBJECT +public: + NetworkSensor( QString device, int interval ); + ~NetworkSensor(); + void update(); + + +private: + unsigned long receivedBytes; + unsigned long transmittedBytes; + QTime netTimer; + QString device; +#ifdef __FreeBSD__ + int if_number; + ifmibdata if_mib; +#endif + void getInOutBytes (unsigned long &in,unsigned long &out) const; + +}; +#endif // NETWORKSENSOR_H + diff --git a/superkaramba/src/noatunsensor.cpp b/superkaramba/src/noatunsensor.cpp new file mode 100644 index 0000000..607da9e --- /dev/null +++ b/superkaramba/src/noatunsensor.cpp @@ -0,0 +1,234 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "noatunsensor.h" + +NoatunSensor::NoatunSensor( int interval, DCOPClient *c) + : Sensor( interval ) +{ + client = c; + noatunID = "noatun"; +} + + +NoatunSensor::~NoatunSensor() +{} + + +void NoatunSensor::update() +{ + QString format; + SensorParams *sp; + Meter *meter; + QObjectListIt it( *objList ); + + QString title; + int songLength = 0; + int currentTime = 0; + + bool running = isRunning(); + + if( running ) + { + title = getTitle(); + + if( title.isEmpty() ) + title = "Noatun"; + currentTime = getTime(); + if( currentTime == -1 ) + currentTime = 0; + + songLength = getLength(); + if( songLength == -1 ) + songLength = 0; + } + + + while (it != 0) + { + sp = (SensorParams*)(*it); + meter = sp->getMeter(); + + if( running ) + { + + format = sp->getParam("FORMAT"); + if (format.length() == 0 ) + { + format = "%title %time / %length"; + } + + if( format.lower() == "%ms" ) + { + meter->setMax( songLength ); + meter->setValue( currentTime ); + } + else + if ( format.lower() == "%full" ) + { + meter->setValue( 1 ); + } + else + + { + format.replace( QRegExp("%title", false), title ); + format.replace( QRegExp("%id", false), noatunID ); + + format.replace( QRegExp("%length", false), QTime( 0,0,0 ). + addMSecs( songLength ) + .toString( "h:mm:ss" ) ); + + format.replace( QRegExp("%time", false), QTime( 0,0,0 ). + addMSecs( currentTime ) + .toString( "h:mm:ss" ) ); + format.replace( QRegExp("%remain", false), QTime( 0,0,0 ). + addMSecs( songLength ) + .addMSecs(-currentTime ) + .toString( "h:mm:ss" ) ); + + meter->setValue(format); + } + } + else + + { + meter->setValue(""); + } + ++it; + + + } + +} + +bool NoatunSensor::isRunning() +{ + QRegExp rx("(noatun)|(noatun-\\d+)"); + QCStringList list = client->registeredApplications(); + QValueList::iterator it; + it = list.begin(); + bool foundNoatun = false; + noatunID = "noatun"; + while( foundNoatun == false && it != list.end() ) + { + if( rx.search( *it ) != -1 ) + { + foundNoatun = true; + noatunID = *it; + } + ++it; + } + return ( client->isApplicationRegistered ( noatunID ) ); +} + + +QString NoatunSensor::getTitle() +{ + QByteArray data, replyData; + QCString replyType; + QString result; + QDataStream arg(data, IO_WriteOnly); + arg << 5; + if (!client->call( noatunID, "Noatun", "title()", + data, replyType, replyData)) + { + result = ""; + qDebug("there was some error using DCOP."); + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> result; + result.replace( QRegExp("_")," " ); + result.replace( QRegExp(".mp3$"),"" ); + + } + else + { + result = ""; + qDebug("title returned an unexpected type of reply!"); + } + } + return result; +} + + +int NoatunSensor::getTime() +{ + QByteArray data, replyData; + QCString replyType; + int result; + QDataStream arg(data, IO_WriteOnly); + arg << 5; + if (!client->call( noatunID, "Noatun", "position()", + data, replyType, replyData)) + { + result = 0; + qDebug("there was some error using DCOP."); + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + { + reply >> result; + } + else + { + result = 0; + qDebug("title returned an unexpected type of reply!"); + } + } + return result; +} + + +int NoatunSensor::getLength() +{ + QByteArray data, replyData; + QCString replyType; + int result; + QDataStream arg(data, IO_WriteOnly); + arg << 5; + if (!client->call( noatunID, "Noatun", "length()", + data, replyType, replyData)) + { + result = 0; + qDebug("there was some error using DCOP."); + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + { + reply >> result; + } + else + { + result = 0; + qDebug("title returned an unexpected type of reply!"); + } + } + return result; +} + + +void NoatunSensor::setMaxValue( SensorParams *sp) +{ + Meter *meter; + meter = sp->getMeter(); + QString f; + f = sp->getParam("FORMAT"); + + if ( f == "%full" ) + meter->setMax( 1 ); + +} diff --git a/superkaramba/src/noatunsensor.h b/superkaramba/src/noatunsensor.h new file mode 100644 index 0000000..7d43b96 --- /dev/null +++ b/superkaramba/src/noatunsensor.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef NOATUNSENSOR_H +#define NOATUNSENSOR_H + +#include "sensor.h" +#include +#include +#include +#include +#include + +/** +@author Hans Karlsson +*/ +class NoatunSensor : public Sensor +{ +public: + NoatunSensor( int interval, DCOPClient *client); + + ~NoatunSensor(); + + void update(); + void setMaxValue( SensorParams *); + + + +private: + QCString noatunID; + + bool isRunning(); + QString getTitle(); + int getTime(); + int getLength(); + + + DCOPClient *client; + QCString appId; +}; + +#endif diff --git a/superkaramba/src/programsensor.cpp b/superkaramba/src/programsensor.cpp new file mode 100644 index 0000000..a3bddc5 --- /dev/null +++ b/superkaramba/src/programsensor.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "programsensor.h" + +#include +ProgramSensor::ProgramSensor(const QString &progName, int interval, QString encoding ) + : Sensor( interval ) +{ + if( !encoding.isEmpty()) + { + codec = QTextCodec::codecForName( encoding.ascii() ); + if ( codec == 0) + codec = QTextCodec::codecForLocale(); + } + else + codec = QTextCodec::codecForLocale(); + + + programName = progName; + //update(); + connect(&ksp, SIGNAL(receivedStdout(KProcess *, char *, int )), + this,SLOT(receivedStdout(KProcess *, char *, int ))); + connect(&ksp, SIGNAL(processExited(KProcess *)), + this,SLOT(processExited( KProcess * ))); +} + +ProgramSensor::~ProgramSensor() +{} + +void ProgramSensor::receivedStdout(KProcess *, char *buffer, int len) +{ + buffer[len] = 0; + sensorResult += codec->toUnicode( QCString(buffer) ); +} + +void ProgramSensor::processExited(KProcess *) +{ + int lineNbr; + SensorParams *sp; + Meter *meter; + QValueVector lines; + QStringList stringList = QStringList::split('\n',sensorResult,true); + QStringList::ConstIterator end( stringList.end() ); + for ( QStringList::ConstIterator it = stringList.begin(); it != end; ++it ) + { + lines.push_back(*it); + } + + int count = (int) lines.size(); + QObjectListIt it( *objList ); + while (it != 0) + { + sp = (SensorParams*)(*it); + meter = sp->getMeter(); + if( meter != 0) + { + lineNbr = (sp->getParam("LINE")).toInt(); + if ( lineNbr >= 1 && lineNbr <= (int) count ) + { + meter->setValue(lines[lineNbr-1]); + } + if ( -lineNbr >= 1 && -lineNbr <= (int) count ) + { + meter->setValue(lines[count+lineNbr]); + } + if (lineNbr == 0) + { + meter->setValue(sensorResult); + } + } + ++it; + } + + sensorResult = ""; +} + +void ProgramSensor::update() +{ + ksp.clearArguments(); + ksp << programName; + + + ksp.start( KProcIO::NotifyOnExit,KProcIO::Stdout); +} + +#include "programsensor.moc" diff --git a/superkaramba/src/programsensor.h b/superkaramba/src/programsensor.h new file mode 100644 index 0000000..1ee7407 --- /dev/null +++ b/superkaramba/src/programsensor.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef PROGRAMSENSOR_H +#define PROGRAMSENSOR_H +#include "sensor.h" +#include +#include +#include +#include +#include +#include +class ProgramSensor : public Sensor +{ + Q_OBJECT +public: + ProgramSensor(const QString &programName, int msec=1000, QString encoding="" ); + ~ProgramSensor(); + void update(); + +private: + QTextCodec *codec; + KShellProcess ksp; + QString programName; + QString sensorResult; + +public slots: + void receivedStdout(KProcess *proc, char *buffer, int buflen); + void processExited(KProcess *proc); +}; + +#endif // PROGRAMSENSOR_H diff --git a/superkaramba/src/richtextlabel.cpp b/superkaramba/src/richtextlabel.cpp new file mode 100644 index 0000000..9a8fee0 --- /dev/null +++ b/superkaramba/src/richtextlabel.cpp @@ -0,0 +1,212 @@ +/*************************************************************************** + * Copyright (C) 2003 by Wilfried Huss * + * Wilfried.Huss@gmx.at * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include +#include +#include "karamba.h" +#include "richtextlabel.h" + +RichTextLabel::RichTextLabel(karamba* k) : + Meter(k, 0, 0, 100, 100), + text(0), + source(""), + colorGrp(k->colorGroup()), + underlineLinks(false) +{ + originalSize = QSize(0, 0); +} + +RichTextLabel::RichTextLabel(karamba* k, int x, int y, int w, int h) : + Meter(k, x, y, w, h), + text(0), + source(""), + colorGrp(k->colorGroup()), + underlineLinks(false) +{ + kdDebug() << k_funcinfo << x << ", " << y << ", " << w << ", " << h << endl; + originalSize = QSize(w, h); +} + +RichTextLabel::~RichTextLabel() +{ + if (text != 0) + { + delete text; + text = 0; + } +} + +void RichTextLabel::setText(QString t, bool linkUnderline) +{ + source = t; + if (text != 0) + { + delete text; + text = 0; + } + else + { + // set underlineLinks only when RichTextLabel is created, not + // when text is changed. + underlineLinks = linkUnderline; + } + + text = new QSimpleRichText(t, font, m_karamba->theme().path(), + 0, // default QStyleSheet* + 0, // default QMimeSourceFactory + -1, // no pageBreak + Qt::blue, // (has no effect) link Color + underlineLinks); + + // set the text to a reasonable size + text->adjustSize(); + if(originalSize.width() < 1) + setWidth(text->width()); + else + text->setWidth(getWidth()); + if(originalSize.height() < 1) + setHeight(text->height()); +} + +void RichTextLabel::setValue(QString text) +{ + setText(text); +} + +void RichTextLabel::setValue(long v) +{ + setText(QString::number(v)); +} + +void RichTextLabel::setFont(QString f) +{ + font.setFamily(f); + if(text != 0) + text->setDefaultFont(font); +} + +QString RichTextLabel::getFont() const +{ + return font.family(); +} + +void RichTextLabel::setFontSize(int size) +{ + font.setPixelSize(size); + if(text != 0) + text->setDefaultFont(font); +} + +int RichTextLabel::getFontSize() const +{ + return font.pixelSize(); +} + +void RichTextLabel::setFixedPitch(bool fp) +{ + font.setFixedPitch(fp); + if(text != 0) + text->setDefaultFont(font); +} + +bool RichTextLabel::getFixedPitch() const +{ + return font.fixedPitch(); +} + +void RichTextLabel::setTextProps(TextField* t) +{ + if(t) + { + setFontSize(t->getFontSize()); + setFont(t->getFont()); + colorGrp.setColor(QColorGroup::Text, t->getColor()); + } +} + +void RichTextLabel::setWidth(int width) +{ + Meter::setWidth(width); + // rearrange text + text->setWidth(getWidth()); + if(originalSize.height() < 1) + setHeight(text->height()); +} + +void RichTextLabel::mUpdate(QPainter* p) +{ + if (hidden || text == 0) + { + return; + } + + int x = getX(); + int y = getY(); + int w = getWidth(); + int h = getHeight(); + QRect clipRect(x, y, w, h); + text->draw(p, x, y, clipRect, colorGrp, 0 /* no background */); +} + +bool RichTextLabel::click(QMouseEvent* e) +{ + if (hidden) + { + return false; + } + QPoint point(e->x() - getX(), e->y() - getY()); + QString anchor = text->anchorAt(point); + if (anchor[0] != '#') + { + if (e->button() == Qt::LeftButton) + { + KRun :: runCommand(anchor); + } + return false; + } + else + { + //call callback meterClicked + return true; + } +} + +QString RichTextLabel::anchorAt(int x, int y) +{ + QPoint point(x - getX(), y - getY()); + QString anchor = text->anchorAt(point); + if (anchor[0] == '#') + { + return anchor.remove(0, 1); + } + else + { + // ASSERT: should never happen + return ""; + } +} + +bool RichTextLabel::insideActiveArea(int x, int y) +{ + QPoint point(x - getX(), y - getY()); + return text->anchorAt(point) != ""; // && text -> inText(point); +} + +void RichTextLabel::setColorGroup(const QColorGroup &colorg) +{ + colorGrp = colorg; +} + +const QColorGroup & RichTextLabel::getColorGroup() const +{ + return colorGrp; +} + +#include "richtextlabel.moc" diff --git a/superkaramba/src/richtextlabel.h b/superkaramba/src/richtextlabel.h new file mode 100644 index 0000000..810b129 --- /dev/null +++ b/superkaramba/src/richtextlabel.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2003 by Wilfried Huss * + * Wilfried.Huss@gmx.at * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef RICHTEXTLABEL_H +#define RICHTEXTLABEL_H + +#include "meter.h" +#include +#include +#include +#include +#include +#include +#include +#include "karamba.h" + +class RichTextLabel : public Meter +{ + Q_OBJECT + public: + RichTextLabel(karamba*); + RichTextLabel(karamba* k, int x, int y, int w, int h); + ~RichTextLabel(); + + void setText(QString text, bool linkUnderline = false); + void setValue(QString text); + void setValue(long v); + QString getStringValue() { return source; }; + + void setFont(QString font); + QString getFont() const; + void setFontSize(int); + int getFontSize() const; + void setFixedPitch(bool); + bool getFixedPitch() const; + void setTextProps( TextField* t ); + void setColorGroup(const QColorGroup &colorg); + const QColorGroup &getColorGroup() const; + void setWidth(int width); + + virtual bool insideActiveArea(int, int); + + virtual bool click(QMouseEvent*); + virtual void mUpdate(QPainter*); + + QString anchorAt(int, int); + + private: + QSimpleRichText* text; + QString source; + QFont font; + QColorGroup colorGrp; + bool underlineLinks; + QSize originalSize; +}; + +#endif diff --git a/superkaramba/src/richtextlabel_python.cpp b/superkaramba/src/richtextlabel_python.cpp new file mode 100644 index 0000000..7ac14cd --- /dev/null +++ b/superkaramba/src/richtextlabel_python.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +* richtextlabel_python.cpp - Functions for richtext python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "richtextlabel.h" +#include "meter_python.h" +#include "richtextlabel_python.h" + +PyObject* py_createRichText(PyObject *, PyObject *args) +{ + long widget, underline = 0; + PyObject *text; + if (!PyArg_ParseTuple(args, (char*)"lO|l:createRichText", + &widget, &text, &underline)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + RichTextLabel *tmp = new RichTextLabel((karamba*)widget); + tmp->setText(PyString2QString(text), underline); + tmp->setTextProps(((karamba*)widget)->getDefaultTextProps()); + ((karamba*)widget)->meterList->append(tmp); + ((karamba*)widget)->clickList->append(tmp); + return (Py_BuildValue((char*)"l", (long)tmp)); +} + +PyObject* py_deleteRichText(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll:deleteRichText", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "RichTextLabel")) + return NULL; + + ((karamba*)widget)->deleteMeterFromSensors((Meter*)meter); + ((karamba*)widget)->clickList->removeRef((Meter*)meter); + return Py_BuildValue((char*)"l", + ((karamba*)widget)->meterList->removeRef((Meter*)meter)); +} + +PyObject* py_getThemeRichText(PyObject *self, PyObject *args) +{ + return py_getThemeMeter(self, args, "RichTextLabel"); +} + +PyObject* py_getRichTextSize(PyObject *self, PyObject *args) +{ + return py_getSize(self, args, "RichTextLabel"); +} + +PyObject* py_resizeRichText(PyObject *self, PyObject *args) +{ + return py_resize(self, args, "RichTextLabel"); +} + +PyObject* py_getRichTextPos(PyObject *self, PyObject *args) +{ + return py_getPos(self, args, "RichTextLabel"); +} + +PyObject* py_moveRichText(PyObject *self, PyObject *args) +{ + return py_move(self, args, "RichTextLabel"); +} + +PyObject* py_hideRichText(PyObject *self, PyObject *args) +{ + return py_hide(self, args, "RichTextLabel"); +} + +PyObject* py_showRichText(PyObject *self, PyObject *args) +{ + return py_show(self, args, "RichTextLabel"); +} + +PyObject* py_getRichTextValue(PyObject *self, PyObject *args) +{ + return py_getStringValue(self, args, "RichTextLabel"); +} + +PyObject* py_setRichTextValue(PyObject *self, PyObject *args) +{ + return py_setStringValue(self, args, "RichTextLabel"); +} + +PyObject* py_getRichTextSensor(PyObject *self, PyObject *args) +{ + return py_getSensor(self, args, "RichTextLabel"); +} + +PyObject* py_setRichTextSensor(PyObject *self, PyObject *args) +{ + return py_setSensor(self, args, "RichTextLabel"); +} + +PyObject* py_setRichTextFontSize(PyObject *, PyObject *args) +{ + long widget, textSensor; + long size; + if (!PyArg_ParseTuple(args, (char*)"lll:changeRichTextSize", + &widget, &textSensor, &size)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "RichTextLabel")) + return NULL; + ((RichTextLabel*)textSensor)->setFontSize( size ); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getRichTextFontSize(PyObject *, PyObject *args) +{ + long widget, textSensor; + if (!PyArg_ParseTuple(args, (char*)"ll:getRichTextSize", &widget, &textSensor)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "RichTextLabel")) + return NULL; + return Py_BuildValue((char*)"l", ((RichTextLabel*)textSensor)->getFontSize()); +} + +PyObject* py_setRichTextFont(PyObject *, PyObject *args) +{ + long widget, textSensor; + char* text; + if (!PyArg_ParseTuple(args, (char*)"lls:changeRichTextFont", + &widget, &textSensor, &text)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "RichTextLabel")) + return NULL; + ((RichTextLabel*)textSensor)->setFont( text ); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getRichTextFont(PyObject *, PyObject *args) +{ + long widget, textSensor; + if (!PyArg_ParseTuple(args, (char*)"ll:getRichTextFont", &widget, &textSensor)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "RichTextLabel")) + return NULL; + return Py_BuildValue((char*)"s", ((RichTextLabel*)textSensor)->getFont().ascii()); +} + +// Set the width of a Rich Text Label +PyObject* py_set_rich_text_width(PyObject*, PyObject* args) +{ + long widget, text, size; + if (!PyArg_ParseTuple(args, (char*)"lll:setRichTextWidth", &widget, &text, &size)) + return NULL; + if (!checkKarambaAndMeter(widget, text, "RichTextLabel")) + return NULL; + + RichTextLabel* richText = (RichTextLabel*) text; + + richText -> setWidth(size); + return Py_BuildValue((char*)"l", 1); +} + diff --git a/superkaramba/src/richtextlabel_python.h b/superkaramba/src/richtextlabel_python.h new file mode 100644 index 0000000..2d988de --- /dev/null +++ b/superkaramba/src/richtextlabel_python.h @@ -0,0 +1,338 @@ +/**************************************************************************** +* richtextlabel_python.h - Functions for richtext python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef RICHTEXTLABEL_PYTHON_H +#define RICHTEXTLABEL_PYTHON_H + +/** RichText/createRichText +* +* SYNOPSIS +* long createRichText(widget, text, underlineLinks) +* DESCRIPTION +* This creates creates a rich text string. underlineLinks is a boolean that +* determines if html links will be automatically underlined so that the +* user knows that the links can be clicked on. You need to save the return +* value of this function to call other functions on your rich text field, +* such as changeRichText(). +* +* The differance between Rich Text and a regular text field is that rich +* text fields can display HTML code embedded in your text. +* +* In a ... tag command is executed if the link is +* click with the left mouse button. +* +* Except if command starts with an '#' (ie: href="#value" ) the callback +* meterClicked is called with value (without the #) as the meter argument. +* +* Also inline images work. Unfortunatly currently only when using absolute +* paths. +* ARGUMENTS +* * long widget -- karamba +* * string text -- text for richtext +* * long underlineLinks -- should the links be underlined +* RETURN VALUE +* Pointer to new richtext meter +*/ +PyObject* py_createRichText(PyObject *self, PyObject *args); + +/** RichText/deleteRichText +* +* SYNOPSIS +* long deleteRichText(widget, richtext) +* DESCRIPTION +* This removes a richt text object from memory. Please do not call +* functions on "text" after calling deleteRichText, as it does not exist +* anymore and that could cause crashes in some cases. +* ARGUMENTS +* * long widget -- karamba +* * long widget -- richtext +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_deleteRichText(PyObject *self, PyObject *args); + +/** RichText/getThemeRichText +* +* SYNOPSIS +* long getThemeRichText(widget, name) +* DESCRIPTION +* You can reference richtext in your python code that was created in the +* theme file. Basically, you just add a NAME= value to the GRAPH line in +* the .theme file. Then if you want to use that object, instead of calling +* createRichText, you can call this function. +* +* The name you pass to the function is the same one that you gave it for +* the NAME= parameter in the .theme file. +* ARGUMENTS +* * long widget -- karamba +* * string name -- name of the richtext to get +* RETURN VALUE +* Pointer to richtext +*/ +PyObject* py_getThemeRichText(PyObject *self, PyObject *args); + +/** RichText/getRichTextSize +* +* SYNOPSIS +* tuple getRichTextSize(widget, richtext) +* DESCRIPTION +* Given a reference to a richtext object, this will return a tuple +* containing the height and width of a richtext object. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* RETURN VALUE +* size +*/ +PyObject* py_getRichTextSize(PyObject *self, PyObject *args); + +/** RichText/resizeRichText +* +* SYNOPSIS +* long resizeRichText(widget, richtext, w, h) +* DESCRIPTION +* This will resize richtext to new height and width. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* * long w -- new width +* * long h -- new height +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_resizeRichText(PyObject *self, PyObject *args); + +/** RichText/getRichTextPos +* +* SYNOPSIS +* tuple getRichTextPos(widget, richtext) +* DESCRIPTION +* Given a reference to a richtext object, this will return a tuple +* containing the x and y coordinate of a richtext object. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* RETURN VALUE +* pos +*/ +PyObject* py_getRichTextPos(PyObject *self, PyObject *args); + +/** RichText/moveRichText +* +* SYNOPSIS +* long moveRichText(widget, richtext, x, y) +* DESCRIPTION +* This moves a text object to a new x, y relative to your widget. In other +* words, (0,0) is the top corner of your widget, not the screen. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* * long x -- x coordinate +* * long y -- y coordinate +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_moveRichText(PyObject *self, PyObject *args); + +/** RichText/hideRichText +* +* SYNOPSIS +* long hideRichText(widget, richtext) +* DESCRIPTION +* This hides an richtext. In other words, during subsequent calls to +* widgetUpdate(), this richtext will not be drawn. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_hideRichText(PyObject *self, PyObject *args); + +/** RichText/showRichText +* +* SYNOPSIS +* long showRichText(widget, richtext) +* DESCRIPTION +* This shows an richtext. In other words, during subsequent calls to +* widgetUpdate(), this richtext will be drawn. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_showRichText(PyObject *self, PyObject *args); + +/** RichText/getRichTextValue +* +* SYNOPSIS +* string getRichTextValue(widget, richtext) +* DESCRIPTION +* Returns current richtext value. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* RETURN VALUE +* value +*/ +PyObject* py_getRichTextValue(PyObject *self, PyObject *args); + +/** RichText/changeRichText +* +* SYNOPSIS +* long changeRichText(widget, richtext, value) +* DESCRIPTION +* This will change the contents of a rich text widget. richText is the +* reference to the text object to change that you saved from the +* createRichText() call. text is a string containing the new value for the +* rich text object. +* +* The differance between Rich Text and a regular text field is that rich +* text fields can display HTML code embedded in your text. +* +* In a ... tag command is executed if the link is +* click with the left mouse button. +* +* Except if command starts with an '#' (ie: href="#value" ) the callback +* meterClicked is called with value (without the #) as the meter argument. +* +* Also inline images work. Unfortunatly currently only when using absolute +* paths. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* * string value -- new text +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setRichTextValue(PyObject *self, PyObject *args); + +/** RichText/getRichTextSensor +* +* SYNOPSIS +* string getRichTextSensor(widget, richtext) +* DESCRIPTION +* Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* RETURN VALUE +* sensor string +*/ +PyObject* py_getRichTextSensor(PyObject *self, PyObject *args); + +/** RichText/setRichTextSensor +* +* SYNOPSIS +* long setRichTextSensor(widget, richtext, sensor) +* DESCRIPTION +* Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* * string sensor -- new sensor as in theme files +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setRichTextSensor(PyObject *self, PyObject *args); + +/** RichText/changeRichTextSize +* +* SYNOPSIS +* long changeRichTextSize(widget, richtext, size) +* DESCRIPTION +* This will change the font size of a richtext widget. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* * long size -- new font point size +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setRichTextFontSize(PyObject *self, PyObject *args); + +/** RichText/getRichTextFontSize +* +* SYNOPSIS +* long getRichTextFontSize(widget, richtext) +* DESCRIPTION +* This will get the font size of a richtext widget. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* RETURN VALUE +* font point size +*/ +PyObject* py_getRichTextFontSize(PyObject *self, PyObject *args); + +/** RichText/changeRichTextFont +* +* SYNOPSIS +* long changeRichTextFont(widget, richtext, font) +* DESCRIPTION +* This will change the font of a richtext widget. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* * string font -- name of the new font +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setRichTextFont(PyObject *self, PyObject *args); + +/** RichText/getRichTextFont +* +* SYNOPSIS +* string getRichTextFont(widget, richtext) +* DESCRIPTION +* This will get the font of a richtext widget. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* RETURN VALUE +* font name +*/ +PyObject* py_getRichTextFont(PyObject *self, PyObject *args); + +/** RichText/setRichTextWidth +* +* SYNOPSIS +* long setRichTextWidth(widget, richtext, width) +* DESCRIPTION +* Given a reference to a rich text object, this function changes it's width +* to the specified value in pixels. +* +* The height adjusts automatically as the contents are changed with +* changeRichText. +* ARGUMENTS +* * long widget -- karamba +* * long richtext -- pointer to richtext +* * long width -- new width in pixels +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_set_rich_text_width(PyObject* self, PyObject* args); + +#endif // RICHTEXTLABEL_PYTHON_H diff --git a/superkaramba/src/rsssensor.cpp b/superkaramba/src/rsssensor.cpp new file mode 100644 index 0000000..1477062 --- /dev/null +++ b/superkaramba/src/rsssensor.cpp @@ -0,0 +1,136 @@ +/*************************************************************************** + * Copyright (C) 2003 by Ralph M. Churchill * + * mrchucho@yahoo.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "karambaapp.h" +#include "rsssensor.h" +#include +#include +#include +#include + +RssSensor::RssSensor( const QString &src, int interval, const QString &form, const QString &enc) + : Sensor(interval), + source(src), + format(form), + encoding(enc) + +{ + // Format: + // %t = title (DEFAULT) + // %d = desc + + if( !encoding.isEmpty() ) + { + codec = QTextCodec::codecForName( encoding.ascii() ); + if ( codec == 0) + codec = QTextCodec::codecForLocale(); + } + else + codec = QTextCodec::codecForLocale(); +} + +RssSensor::~RssSensor() +{ +} + +void RssSensor::update() +{ + QDomDocument doc; + QFile file; + QString tmpFile; + bool OK = false; + +#if defined(KDE_3_3) + if(KIO::NetAccess::download(KURL(source), tmpFile, karambaApp->parentWindow())) +#else + if(KIO::NetAccess::download(KURL(source), tmpFile)) +#endif + { + file.setName(tmpFile); + if ( file.open(IO_ReadOnly | IO_Translate) ) + { + if ( doc.setContent( &file ) ) + { + OK = true; + } + else + { + qDebug("Error on building DOM"); + } + } + else + { + qDebug("Error opening file"); + } + } + else { + qDebug( "Error Downloading: %s", source.ascii()); + } + + if ( OK ) + { + SensorParams *sp; + Meter *meter; + + QObjectListIt it( *objList ); + while (it != 0) + { + sp = (SensorParams*)(*it); + meter = sp->getMeter(); + + // this is a hack to force the + // clickmap to reset its data lists + meter->setValue(0); + + QDomElement docElem = doc.documentElement(); + QDomNode n = docElem.firstChild(); + if (!n.isNull()) + { + QDomNodeList links = docElem.elementsByTagName( "link" ); + QDomNodeList displays; + if ( format.contains( "%d", false ) > 0 ) + { + displays = docElem.elementsByTagName( "description" ); + } + else + { + displays = docElem.elementsByTagName( "title" ); + } + + QRegExp rx("^http://", false ); + for (uint i=1; i < displays.count(); ++i ) + { + QString dispTxt = displays.item( i ).toElement().text(); + QString linkTxt = links.item( i ).toElement().text(); + if( (rx.search(dispTxt) == -1) && (rx.search(linkTxt) != -1) ) + { + meter->setValue( dispTxt ); + meter->setValue( linkTxt ); + } + else + { + qDebug("Skipping"); + } + } + } + else + { + qDebug ("Document Node was null!!"); + } + + ++it; + } + } + // Cleanup + file.close(); + KIO::NetAccess::removeTempFile( tmpFile ); +} + +#include "rsssensor.moc" diff --git a/superkaramba/src/rsssensor.h b/superkaramba/src/rsssensor.h new file mode 100644 index 0000000..d896d04 --- /dev/null +++ b/superkaramba/src/rsssensor.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * Copyright (C) 2003 by Ralph M. Churchill * + * mrchucho@yahoo.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef RSSSENSOR_H +#define RSSSENSOR_H + +#include +#include +#include + +/** + * + * Ralph M. Churchill + **/ +class RssSensor : public Sensor +{ + Q_OBJECT +public: + RssSensor( const QString &source, int interval, const QString &format, const QString &encoding=QString::null ); + + ~RssSensor(); + + void update(); +private: + QTextCodec *codec; + QString source; + QString format; + QString encoding; + +}; + +#endif // RSSSENSOR_H diff --git a/superkaramba/src/sensor.cpp b/superkaramba/src/sensor.cpp new file mode 100644 index 0000000..6aba5d2 --- /dev/null +++ b/superkaramba/src/sensor.cpp @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "sensor.h" +Sensor::Sensor(int iMsec) +{ + objList = new QObjectList(); + objList->setAutoDelete( true ); + msec = iMsec; +} + +void Sensor::start() +{ + if (!timer.isActive()) + { + connect (&timer,SIGNAL(timeout()),this,SLOT(update())); + timer.start( (msec == 0)?1000:msec); + } +} + +Sensor::~Sensor() +{ +objList->clear(); +delete objList; +} + +void Sensor::addMeter( SensorParams *sp ) +{ + objList->append(sp); +} + +SensorParams* Sensor::hasMeter( Meter *meter ) +{ + QObjectListIt it( *objList ); + while ( it != 0 ) + { + if (((SensorParams*) *it)->getMeter() == meter) + { + return (SensorParams*) *it; + } + ++it; + } + return NULL; +} + +void Sensor::deleteMeter( Meter *meter ) +{ + SensorParams* sp = hasMeter(meter); + + if (sp) + objList->removeRef(sp); +} + +void Sensor::setMaxValue( SensorParams* ) +{ +} + +#include "sensor.moc" diff --git a/superkaramba/src/sensor.h b/superkaramba/src/sensor.h new file mode 100644 index 0000000..d7368b0 --- /dev/null +++ b/superkaramba/src/sensor.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef SENSOR_H +#define SENSOR_H +#include +#include +#include +#include +#include +#include + +#include "sensorparams.h" + +class Sensor : public QObject +{ + Q_OBJECT + +public: + Sensor( int msec = 1000 ); + void start(); + virtual ~Sensor(); + void addMeter( SensorParams *s ); + SensorParams* hasMeter( Meter *meter ); + void deleteMeter( Meter *meter ); + int isEmpty() { return objList->isEmpty(); }; + virtual void setMaxValue( SensorParams *s ); + +private: + int msec; + QTimer timer; + +protected: + QObjectList *objList; + +public slots: + virtual void update()=0; + +}; + +#endif // SENSOR_H diff --git a/superkaramba/src/sensorparams.cpp b/superkaramba/src/sensorparams.cpp new file mode 100644 index 0000000..954b2d5 --- /dev/null +++ b/superkaramba/src/sensorparams.cpp @@ -0,0 +1,34 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "sensorparams.h" + + +SensorParams::SensorParams(Meter* m) +{ + meter = m; +} + +SensorParams::~SensorParams() +{ +} + +void SensorParams::addParam( const QString &name, const QString &value){ + params[name] = value; +} + +QString SensorParams::getParam( const QString &name ) const +{ + return params[name]; +} + +Meter* SensorParams::getMeter() const +{ + return meter; +} diff --git a/superkaramba/src/sensorparams.h b/superkaramba/src/sensorparams.h new file mode 100644 index 0000000..24f0fae --- /dev/null +++ b/superkaramba/src/sensorparams.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#ifndef SENSORPARAMS_H +#define SENSORPARAMS_H + +#include "meter.h" +#include +#include +/** + * + * Hans Karlsson + **/ +class SensorParams : public QObject +{ +public: + SensorParams( Meter* ); + + ~SensorParams(); + + void addParam( const QString &name, const QString &value); + QString getParam( const QString& ) const; + + Meter* getMeter() const; +private: +Meter *meter; +QMap params; + +}; + +#endif diff --git a/superkaramba/src/sensorsensor.cpp b/superkaramba/src/sensorsensor.cpp new file mode 100644 index 0000000..9ff0d47 --- /dev/null +++ b/superkaramba/src/sensorsensor.cpp @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "sensorsensor.h" +#include + +SensorSensor::SensorSensor(int interval, char tempUnit) : Sensor( interval ) +{ +#if defined __FreeBSD__ || defined(Q_OS_NETBSD) + sensorMapBSD["VCore 1"] = "VC0"; + sensorMapBSD["VCore 2"] = "VC1"; + sensorMapBSD["+3.3V"] = "V33"; + sensorMapBSD["+5V"] = "V50P"; + sensorMapBSD["+12V"] = "V12P"; + sensorMapBSD["-12V"] = "V12N"; + sensorMapBSD["-5V"] = "V50N"; + sensorMapBSD["fan1"] = "FAN0"; + sensorMapBSD["fan2"] = "FAN1"; + sensorMapBSD["fan3"] = "FAN2"; + sensorMapBSD["temp1"] = "TEMP0"; + sensorMapBSD["temp2"] = "TEMP1"; + sensorMapBSD["temp3"] = "TEMP2"; +#endif + if(tempUnit == 'F') + extraParams = " -f"; + connect(&ksp, SIGNAL(receivedStdout(KProcess *, char *, int )), + this,SLOT(receivedStdout(KProcess *, char *, int ))); + connect(&ksp, SIGNAL(processExited(KProcess *)), + this,SLOT(processExited( KProcess * ))); + + // readValues(); +} + + +SensorSensor::~SensorSensor() +{ +} + +void SensorSensor::receivedStdout(KProcess *, char *buffer, int len ) +{ + buffer[len] = 0; + sensorResult += QString( QCString(buffer) ); +} + +void SensorSensor::processExited(KProcess *) +{ + QStringList stringList = QStringList::split('\n',sensorResult); + sensorResult = ""; + QStringList::Iterator it = stringList.begin(); +#if defined __FreeBSD__ || defined(Q_OS_NETBSD) + QRegExp rx( "^(\\S+)\\s+:\\s+[\\+\\-]?(\\d+\\.?\\d*)"); +#else + QRegExp rx( "^(.+):\\s+[\\+\\-]?(\\d+\\.?\\d*)"); +#endif + while( it != stringList.end()) + { + rx.search( *it ); + + if ( !rx.cap(0).isEmpty()) + { + sensorMap[rx.cap(1)] = rx.cap(2); + } + it++; + } + + QString format; + QString type; + SensorParams *sp; + Meter *meter; + + QObjectListIt lit( *objList ); + while (lit != 0) + { + sp = (SensorParams*)(*lit); + meter = sp->getMeter(); + format = sp->getParam("FORMAT"); + type = sp->getParam("TYPE"); + + if (type.length() == 0) + type = "temp2"; + + if (format.length() == 0 ) + { + format = "%v"; + } + +#if defined __FreeBSD__ || defined(Q_OS_NETBSD) + format.replace( QRegExp("%v", false), sensorMap[sensorMapBSD[type]]); +#else + format.replace( QRegExp("%v", false), sensorMap[type]); +#endif + meter->setValue(format); + ++lit; + } +} + +void SensorSensor::update() +{ + ksp.clearArguments(); +#if defined __FreeBSD__ || defined(Q_OS_NETBSD) + ksp << "mbmon -r -c 1" << extraParams; +#else + ksp << "sensors" << extraParams; +#endif + ksp.start( KProcess::NotifyOnExit,KProcIO::Stdout); +} + + +#include "sensorsensor.moc" diff --git a/superkaramba/src/sensorsensor.h b/superkaramba/src/sensorsensor.h new file mode 100644 index 0000000..82adf10 --- /dev/null +++ b/superkaramba/src/sensorsensor.h @@ -0,0 +1,49 @@ + +#ifndef SENSORSENSOR_H +#define SENSORSENSOR_H + +#include +#include +#include +#include +#include +#include +#include + + +#include "sensor.h" + +/** + * + * Hans Karlsson + **/ +class SensorSensor : public Sensor +{ + Q_OBJECT +public: + SensorSensor(int interval, char tempUnit); + + ~SensorSensor(); + + void update(); + + +private: + KShellProcess ksp; + QString extraParams; + + QMap sensorMap; +#ifdef __FreeBSD__ + QMap sensorMapBSD; +#endif + QString sensorResult; + +private slots: + void receivedStdout(KProcess *, char *buffer, int); + void processExited(KProcess *); + + + +}; + +#endif diff --git a/superkaramba/src/showdesktop.cpp b/superkaramba/src/showdesktop.cpp new file mode 100644 index 0000000..304dcb6 --- /dev/null +++ b/superkaramba/src/showdesktop.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#include +#include +#include + +#include "karambaapp.h" +#include "showdesktop.h" +#include "showdesktop.moc" + +ShowDesktop* ShowDesktop::the() +{ + static ShowDesktop showDesktop; + return &showDesktop; +} + +ShowDesktop::ShowDesktop() + : QObject() + , showingDesktop( false ) + , kWinModule( 0 ) +{ + kWinModule = new KWinModule( this ); + + // on desktop changes or when a window is deiconified, we abort the show desktop mode + connect( kWinModule, SIGNAL(currentDesktopChanged(int)), + SLOT(slotCurrentDesktopChanged(int))); + connect( kWinModule, SIGNAL(windowChanged(WId,unsigned int)), + SLOT(slotWindowChanged(WId,unsigned int))); +} + +void ShowDesktop::slotCurrentDesktopChanged(int) +{ + showDesktop( false ); +} + +#ifdef KDE_3_3 +#define NET_ALL_TYPES_MASK (NET::AllTypesMask) +#else +#define NET_ALL_TYPES_MASK (-1LU) +#endif + +void ShowDesktop::slotWindowChanged(WId w, unsigned int dirty) +{ + if (!showingDesktop) + return; + + // SELI this needs checking for kwin_iii (_NET_SHOWING_DESKTOP) + if ( dirty & NET::XAWMState ) + { + NETWinInfo inf(qt_xdisplay(), w, qt_xrootwin(), + NET::XAWMState | NET::WMWindowType); +#ifdef KDE_3_2 + NET::WindowType windowType = inf.windowType(NET_ALL_TYPES_MASK); +#else + NET::WindowType windowType = inf.windowType(); +#endif + if ((windowType == NET::Normal || windowType == NET::Unknown) + && inf.mappingState() == NET::Visible ) + { + // a window was deiconified, abort the show desktop mode. + iconifiedList.clear(); + showingDesktop = false; + emit desktopShown( false ); + } + } +} + +void ShowDesktop::showDesktop( bool b ) +{ + if( b == showingDesktop ) return; + showingDesktop = b; + + if ( b ) { + // this code should move to KWin after supporting NETWM1.2 + iconifiedList.clear(); + const QValueList windows = kWinModule->windows(); + QValueList::ConstIterator it; + QValueList::ConstIterator end( windows.end() ); + for ( it=windows.begin(); it!=end; ++it ) { + WId w = *it; + NETWinInfo info( qt_xdisplay(), w, qt_xrootwin(), + NET::XAWMState | NET::WMDesktop ); + if ( info.mappingState() == NET::Visible && + ( info.desktop() == NETWinInfo::OnAllDesktops + || info.desktop() == (int) kWinModule->currentDesktop() ) + ) { + iconifiedList.append( w ); + } + } + // find first, hide later, otherwise transients may get minimized + // with the window they're transient for + QValueList::ConstIterator endInconifiedList( iconifiedList.end() ); + for ( it=iconifiedList.begin(); it!=endInconifiedList; ++it ) { + KWin::iconifyWindow( *it, false ); + } + } else { + QValueList::ConstIterator it; + QValueList::ConstIterator end( iconifiedList.end() ); + for ( it=iconifiedList.begin(); it!=end; ++it ) { + KWin::deIconifyWindow( *it, false ); + } + } + + emit desktopShown( showingDesktop ); +} diff --git a/superkaramba/src/showdesktop.h b/superkaramba/src/showdesktop.h new file mode 100644 index 0000000..6a980dc --- /dev/null +++ b/superkaramba/src/showdesktop.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#ifndef __showdesktop_h__ +#define __showdesktop_h__ + +class KWinModule; + +/** + * Singleton class that handles desktop access (minimizing all windows) + */ +class ShowDesktop : public QObject +{ + Q_OBJECT + +public: + static ShowDesktop* the(); + bool desktopShowing() { return showingDesktop; } + +public slots: + void showDesktop( bool show ); + void toggle() { showDesktop( !desktopShowing() ); } + +signals: + void desktopShown( bool shown ); + +private slots: + void slotCurrentDesktopChanged(int); + void slotWindowChanged(WId w, unsigned int dirty); + +private: + ShowDesktop(); + + bool showingDesktop; + KWinModule* kWinModule; + QValueList iconifiedList; + +}; + +#endif diff --git a/superkaramba/src/sklineedit.cpp b/superkaramba/src/sklineedit.cpp new file mode 100644 index 0000000..a384e44 --- /dev/null +++ b/superkaramba/src/sklineedit.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** + * Copyright (c) 2005 Alexander Wiedenbruch + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "sklineedit.h" +#include "karamba.h" +#include "kdebug.h" + +SKLineEdit::SKLineEdit(QWidget *w, Input *i) : QLineEdit(w), m_input(i) +{ + frameColor = Qt::gray; + setBackgroundColor(Qt::white); +} + +SKLineEdit::~SKLineEdit() +{ +} + +void SKLineEdit::drawFrame(QPainter *p) +{ + p->setPen(frameColor); + p->drawRect(frameRect()); +} + +void SKLineEdit::drawContents(QPainter *p) +{ + QLineEdit::drawContents(p); +} + +void SKLineEdit::setFrameColor(QColor c) +{ + frameColor = c; + repaint(); +} + +void SKLineEdit::setBackgroundColor(QColor c) +{ + QLineEdit::setBackgroundColor(c); + repaint(); +} + +QColor SKLineEdit::getFrameColor() const +{ + return frameColor; +} + +void SKLineEdit::keyPressEvent(QKeyEvent* e) +{ + QLineEdit::keyPressEvent(e); + + if(!e->text().isEmpty()) + { + karamba* k = static_cast(parent()); + k->keyPressed(e->text(), m_input); + } +} + +void SKLineEdit::keyReleaseEvent(QKeyEvent* e) +{ + QLineEdit::keyReleaseEvent(e); +} + +Input* SKLineEdit::getInput() +{ + return m_input; +} diff --git a/superkaramba/src/sklineedit.h b/superkaramba/src/sklineedit.h new file mode 100644 index 0000000..2afd6c5 --- /dev/null +++ b/superkaramba/src/sklineedit.h @@ -0,0 +1,57 @@ +/**************************************************************************** + * Copyright (c) 2005 Alexander Wiedenbruch + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#ifndef SKLINEEDIT_H +#define SKLINEEDIT_H + +#include +#include +#include +#include +#include + +class Input; + +class SKLineEdit : public QLineEdit +{ + public: + SKLineEdit(QWidget *w, Input *i); + ~SKLineEdit(); + + void drawFrame(QPainter *p); + void drawContents(QPainter *p); + + void setFrameColor(QColor c); + QColor getFrameColor() const; + + void setBackgroundColor(QColor c); + + Input* getInput(); + + protected: + virtual void keyReleaseEvent(QKeyEvent* e); + virtual void keyPressEvent(QKeyEvent* e); + + private: + QColor frameColor; + Input* m_input; +}; + +#endif diff --git a/superkaramba/src/sknewstuff.cpp b/superkaramba/src/sknewstuff.cpp new file mode 100644 index 0000000..bf16fe6 --- /dev/null +++ b/superkaramba/src/sknewstuff.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include "karambaapp.h" +#include "themesdlg.h" +#ifdef HAVE_KNEWSTUFF +#include "sknewstuff.h" + +SKNewStuff::SKNewStuff( ThemesDlg *dlg ) : + KNewStuff( "superkaramba/themes", dlg ), + mDlg( dlg ) +{ +} + +bool SKNewStuff::install( const QString &fileName ) +{ + kdDebug() << "SKNewStuff::install(): " << fileName << endl; + + KMimeType::Ptr result = KMimeType::findByURL(fileName); + KStandardDirs myStdDir; + QFileInfo fi(fileName); + QString base = fi.baseName(); + QString baseDestDir =myStdDir.saveLocation("data", kapp->instanceName() + "/themes/", true); + const QString destDir = baseDestDir + base + "/"; + KStandardDirs::makeDir( destDir ); + + kdDebug() << "SKNewStuff::install() mimetype: " << result->name() << endl; + + if( result->name() == "application/x-gzip" || + result->name() == "application/x-tgz" || + result->name() == "application/x-bzip" || + result->name() == "application/x-bzip2" || + result->name() == "application/x-tbz" || + result->name() == "application/x-tbz2" || + result->name() == "application/x-tar" || + result->name() == "application/x-tarz") + { + kdDebug() << "SKNewStuff::install() gzip/bzip2 mimetype encountered" << + endl; + KTar archive( fileName ); + if ( !archive.open( IO_ReadOnly ) ) + return false; + const KArchiveDirectory *archiveDir = archive.directory(); + archiveDir->copyTo(destDir); + //Add the theme to the Theme Dialog + mDlg->addThemeToDialog(archiveDir, destDir); + archive.close(); + } + else if(result->name() == "application/x-zip" || + result->name() == "application/x-superkaramba") + { + kdDebug() << "SKNewStuff::install() zip mimetype encountered" << endl; + //TODO: write a routine to check if this is a valid .skz file + //otherwise we need to unpack it like it is an old theme that was packaged + //as a .zip instead of .bz2 or .tar.gz + KURL sourceFile(fileName); + KURL destFile( destDir + sourceFile.fileName() ); + if(!KIO::NetAccess::file_copy( sourceFile, destFile )) + { + return false; + } + KIO::NetAccess::removeTempFile( sourceFile.url() ); + //Add the skz theme to the Theme Dialog + mDlg->addSkzThemeToDialog(destFile.path()); + } + else if(result->name() == "plain/text") + { + kdDebug() << "SKNewStuff::install() plain text" << endl; + } + else if(result->name() == "text/html") + { + kdDebug() << "SKNewStuff::install() text/html" << endl; + KRun::runURL( m_sourceLink, "text/html"); + } + else + { + kdDebug() << "SKNewStuff::install() Error no compatible mimetype encountered to install" + << endl; + return false; + } + return true; +} + +bool SKNewStuff::createUploadFile( const QString &fileName ) +{ + kdDebug() << "SKNewStuff::createUploadFile(): " << fileName << endl; + return true; +} + +QString SKNewStuff::downloadDestination( KNS::Entry *entry ) +{ + KURL source = entry->payload(); + m_sourceLink = source; + + kdDebug() << "SKNewStuff::downloadDestination() url: " + << source.url() << " fileName: " << source.fileName() << endl; + QString file(source.fileName()); + if ( file.isEmpty() ) + { + kdDebug() << "The file was empty. " << source.url() << + " must be a URL link." << endl; + KRun::runURL( source, "text/html"); + return file; + } + return KGlobal::dirs()->saveLocation( "tmp" ) + source.fileName(); +} +#endif //HAVE_KNEWSTUFF diff --git a/superkaramba/src/sknewstuff.h b/superkaramba/src/sknewstuff.h new file mode 100644 index 0000000..c646f36 --- /dev/null +++ b/superkaramba/src/sknewstuff.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#ifndef SKNEWSTUFF_H +#define SKNEWSTUFF_H + +#include +#include "karambaapp.h" + +#ifdef HAVE_CONFIG_H + #include +#endif + +#ifdef HAVE_KNEWSTUFF +#include "knewstuff/knewstuff.h" +#include "knewstuff/entry.h" + +class ThemesDlg; +class KArchiveDirectory; + +class SKNewStuff : public KNewStuff +{ + public: + SKNewStuff( ThemesDlg * ); + + bool install( const QString &fileName ); + bool createUploadFile( const QString &fileName ); + QString downloadDestination( KNS::Entry *entry ); + + private: + ThemesDlg *mDlg; + KURL m_sourceLink; +}; + +#endif //HAVE_KNEWSTUFF +#endif //SKNEWSTUFF_H diff --git a/superkaramba/src/superkaramba.desktop b/superkaramba/src/superkaramba.desktop new file mode 100644 index 0000000..77d54f5 --- /dev/null +++ b/superkaramba/src/superkaramba.desktop @@ -0,0 +1,99 @@ +[Desktop Entry] +Name=SuperKaramba +Name[ar]=سوبركارامبا +Name[is]=SúperKaramba +Name[ne]=सुपरकराम्बा +Name[sr]=СуперКарамба +Exec=superkaramba %U +Icon=superkaramba +Type=Application +MimeType=application/x-superkaramba; +Comment=An engine for cool desktop eyecandy. +Comment[ar]=محرك لجماليات سطح مكتب لطيفة. +Comment[bg]=Модул за разкрасяване на работния плот +Comment[bs]=Pogon za cool ukrase desktopa. +Comment[ca]=Un motor per fer més vistós l'escriptori. +Comment[cs]=Nástroj pro úžasnou pracovní plochu, která je pastvou pro oči. +Comment[da]=En grænseflade for lækre øjegodter på desktoppen. +Comment[de]=Infrastruktur für faszinierende optische Effekte +Comment[el]=Μία μηχανή για εντυπωσιακές διακοσμήσεις επιφάνειας εργασίας. +Comment[es]=Un motor para añadir vistosidad al escritorio. +Comment[et]=Töölaua lahedate vidinate mootor. +Comment[eu]=Mahaigaineko efektu politentzako euskarri bat. +Comment[fa]=eyecandy موتوری برای سرد کردن رومیزی. +Comment[fi]=Työpöydän hieno koristelu. +Comment[fr]=Un moteur de bureau esthétique et sympathique +Comment[he]=מנוע שהופך את שולחן העבודה למגניב. +Comment[hu]=Keretrendszer grafikus asztali elemek használatához. +Comment[is]=Flottar skjáborðsviðbætur. +Comment[it]=Un motore per rendere il desktop più gradevole. +Comment[ja]=格好いいデスクトップ eyecandy エンジン。 +Comment[kk]=Үстелдің әсем бөлшектері. +Comment[km]=ម៉ាស៊ីន​សម្រាប់​កម្មវិធី​ត្រជាក់​ភ្នែក​របស់​ផ្ទៃតុ +Comment[lt]=Šaunių darbastalio papuošimų priedas. +Comment[nb]=Et program for kule skrivebordseffekter. +Comment[nds]=En Ümgeven för wunnerbore Schriefdischeffekten. +Comment[ne]=ठन्डा डेस्कटप आइक्यान्डीका लागि इन्जिन । +Comment[nl]=Een programma voor bureaubladverfraaiing. +Comment[nn]=Eit rammeverk for lekre skrivebord. +Comment[pl]=Narzędzie do tworzenia efektownego pulpitu. +Comment[pt]=Um motor para embelezar o ecrã. +Comment[pt_BR]=Mecanismo para recursos gráficos interessantes. +Comment[ru]=Набор виджетов рабочего стола. +Comment[sk]=Podpora pre cool desktop eyecandy. +Comment[sl]=Pogon za lišpanje namizja. +Comment[sr]=Машина за лицкање радне површине. +Comment[sr@Latn]=Mašina za lickanje radne površine. +Comment[sv]=Ett gränssnitt för häftigt ögongodis på skrivbordet. +Comment[tr]=Masaüstünde güzel görünüm sağlayan bir motor. +Comment[uk]=Рушій для елементів стільниці. +Comment[zh_CN]=桌面养眼引擎。 +Comment[zh_TW]=桌面佈景選擇程式 +GenericName=Desktop Widgets +GenericName[ar]=أدوات سطح المكتب +GenericName[bg]=Графични контроли +GenericName[bs]=Desktop ukrasi +GenericName[ca]=Estris de l'escriptori +GenericName[cs]=Udělátka pro pracovní plochu +GenericName[da]=Desktopkontroller +GenericName[de]=Arbeitsflächen-Erweiterungen +GenericName[el]=Γραφικά συστατικά επιφάνειας εργασίας +GenericName[eo]=Tabulaj fenestraĵoj +GenericName[es]=Elementos visuales para el escritorio +GenericName[et]=Töölauavidinad +GenericName[eu]=Mahaigaineko trepetak +GenericName[fa]=عنصرهای رومیزی +GenericName[fi]=Työpöytäelementit +GenericName[fr]=Éléments graphiques pour le bureau +GenericName[ga]=Giuirléidí Deisce +GenericName[he]=יישומונים על שולחן העבודה +GenericName[hu]=Asztali programelemek +GenericName[is]=Skjáborðshlutir +GenericName[it]=Elementi desktop +GenericName[ja]=デスクトップウィジェット +GenericName[ka]=სამუშაო მაგიდის ელემენტები +GenericName[kk]=Үстелдің бөлшектері +GenericName[km]=វត្ថុ​មើលឃើញ​របស់​ផ្ទៃតុ +GenericName[lt]=Darbastalio valdikliai +GenericName[nb]=Skjermelement for skrivebordet +GenericName[nds]=Schriefdisch-Verwiedern +GenericName[ne]=डेस्कटप विजेट +GenericName[nl]=Bureaubladprogramma's +GenericName[nn]=Skrivebordsprogram +GenericName[pa]=ਵੇਹੜਾ ਸਹਾਇਕ +GenericName[pl]=Aplety pulpitu +GenericName[pt]=Elementos do Ecrã +GenericName[pt_BR]=Componentes para o Desktop +GenericName[ru]=Виджеты рабочего стола +GenericName[sk]=Prvky pracovnej plochy +GenericName[sl]=Namizni gradniki +GenericName[sr]=Додаци десктопа +GenericName[sr@Latn]=Dodaci desktopa +GenericName[sv]=Grafiska skrivbordskomponenter +GenericName[tr]=Masaüstü Ögeleri +GenericName[uk]=Віджети стільниці +GenericName[zh_CN]=桌面部件 +GenericName[zh_TW]=桌面元件 +DocPath=superkaramba/index.html +Categories=Qt;KDE;Utility;X-KDE-Utilities-Desktop; +OnlyShowIn=KDE; diff --git a/superkaramba/src/superkaramba.kcfg b/superkaramba/src/superkaramba.kcfg new file mode 100644 index 0000000..c586b3c --- /dev/null +++ b/superkaramba/src/superkaramba.kcfg @@ -0,0 +1,16 @@ + + + + + + + + true + + + + + + + + diff --git a/superkaramba/src/superkaramba.lsm b/superkaramba/src/superkaramba.lsm new file mode 100644 index 0000000..614fc65 --- /dev/null +++ b/superkaramba/src/superkaramba.lsm @@ -0,0 +1,16 @@ +Begin3 +Title: SuperKaramba - Eye-candy for KDE +Version: 0.40 +Entered-date: +Description: +Keywords: KDE3 Qt +Author: Hans Karlsson +Maintained-by: Adam Geitgey +Home-page: http://netdragon.sourceforge.net/ssuperkaramba.html +Alternate-site: +Primary-site: http://netdragon.sourceforge.net/ssuperkaramba.html + xxxxxx superkaramba-0.40.tar.gz + xxx superkaramba-0.40.lsm +Platform: Linux. Needs KDE 3.? QT 3.? +Copying-policy: GPL +End diff --git a/superkaramba/src/superkarambasettings.kcfgc b/superkaramba/src/superkarambasettings.kcfgc new file mode 100644 index 0000000..deb102f --- /dev/null +++ b/superkaramba/src/superkarambasettings.kcfgc @@ -0,0 +1,4 @@ +File=superkaramba.kcfg +ClassName=SuperKarambaSettings +Singleton=true +Mutators=true \ No newline at end of file diff --git a/superkaramba/src/superkarambaui.rc b/superkaramba/src/superkarambaui.rc new file mode 100644 index 0000000..fcecdab --- /dev/null +++ b/superkaramba/src/superkarambaui.rc @@ -0,0 +1,8 @@ + + + + C&ustom + + + + diff --git a/superkaramba/src/svcgrp_python.cpp b/superkaramba/src/svcgrp_python.cpp new file mode 100644 index 0000000..5a59c82 --- /dev/null +++ b/superkaramba/src/svcgrp_python.cpp @@ -0,0 +1,156 @@ +/*************************************************************************** + * * + * Copyright (C) 2004 Luke Kenneth Casson Leighton * + * * + * contains code from kickermenu: * + * * + * Copyright (C) 2004 by Tommy Brander * + * tbr00001@student.mdh.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include "task_python.h" +#include +#include +#include "karamba.h" +#include "svcgrp_python.h" + +static PyObject *get_svc_grp(KServiceGroup::Ptr const& g) +{ + //Avoid adding empty groups. + KServiceGroup::Ptr subMenuRoot = KServiceGroup::group(g->relPath()); + if (subMenuRoot->childCount() == 0) + return NULL; + // Ignore dotfiles. + if ((g->name().at(0) == '.')) + return NULL; + + PyObject *tuple = PyTuple_New(2); + PyObject *dict = PyDict_New(); + + PyDict_SetItem(dict, PyString_FromString("caption"), + PyString_FromString(g->caption().ascii())); + if (g->comment() != NULL) + PyDict_SetItem(dict, PyString_FromString("comment"), + PyString_FromString(g->comment().ascii())); + if (g->icon() != NULL) + PyDict_SetItem(dict, PyString_FromString("icon"), + PyString_FromString(g->icon().ascii())); + PyDict_SetItem(dict, PyString_FromString("relpath"), + PyString_FromString(g->relPath().ascii())); + + PyTuple_SET_ITEM(tuple, 0, Py_BuildValue((char*)"l", 0)); + PyTuple_SET_ITEM(tuple, 1, dict); + + return tuple; +} + + +static PyObject *get_svc(KService::Ptr const& g) +{ + PyObject *tuple = PyTuple_New(2); + PyObject *dict = PyDict_New(); + + if (g->exec() != NULL) + PyDict_SetItem(dict, PyString_FromString("exec"), + PyString_FromString(g->exec().ascii())); + if (g->menuId() != NULL) + PyDict_SetItem(dict, PyString_FromString("menuid"), + PyString_FromString(g->menuId().ascii())); + if (g->name() != NULL) + PyDict_SetItem(dict, PyString_FromString("name"), + PyString_FromString(g->name().ascii())); + if (g->path() != NULL) + PyDict_SetItem(dict, PyString_FromString("path"), + PyString_FromString(g->path().ascii())); + if (g->icon() != NULL) + PyDict_SetItem(dict, PyString_FromString("icon"), + PyString_FromString(g->icon().ascii())); + if (g->library() != NULL) + PyDict_SetItem(dict, PyString_FromString("library"), + PyString_FromString(g->library().ascii())); + if (g->comment() != NULL) + PyDict_SetItem(dict, PyString_FromString("comment"), + PyString_FromString(g->comment().ascii())); + if (g->type() != NULL) + PyDict_SetItem(dict, PyString_FromString("type"), + PyString_FromString(g->type().ascii())); + if (g->genericName() != NULL) + PyDict_SetItem(dict, PyString_FromString("genericname"), + PyString_FromString(g->genericName().ascii())); + /* + PyDict_SetItem(dict, PyString_FromString("terminal"), + Py_BuildValue("l", g->terminal())); + PyDict_SetItem(dict, PyString_FromString("type"), + PyString_FromString(g->type().ascii())); + PyDict_SetItem(dict, PyString_FromString("username"), + PyString_FromString(g->username().ascii())); + PyDict_SetItem(dict, PyString_FromString("substuid"), + Py_BuildValue("l", g->substituteUid())); + PyDict_SetItem(dict, PyString_FromString("path"), + PyString_FromString(g->path().ascii())); + */ + + PyTuple_SET_ITEM(tuple, 0, Py_BuildValue((char*)"l", 1)); + PyTuple_SET_ITEM(tuple, 1, dict); + + return tuple; +} + +static PyObject *getServiceGroups(const char *rel_path) +{ + PyObject *list = PyList_New(0); + + // We ask KSycoca to give us all services (sorted). + KServiceGroup::Ptr root = KServiceGroup::group(rel_path); + + if (!root || !root->isValid()) + return list; + + bool excludeNoDisplay_ = true; + bool detailed_ = false; + bool detailedNamesFirst_ = false; + + KServiceGroup::List sl = root->entries(true, excludeNoDisplay_, true, detailed_ && !detailedNamesFirst_); + + QStringList suppressGenericNames = root->suppressGenericNames(); + + KServiceGroup::List::ConstIterator it = sl.begin(); + for (; it != sl.end(); ++it) + { + KSycocaEntry * e = *it; + + PyObject *tuple = NULL; + if (e->isType(KST_KServiceGroup)) { + KServiceGroup::Ptr g(static_cast(e)); + tuple = get_svc_grp(g); + } + else if (e->isType(KST_KService)) { + KService::Ptr g(static_cast(e)); + tuple = get_svc(g); + } + + if (tuple != NULL) + PyList_Append(list, tuple); + } + + return list; +} + +PyObject* py_get_service_groups(PyObject *, PyObject *args) +{ + char *rel_path; + if (!PyArg_ParseTuple(args, (char*)"s:getServiceGroup", &rel_path)) + return NULL; + return getServiceGroups(rel_path); +} + diff --git a/superkaramba/src/svcgrp_python.h b/superkaramba/src/svcgrp_python.h new file mode 100644 index 0000000..e8d4e4b --- /dev/null +++ b/superkaramba/src/svcgrp_python.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2004 Luke Kenneth Casson Leighton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef SVC_GRPS_PYTHON_H +#define SVC_GRPS_PYTHON_H + +#include + +//****p* Misc/getServiceGroups +// +// SYNOPSIS +// list getServiceGroups(widget, path) +// DESCRIPTION +// This function returns a list of services and service groups +// that are in the user's KDE Menu. It is not a recursive +// function, so if there are submenus (service groups) in the +// returned results, you must call getServiceGroups with the +// path of the submenu in order to obtain the information in +// that submenu. +// The return result is complex: it's a list of tuples. +// The tuple contains two elements - a 1 if the second element +// is a service, and a 0 if it's a service group. +// The second element is a dictionary, with keys (if they exist) +// of caption, comment, icon, and relpath if it's a service group, +// and keys (if they exist) of exec, menuid, name, path, icon, +// library, comment, type and genericname. +// To fully understand the return results of this function, +// it is thoroughly recommended // that you look up the +// KDE documentation on KServiceGroup and KService. +// ARGUMENTS +// * long widget -- karamba +// * string path -- path to the Service Group you wish to retrieve +// RETURN VALUE +// List of Dictionaries of services and service groups +//*** +PyObject* py_get_service_groups(PyObject *self, PyObject *args); + +#endif // SVC_GRPS_PYTHON_H diff --git a/superkaramba/src/systemtray.cpp b/superkaramba/src/systemtray.cpp new file mode 100644 index 0000000..312fe59 --- /dev/null +++ b/superkaramba/src/systemtray.cpp @@ -0,0 +1,231 @@ +/*************************************************************************** + copyright (C) 2003 Adam Geitgey + 2003 Sven Leiber + 2000-2001 Matthias Ettrich + 2000-2001 Matthias Elter + 2001 Carsten Pfeiffer + 2001 Martijn Klingens + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "systemtray.h" + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +Systemtray::Systemtray(QWidget* parent) + : QWidget(parent,0,0) +{ + setBackgroundOrigin(ParentOrigin); + setBackgroundMode(FixedPixmap); + m_Wins.setAutoDelete(true); +} + + +Systemtray::~Systemtray() +{ + m_Wins.clear(); +} + +int Systemtray::getTraySize() { + + return (int) kwin_module->systemTrayWindows().size(); +} + +void Systemtray::updateBackgroundPixmap ( const QPixmap & pixmap) { + QXEmbed *emb; + setPaletteBackgroundPixmap (pixmap); + for (emb = m_Wins.first(); emb != 0L; emb = m_Wins.next()) { + + //Stupid stupid stupid work around for annoying bug + //QXEmbed ignores setBackgroundOrigin(AncestorOrigin).... + QPixmap bug = QPixmap(emb->size()); + bitBlt(&bug, 0, 0, &pixmap, emb->parentWidget()->x()+emb->x(), emb->parentWidget()->y()+emb->y(), emb->width(), emb->height(),Qt::CopyROP, false); + emb->setPaletteBackgroundPixmap (bug); + + } + + QPoint topPoint = mapToGlobal(QPoint(0,0)); + Window hack = XCreateSimpleWindow(qt_xdisplay(), winId(), 0,0, width(), height(), 0, 0, 0); + XRaiseWindow(qt_xdisplay(), hack); + XMapWindow(qt_xdisplay(), hack); + XUnmapWindow(qt_xdisplay(), hack); + XDestroyWindow(qt_xdisplay(), hack); +} + +void Systemtray::initSystray( void ) +{ + bool existing = false; + //bool content = false; + Display *display = qt_xdisplay(); + no_of_systray_windows = 0; + + kwin_module = new KWinModule(); + systemTrayWindows = kwin_module->systemTrayWindows(); + QValueList::ConstIterator end(systemTrayWindows.end()); + for (QValueList::ConstIterator it = systemTrayWindows.begin(); it!=end; ++it) + { + no_of_systray_windows++; + QXEmbed *emb; + + emb = new QXEmbed(this); + emb->setBackgroundMode(FixedPixmap); + + emb->setAutoDelete(false); + + connect(emb, SIGNAL(embeddedWindowDestroyed()), SLOT(updateTrayWindows())); + + m_Wins.append(emb); + + emb->embed(*it); + emb->resize(24, 24); + emb->show(); + existing = true; + } + + updateTrayWindows(); + + connect(kwin_module, SIGNAL(systemTrayWindowAdded(WId)), SLOT(systemTrayWindowAdded(WId))); + connect(kwin_module, SIGNAL(systemTrayWindowRemoved(WId)), SLOT(systemTrayWindowRemoved(WId))); + + QCString screenstr; + screenstr.setNum(qt_xscreen()); + QCString trayatom = "_NET_SYSTEM_TRAY_S" + screenstr; + + net_system_tray_selection = XInternAtom( display, trayatom, false ); + net_system_tray_opcode = XInternAtom( display, "_NET_SYSTEM_TRAY_OPCODE", false ); + + // Acquire system tray + XSetSelectionOwner( display, + net_system_tray_selection, + winId(), + CurrentTime ); + + WId root = qt_xrootwin(); + + if (XGetSelectionOwner(display, net_system_tray_selection) == winId()) + { + XClientMessageEvent xev; + + xev.type = ClientMessage; + xev.window = root; + + xev.message_type = XInternAtom(display, "MANAGER", false); + xev.format = 32; + + xev.data.l[0] = CurrentTime; + xev.data.l[1] = net_system_tray_selection; + xev.data.l[2] = winId(); + xev.data.l[3] = 0; /* Manager specific data */ + xev.data.l[4] = 0; /* Manager specific data */ + + XSendEvent( display, root, false, StructureNotifyMask, (XEvent *)&xev ); + } +} + +void Systemtray::updateTrayWindows( void ) +{ + QXEmbed *emb; + + emb = m_Wins.first(); + while ((emb = m_Wins.current()) != 0L) + { + WId wid = emb->embeddedWinId(); + if ((wid == 0) || !kwin_module->systemTrayWindows().contains(wid) ) + m_Wins.remove(emb); + else + m_Wins.next(); + } + layoutSystray(); +} +void Systemtray::layoutSystray() +{ + int i = 0, a = 0; + + QXEmbed* emb; + int x = 0; + int count = 0; + + //How many systray icons can fit on a line? + int aa = width() / 24; + + if(aa < 1) + { + /* The place is to small to display a icon we make than one line with + icons that we display at the top */ + aa = 1; + } + + for (emb = m_Wins.first(); emb != 0L; emb = m_Wins.next()) { + x = 2+i*24; + + emb->move(a*24, x); + a++; + + if(a+1 > aa) { + a = 0; + i++; + } + + count++; + emb->repaint(); + } +} + +void Systemtray::systemTrayWindowAdded( WId w ) +{ + //bool content = false; + QXEmbed *emb; + no_of_systray_windows++; + emit updated(); + + emb = new QXEmbed(this); + + emb->setAutoDelete(false); + //emb->setBackgroundMode(X11ParentRelative); + emb->setBackgroundMode(FixedPixmap); + connect(emb, SIGNAL(embeddedWindowDestroyed()), SLOT(updateTrayWindows())); + m_Wins.append(emb); + + emb->embed(w); + emb->resize(24, 24); + emb->show(); + + layoutSystray(); +} + +void Systemtray::systemTrayWindowRemoved(WId) +{ + no_of_systray_windows--; + emit updated(); + updateTrayWindows(); +} + +int Systemtray::getCurrentWindowCount() +{ + return no_of_systray_windows; +} + +#include "systemtray.moc" diff --git a/superkaramba/src/systemtray.h b/superkaramba/src/systemtray.h new file mode 100644 index 0000000..768e00c --- /dev/null +++ b/superkaramba/src/systemtray.h @@ -0,0 +1,69 @@ +/* + *************************************************************************** + copyright (C) 2003 Adam Geitgey + 2003 Sven Leiber + 2000-2001 Matthias Ettrich + 2000-2001 Matthias Elter + 2001 Carsten Pfeiffer + 2001 Martijn Klingens + *************************************************************************** + + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + *************************************************************************** + */ + +#ifndef TESTCARDAPPLET_H +#define TESTCARDAPPLET_H + +#include +#include +#include +#include + +class KWinModule; + +typedef long unsigned int Atom; + + +class Systemtray : public QWidget +{ + Q_OBJECT +public: + Systemtray(QWidget* parent); + ~Systemtray(); + + void updateBackgroundPixmap ( const QPixmap & ); + + int getCurrentWindowCount(); + + virtual void initSystray( void ); + +public slots: + void updateTrayWindows(); + int getTraySize(); + void systemTrayWindowAdded( WId w ); + void systemTrayWindowRemoved( WId w ); + void layoutSystray(); + +signals: + void updated(); + +private: + KWinModule *kwin_module; + QValueList systemTrayWindows; + + QPtrList m_Wins; + + Atom net_system_tray_selection; + Atom net_system_tray_opcode; + + int no_of_systray_windows; +}; + +#endif diff --git a/superkaramba/src/systray_python.cpp b/superkaramba/src/systray_python.cpp new file mode 100644 index 0000000..cb8909a --- /dev/null +++ b/superkaramba/src/systray_python.cpp @@ -0,0 +1,199 @@ +/**************************************************************************** +* systray_python.h - Functions for systray python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "meter.h" +#include "meter_python.h" +#include "systray_python.h" + +long moveSystray(long widget, long x, long y, long w, long h) +{ + karamba* currTheme = (karamba*)widget; + + if (currTheme->systray != 0) { + currTheme->systray->move((int)x,(int)y); + currTheme->systray->setMinimumSize((int)w,(int)h); + currTheme->systray->layoutSystray(); + currTheme->systray->show(); + } + return 1; +} + +PyObject* py_move_systray(PyObject *, PyObject *args) +{ + long widget, x, y, w, h; + if (!PyArg_ParseTuple(args, (char*)"lllll:moveSystray", &widget, &x, &y, &w, &h)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", moveSystray(widget, x, y, w, h)); +} + +/* now a method we need to expose to Python */ +long showSystray(long widget) +{ + karamba* currTheme = (karamba*)widget; + + if (currTheme->systray != 0) + { + currTheme->systray->show(); + } + return 1; +} + +PyObject* py_show_systray(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:showSystray", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", showSystray(widget)); +} + +/* now a method we need to expose to Python */ +long hideSystray(long widget) +{ + karamba* currTheme = (karamba*)widget; + + if (currTheme->systray != 0) + { + currTheme->systray->hide(); + } + return 1; +} + +PyObject* py_hide_systray(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:hideSystray", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", hideSystray(widget)); +} + +/* now a method we need to expose to Python */ +long createSystray(long widget, long x, long y, long w, long h) +{ + karamba* currTheme = (karamba*)widget; + + //Don't create more than one systray + if (currTheme->systray == 0) { + currTheme->systray = new Systemtray(currTheme); + currTheme->systray->move((int)x,(int)y); + currTheme->systray->setMinimumSize((int)w,(int)h); + currTheme->systray->initSystray(); + QObject::connect(currTheme->systray,SIGNAL(updated()), + currTheme,SLOT(systrayUpdated())); + currTheme->systray->show(); + } + + return 1; +} + +PyObject* py_create_systray(PyObject *, PyObject *args) +{ + long widget, x, y, w, h; + if (!PyArg_ParseTuple(args, (char*)"lllll:createSystray", &widget, &x, &y, &w, &h)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", createSystray(widget, x, y, w, h)); +} + +/* now a method we need to expose to Python */ +long getCurrentWindowCount(long widget) +{ + karamba* currTheme = (karamba*)widget; + int num; + + num = 0; + + if (currTheme->systray != 0) + { + num = currTheme->systray->getCurrentWindowCount(); + } + return num; +} + +PyObject* py_get_current_window_count(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:getCurrentWindowCount", &widget )) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", getCurrentWindowCount(widget)); +} + +/* now a method we need to expose to Python */ +long updateSystrayLayout(long widget) +{ + karamba* currTheme = (karamba*)widget; + + if (currTheme->systray != 0) + { + currTheme->systray->layoutSystray(); + } + return 1; +} + +PyObject* py_update_systray_layout(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:updateSystrayLayout", &widget )) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", updateSystrayLayout(widget)); +} + +/* get the systray size from python */ +int getSystraySize(long widget) { + karamba* currTheme = (karamba*)widget; + if(currTheme->systray == 0) { + return 0; + } else { + return currTheme->systray->getTraySize(); + } +} + +// Returns the size of the systray +PyObject* py_get_systray_size(PyObject*, PyObject* args) +{ + long widget; + + if (!PyArg_ParseTuple(args, "l:getSystraySize", &widget)) + return NULL; + + return Py_BuildValue("l", getSystraySize(widget)); +} + diff --git a/superkaramba/src/systray_python.h b/superkaramba/src/systray_python.h new file mode 100644 index 0000000..045382a --- /dev/null +++ b/superkaramba/src/systray_python.h @@ -0,0 +1,117 @@ +/**************************************************************************** +* systray_python.h - Functions for systray python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef SYSTRAY_PYTHON_H +#define SYSTRAY_PYTHON_H + +struct _object; +typedef _object PyObject; + +/** Systray/moveSystray +* +* SYNOPSIS +* long moveSystray(widget, x, y, w, h) +* DESCRIPTION +* ?? +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * long w -- width +* * long h -- height +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_move_systray(PyObject *self, PyObject *args); + +/** Systray/showSystray +* +* SYNOPSIS +* long showSystray(widget) +* DESCRIPTION +* ?? +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_show_systray(PyObject *self, PyObject *args); + +/** Systray/hideSystray +* +* SYNOPSIS +* long hideSystray(widget) +* DESCRIPTION +* ?? +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_hide_systray(PyObject *self, PyObject *args); + +/** Systray/createSystray +* +* SYNOPSIS +* long createSystray(widget, x, y, w, h) +* DESCRIPTION +* ?? +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * long w -- width +* * long h -- height +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_create_systray(PyObject *self, PyObject *args); + +/** Systray/getCurrentWindowCount +* +* SYNOPSIS +* long getCurrentWindowCount(widget) +* DESCRIPTION +* ?? +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* window count +*/ +PyObject* py_get_current_window_count(PyObject *self, PyObject *args); + +/** Systray/updateSystrayLayout +* +* SYNOPSIS +* long getCurrentWindowCount(widget) +* DESCRIPTION +* ?? +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_update_systray_layout(PyObject *self, PyObject *args); +PyObject* py_get_systray_size(PyObject *self, PyObject *args); + +#endif // SYSTRAY_PYTHON_H diff --git a/superkaramba/src/task_python.cpp b/superkaramba/src/task_python.cpp new file mode 100644 index 0000000..7a74559 --- /dev/null +++ b/superkaramba/src/task_python.cpp @@ -0,0 +1,375 @@ +/**************************************************************************** +* task_python.cpp - Functions for task python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "meter.h" +#include "meter_python.h" +#include "task_python.h" + +// This does something with a task, such as minimize or close it +int performTaskAction(long widget, long ctask, long action) +{ + karamba* currTheme = (karamba*)widget; + Task* currTask = 0; + Task* task; + + TaskList taskList = currTheme -> taskManager.tasks(); + + for (task = taskList.first(); task; task = taskList.next()) + { + if ((long)task == (long)ctask) + { + currTask = task; + } + } + + if (currTask != 0) + { + switch (action) + { + case 1: + currTask->maximize(); + break; + + case 2: + currTask->restore(); + break; + + case 3: + currTask->iconify(); + break; + + case 4: + currTask->close(); + break; + + case 5: + currTask->activate(); + break; + + case 6: + currTask->raise(); + break; + + case 7: + currTask->lower(); + break; + + case 8: + currTask->activateRaiseOrIconify(); + break; + + case 9: + currTask->toggleAlwaysOnTop(); + break; + + case 10: + currTask->toggleShaded(); + break; + + default: + printf("You are trying to perform an invalid action in \ + performTaskAction\n"); + } + return 1; + } + else + { + return 0; + } +} + +PyObject* py_perform_task_action(PyObject *, PyObject *args) +{ + long widget, task, action; + if (!PyArg_ParseTuple(args, (char*)"lll:performTaskAction", + &widget, &task, &action)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", performTaskAction(widget, task, action)); +} + +// This returns all the info about a certain task +// Return type is a Python List +PyObject* getTaskInfo(long widget, long ctask) +{ + karamba* currTheme = (karamba*)widget; + Task* currTask = 0; + Task* task; + + TaskList taskList = currTheme -> taskManager.tasks(); + + for (task = taskList.first(); task; task = taskList.next()) + { + if ((long)task == (long)ctask) + { + currTask = task; + } + + } + + if (currTask != 0) + { + PyObject* pList = PyList_New(0); + + //Task Name + if (currTask->name() != NULL) + { + PyList_Append(pList, PyString_FromString(currTask->name().latin1())); + } + else + { + PyList_Append(pList, PyString_FromString("")); + } + + //Icon Name + if (currTask->iconName() != NULL) + { + PyList_Append(pList, PyString_FromString(currTask->iconName().latin1())); + } + else + { + PyList_Append(pList, PyString_FromString("")); + } + + //Class Name + if (currTask->className() != NULL) + { + PyList_Append(pList, PyString_FromString(currTask->className().latin1())); + } + else + { + PyList_Append(pList, PyString_FromString("")); + } + + // Desktop this task is on + PyList_Append(pList, PyInt_FromLong(currTask->desktop())); + + // is it maximized? + PyList_Append(pList, PyInt_FromLong(currTask->isMaximized())); + + // is it iconified? + PyList_Append(pList, PyInt_FromLong(currTask->isIconified())); + + // is it shaded? + PyList_Append(pList, PyInt_FromLong(currTask->isShaded())); + + // is it focused? + PyList_Append(pList, PyInt_FromLong(currTask->isActive())); + + // a reference back to itself + PyList_Append(pList, PyInt_FromLong((long)currTask)); + + return pList; + + } + else + { + qWarning("Task not found."); + return NULL; + } +} + +PyObject* py_get_task_info(PyObject *, PyObject *args) +{ + long widget, task; + if (!PyArg_ParseTuple(args, (char*)"ll:getTaskInfo", &widget, &task)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return getTaskInfo(widget, task); +} + +// This returns all the info about a certain startup +// Return type is a Python List +PyObject* getStartupInfo(long widget, long cstartup) +{ + karamba* currTheme = (karamba*)widget; + Startup* currentStartup = (Startup*) cstartup; + Startup* startup; + + StartupList startupList = currTheme -> taskManager.startups(); + + for (startup = startupList.first(); startup; startup = startupList.next()) + { + if ((long)startup == (long)cstartup) + { + break; + } + } + + startup = currentStartup; + + if (startup != 0) + { + PyObject* pList = PyList_New(0); + + //Startup Name + if (startup -> text() != NULL) + { + PyList_Append(pList, PyString_FromString(startup -> text().latin1())); + } + else + { + PyList_Append(pList, PyString_FromString("")); + } + + //Icon Name + if (startup -> icon() != NULL) + { + PyList_Append(pList, PyString_FromString(startup -> icon().latin1())); + } + else + { + PyList_Append(pList, PyString_FromString("")); + } + + //Executable Name + if (startup -> bin() != NULL) + { + PyList_Append(pList, PyString_FromString(startup -> bin().latin1())); + } + else + { + PyList_Append(pList, PyString_FromString("")); + } + + // a reference back to itself + PyList_Append(pList, PyInt_FromLong((long) startup)); + + return pList; + + } + else + { + return NULL; + } +} + +PyObject* py_get_startup_info(PyObject*, PyObject* args) +{ + long widget, startup; + if (!PyArg_ParseTuple(args, (char*)"ll:getStartupInfo", &widget, &startup)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return getStartupInfo(widget, startup); +} + +// This gets a system task list +// It returns a String List of task names +PyObject* getTaskNames(long widget) +{ + karamba* currTheme = (karamba*)widget; + PyObject* pList = PyList_New(0); + PyObject* pString; + + TaskList taskList = currTheme -> taskManager.tasks(); + + Task* task; + for (task = taskList.first(); task; task = taskList.next()) + { + const char* tmp = task->name().latin1(); + if(tmp == 0) + continue; + pString = PyString_FromString(tmp); + if(pString) + PyList_Append(pList, pString); + } + return pList; +} + +PyObject* py_get_task_names(PyObject *, PyObject *args) +{ + long widget; + if(!PyArg_ParseTuple(args, (char*)"l:getTaskNames", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return getTaskNames(widget); +} + +// This gets a system task list +PyObject* getTaskList(long widget) +{ + karamba* currTheme = (karamba*)widget; + PyObject* pList = PyList_New(0); + PyObject* pString; + + TaskList taskList = currTheme -> taskManager.tasks(); + + Task* task; + for (task = taskList.first(); task; task = taskList.next()) + { + pString = PyInt_FromLong((long)task); + PyList_Append(pList, pString); + } + return pList; +} + +PyObject* py_get_task_list(PyObject *, PyObject *args) +{ + long widget; + if(!PyArg_ParseTuple(args, (char*)"l:getTaskList", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return getTaskList(widget); +} + +// This gets a system startup list +PyObject* getStartupList(long widget) +{ + karamba* currTheme = (karamba*)widget; + PyObject* pList = PyList_New(0); + PyObject* pString; + + StartupList startupList = currTheme -> taskManager.startups(); + + Startup* startup; + + for (startup = startupList.first(); startup; startup = startupList.next()) + { + pString = PyInt_FromLong((long) startup); + PyList_Append(pList, pString); + } + return pList; +} + +PyObject* py_get_startup_list(PyObject *, PyObject *args) +{ + long widget; + if(!PyArg_ParseTuple(args, (char*)"l:getStartupList", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return getStartupList(widget); +} diff --git a/superkaramba/src/task_python.h b/superkaramba/src/task_python.h new file mode 100644 index 0000000..ab4365e --- /dev/null +++ b/superkaramba/src/task_python.h @@ -0,0 +1,153 @@ +/**************************************************************************** +* task_python.h - Functions for task python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef TASK_PYTHON_H +#define TASK_PYTHON_H + +/** Task/performTaskAction +* +* SYNOPSIS +* long performTaskAction(widget, task, action) +* DESCRIPTION +* This peforms the given action on a task object. widget is a reference to +* the current widget. task is a reference to a task object you got from +* getTaskList(). Action is a number from 1 to 10. See the list below. +* +* Possible actions: +* * 1 = Maximize the window +* * 2 = Restore the window (use on iconified windows) +* * 3 = Iconify the window (minimize it) +* * 4 = Close the window +* * 5 = Activate (give focus to) the window +* * 6 = Raise the window +* * 7 = Lower the window +* * 8 = Smart Focus/Minimize - This will what the KDE taskbar does when you +* click on a window. If it is iconified, raise it. If it has focus, +* iconify it. +* * 9 = Toggle whether this window is always on top +* * 10 = Toggle wheter this window is shaded (rolled up) +* ARGUMENTS +* * long widget -- karamba +* * long task -- pointer to task +* * long action -- action number +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_perform_task_action(PyObject *self, PyObject *args); + +/** Task/getTaskInfo +* +* SYNOPSIS +* list getTaskInfo(widget, task) +* DESCRIPTION +* This returns all of the info about a certain task in the form of a Python +* List. widget is a reference to the current widget. task is a reference to +* the window you want info about which you obtain by calling getTaskList(). +* ARGUMENTS +* * long widget -- karamba +* * long task -- pointer to task +* RETURN VALUE +* Here is the format of the returned list by index value: +* * 0 = Task name (The full name of the window) +* * 1 = Icon name +* * 2 = Class name - This is for grouping tasks. All tasks with the same +* name can be grouped together because they are instances of the same +* program. +* * 3 = Desktop number - The desktop number this window is on +* * 4 = Is this window maximized? 0=no, 1=yes +* * 5 = Is this window iconified (minimized)? 0=no, 1=yes +* * 6 = Is this window shaded (rolled up)? 0=no, 1=yes +* * 7 = Is this window focused? 0=no, 1=yes +* * 8 = A reference back to the task you got info on +*/ +PyObject* py_get_task_info(PyObject *self, PyObject *args); + +/** Task/getStartupInfo +* +* SYNOPSIS +* list getStartupInfo(widget, task) +* DESCRIPTION +* This returns all of the info about a certain starting task in the form of +* a Python List. widget is a reference to the current widget. task is a +* reference to the window you want info about which you obtain by calling +* getStartupList(). +* ARGUMENTS +* * long widget -- karamba +* * long task -- pointer to task +* RETURN VALUE +* Here is the format of the returned list by index value: +* * 0 = Task name (The full name of the window) +* * 1 = Icon name +* * 2 = Executable name +* * 3 = A reference back to the task you got info on +*/ +PyObject* py_get_startup_info(PyObject* self, PyObject* args); + +/** Task/getTaskNames +* +* SYNOPSIS +* list getTaskNames(widget) +* DESCRIPTION +* This returns a Python List containing the String names of all open +* windows on the system. This is for convience if you want to list open +* windows or see if a window by a certain name exists. Anything else +* requires the reference to the window you would obtain from getTaskList() +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* Task list +*/ +PyObject* py_get_task_names(PyObject *self, PyObject *args); + +/** Task/getTaskList +* +* SYNOPSIS +* list getTaskList(widget) +* DESCRIPTION +* This returns a Python List object with references to all the current +* windows open on this system. You can then call performTaskAction() or +* getTaskInfo() on any of the entries in the list. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* Task list +*/ +PyObject* py_get_task_list(PyObject *self, PyObject *args); + +/** Task/getStartupList +* +* SYNOPSIS +* list getTaskList(widget) +* DESCRIPTION +* This returns a Python List object with references to all the current +* windows that are in the process of loading on this system. You can then +* call getStartupInfo() on any of the entries in the list. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* startup list +*/ +PyObject* py_get_startup_list(PyObject *self, PyObject *args); + +#endif // TASK_PYTHON_H diff --git a/superkaramba/src/taskbartest.cpp b/superkaramba/src/taskbartest.cpp new file mode 100644 index 0000000..3ad6922 --- /dev/null +++ b/superkaramba/src/taskbartest.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2003 Hans Karlsson + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "taskbartest.h" + +static const char *description = + I18N_NOOP("A KDE Eye-candy Application"); + +static const char *version = "0.17"; + +static KCmdLineOptions options[] = + { + // { "+[URL]", I18N_NOOP( "Document to open" ), 0 }, + { "+file", I18N_NOOP("A required argument 'file'"), 0 }, + { 0, 0, 0 } + + }; + + +int main(int argc, char **argv) +{ + KAboutData about("karamba", I18N_NOOP("karamba"), version, description, + KAboutData::License_GPL, "(C) 2003 Hans Karlsson", 0, 0, "karlsson.h@home.se"); + about.addAuthor( "Hans Karlsson", 0, "karlsson.h@home.se" ); + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions( options ); + + KApplication app; +// karamba *mainWin = 0; + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + +// //KSGRD::SensorManager *f32 = new KSGRD::SensorManager(); +// //f32->engage("localhost"); +// // KSGRD::SensorMgr foo ;// p->engage( "" ); + + +// //KConfig *kconfig = KGlobal::config(); +// //kconfig->setGroup("karamba"); +// //kconfig->writeEntry("test", "/home/hk/foofoo"); +// //kconfig->sync(); + + +// bool OK = false; + +// // initialize Python +// Py_Initialize(); + +// // initialize thread support +// PyEval_InitThreads(); + +// mainThreadState = NULL; + +// // save a pointer to the main PyThreadState object +// mainThreadState = PyThreadState_Get(); + +// // release the lock +// PyEval_ReleaseLock(); + + +// if(args->count() > 0) +// { +// for (int i = 0; i < (args->count()); i++) +// { +// if( args->arg(i) != "" ) +// { +// QFileInfo file( args->arg(i) ); +// //qDebug( file.dirPath(true) ); +// if( file.exists() && !file.isDir() ) +// { +// //qDebug( "File exists" ); +// mainWin = new karamba( ( args->arg(i) )); +// mainWin->show(); +// OK = true; +// } +// } +// } + +// //app.setMainWidget( mainWin ); +// int ret = 0; +// if( OK ) +// ret = app.exec(); + +// // shut down the interpreter +// PyInterpreterState * mainInterpreterState = mainThreadState->interp; +// // create a thread state object for this thread +// PyThreadState * myThreadState = PyThreadState_New(mainInterpreterState); +// PyThreadState_Swap(myThreadState); + +// PyEval_AcquireLock(); +// Py_Finalize(); + +// return ret; +// } +// else +// { +// QStringList fileNames; +// fileNames = KFileDialog::getOpenFileNames(QString::null, "*.theme", 0, "Open configurations"); +// for ( QStringList::Iterator it = fileNames.begin(); it != fileNames.end(); ++it ) +// { +// QFileInfo file( *it ); +// if( file.exists() && !file.isDir() ) +// { +// mainWin = new karamba( *it ); +// mainWin->show(); +// OK = true; +// } +// } +// int ret = 0; +// if( OK ) +// ret = app.exec(); + +// // shut down the interpreter +// PyInterpreterState * mainInterpreterState = mainThreadState->interp; +// // create a thread state object for this thread +// PyThreadState * myThreadState = PyThreadState_New(mainInterpreterState); +// PyThreadState_Swap(myThreadState); +// PyEval_AcquireLock(); +// Py_Finalize(); +// return ret; +// } + +// args->clear(); + +// // shut down the interpreter + +// PyInterpreterState * mainInterpreterState = mainThreadState->interp; +// // create a thread state object for this thread +// PyThreadState * myThreadState = PyThreadState_New(mainInterpreterState); +// PyThreadState_Swap(myThreadState); +// PyEval_AcquireLock(); +// Py_Finalize(); + + + TaskManager t; + + printf("%d %d", t.numberOfDesktops(), t.currentDesktop()); + + TaskList list = t.tasks(); + + Task *task; + for ( task = list.first(); task; task = list.next() ) { + cout << task->name().latin1() << endl; + task->restore(); + } + cout << endl; + + return 0; + + + +} diff --git a/superkaramba/src/taskbartest.h b/superkaramba/src/taskbartest.h new file mode 100644 index 0000000..6050569 --- /dev/null +++ b/superkaramba/src/taskbartest.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2003 Hans Karlsson + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#include "taskmanager.h" diff --git a/superkaramba/src/taskmanager.cpp b/superkaramba/src/taskmanager.cpp new file mode 100644 index 0000000..c1f2568 --- /dev/null +++ b/superkaramba/src/taskmanager.cpp @@ -0,0 +1,829 @@ +/***************************************************************** + +Copyright (c) 2000 Matthias Elter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "taskmanager.h" +#include "taskmanager.moc" + +template class QPtrList; + +// Hack: create a global KWinModule without a parent. We +// can't make it a child of TaskManager because more than one +// TaskManager might be created. We can't make it a class +// variable without changing Task, which also uses it. +// So, we'll leak a little memory, but it's better than crashing. +// The real problem is that KWinModule should be a singleton. +KWinModule* kwin_module = 0; + +TaskManager::TaskManager(QObject *parent, const char *name) + : QObject(parent, name), _active(0), _startup_info( NULL ) +{ + + kwin_module = new KWinModule(); + +// KGlobal::locale()->insertCatalogue("libtaskmanager"); + connect(kwin_module, SIGNAL(windowAdded(WId)), SLOT(windowAdded(WId))); + connect(kwin_module, SIGNAL(windowRemoved(WId)), SLOT(windowRemoved(WId))); + connect(kwin_module, SIGNAL(activeWindowChanged(WId)), SLOT(activeWindowChanged(WId))); + connect(kwin_module, SIGNAL(currentDesktopChanged(int)), SLOT(currentDesktopChanged(int))); + connect(kwin_module, SIGNAL(windowChanged(WId,unsigned int)), SLOT(windowChanged(WId,unsigned int))); + + // register existing windows + const QValueList windows = kwin_module->windows(); + QValueList::ConstIterator end( windows.end() ); + for (QValueList::ConstIterator it = windows.begin(); it != end; ++it ) + windowAdded(*it); + + // set active window + WId win = kwin_module->activeWindow(); + activeWindowChanged(win); + + configure_startup(); +} + +TaskManager::~TaskManager() +{ +} + +void TaskManager::configure_startup() +{ + KConfig c("klaunchrc", true); + c.setGroup("FeedbackStyle"); + if (!c.readBoolEntry("TaskbarButton", true)) + return; + _startup_info = new KStartupInfo( true, this ); + connect( _startup_info, + SIGNAL( gotNewStartup( const KStartupInfoId&, const KStartupInfoData& )), + SLOT( gotNewStartup( const KStartupInfoId&, const KStartupInfoData& ))); + connect( _startup_info, + SIGNAL( gotStartupChange( const KStartupInfoId&, const KStartupInfoData& )), + SLOT( gotStartupChange( const KStartupInfoId&, const KStartupInfoData& ))); + connect( _startup_info, + SIGNAL( gotRemoveStartup( const KStartupInfoId&, const KStartupInfoData& )), + SLOT( gotRemoveStartup( const KStartupInfoId& ))); + c.setGroup( "TaskbarButtonSettings" ); + _startup_info->setTimeout( c.readUnsignedNumEntry( "Timeout", 30 )); +} + +Task* TaskManager::findTask(WId w) +{ + for (Task* t = _tasks.first(); t != 0; t = _tasks.next()) + if (t->window() == w || t->hasTransient(w)) + return t; + return 0; +} + +#ifdef KDE_3_3 +#define NET_ALL_TYPES_MASK (NET::AllTypesMask) +#else +#define NET_ALL_TYPES_MASK (-1LU) +#endif + +void TaskManager::windowAdded(WId w ) +{ + NETWinInfo info(qt_xdisplay(), w, qt_xrootwin(), + NET::WMWindowType | NET::WMPid | NET::WMState ); + #ifdef KDE_3_2 + NET::WindowType windowType = info.windowType(NET_ALL_TYPES_MASK); + #else + NET::WindowType windowType = info.windowType(); + #endif + // ignore NET::Tool and other special window types + if (windowType != NET::Normal && windowType != NET::Override + && windowType != NET::Unknown && windowType != NET::Dialog) + return; + // ignore windows that want to be ignored by the taskbar + if ((info.state() & NET::SkipTaskbar) != 0) + { + _skiptaskbar_windows.push_front( w ); // remember them though + return; + } + + Window transient_for_tmp; + if (XGetTransientForHint(qt_xdisplay(), (Window) w, &transient_for_tmp)) + { + WId transient_for = (WId) transient_for_tmp; + + // check if it's transient for a skiptaskbar window + if (_skiptaskbar_windows.contains(transient_for)) + return; + + // lets see if this is a transient for an existing task + if (transient_for != qt_xrootwin() && transient_for != 0 ) + { + Task* t = findTask(transient_for); + if (t) + { + if (t->window() != w) + { + t->addTransient(w); + // kdDebug() << "TM: Transient " << w << " added for Task: " << t->window() << endl; + } + return; + } + } + } + Task* t = new Task(w, this); + _tasks.append(t); + + // kdDebug() << "TM: Task added for WId: " << w << endl; + emit taskAdded(t); +} + +void TaskManager::windowRemoved(WId w ) +{ + _skiptaskbar_windows.remove( w ); + // find task + Task* t = findTask(w); + if (!t) return; + + if (t->window() == w) { + _tasks.removeRef(t); + + emit taskRemoved(t); + + if(t == _active) _active = 0; + delete t; + //kdDebug() << "TM: Task for WId " << w << " removed." << endl; + } + else { + t->removeTransient( w ); + //kdDebug() << "TM: Transient " << w << " for Task " << t->window() << " removed." << endl; + } +} + +void TaskManager::windowChanged(WId w, unsigned int dirty) +{ + if( dirty & NET::WMState ) { + NETWinInfo info ( qt_xdisplay(), w, qt_xrootwin(), NET::WMState ); + if ( (info.state() & NET::SkipTaskbar) != 0 ) { + windowRemoved( w ); + _skiptaskbar_windows.push_front( w ); + return; + } + else { + _skiptaskbar_windows.remove( w ); + if( !findTask( w )) + windowAdded( w ); // skipTaskBar state was removed, so add this window + } + } + + // check if any state we are interested in is marked dirty + if(!(dirty & (NET::WMVisibleName|NET::WMName|NET::WMState|NET::WMIcon|NET::XAWMState|NET::WMDesktop)) ) + return; + + // find task + Task* t = findTask( w ); + if (!t) return; + + //kdDebug() << "TaskManager::windowChanged " << w << " " << dirty << endl; + + + // refresh icon pixmap if necessary + if (dirty & NET::WMIcon) + t->refresh(true); + else + t->refresh(); + + if(dirty & (NET::WMDesktop|NET::WMState|NET::XAWMState)) + emit windowChanged(w); // moved to different desktop or is on all or change in iconification/withdrawnnes +} + +void TaskManager::activeWindowChanged(WId w ) +{ + //kdDebug() << "TaskManager::activeWindowChanged" << endl; + + Task* t = findTask( w ); + if (!t) { + if (_active) { + _active->setActive(false); + _active = 0; + + // there is no active window at the moment + emit activeTaskChanged(0); + } + } + else { + if (_active) + _active->setActive(false); + + _active = t; + _active->setActive(true); + + emit activeTaskChanged(_active); + } +} + +void TaskManager::currentDesktopChanged(int desktop) +{ + emit desktopChanged(desktop); +} + +void TaskManager::gotNewStartup( const KStartupInfoId& id, const KStartupInfoData& data ) +{ + Startup* s = new Startup( id, data, this ); + _startups.append(s); + + emit startupAdded(s); +} + +void TaskManager::gotStartupChange( const KStartupInfoId& id, const KStartupInfoData& data ) +{ + for( Startup* s = _startups.first(); s != 0; s = _startups.next()) { + if ( s->id() == id ) { + s->update( data ); + return; + } + } +} + +void TaskManager::gotRemoveStartup( const KStartupInfoId& id ) +{ + killStartup( id ); +} + +void TaskManager::killStartup( const KStartupInfoId& id ) +{ + Startup* s = 0; + for(s = _startups.first(); s != 0; s = _startups.next()) { + if (s->id() == id) + break; + } + if (s == 0) return; + + _startups.removeRef(s); + emit startupRemoved(s); + delete s; +} + +void TaskManager::killStartup(Startup* s) +{ + if (s == 0) return; + + _startups.removeRef(s); + emit startupRemoved(s); + delete s; +} + +QString TaskManager::desktopName(int desk) const +{ + return kwin_module->desktopName(desk); +} + +int TaskManager::numberOfDesktops() const +{ + return kwin_module->numberOfDesktops(); +} + +bool TaskManager::isOnTop(const Task* task) +{ + if(!task) return false; + + for (QValueList::ConstIterator it = kwin_module->stackingOrder().fromLast(); + it != kwin_module->stackingOrder().end(); --it ) { + for (Task* t = _tasks.first(); t != 0; t = _tasks.next() ) { + if ( (*it) == t->window() ) { + if ( t == task ) + return true; + if ( !t->isIconified() && (t->isAlwaysOnTop() == task->isAlwaysOnTop()) ) + return false; + break; + } + } + } + return false; +} + + +Task::Task(WId win, TaskManager * parent, const char *name) : + QObject(parent, name), + _active(false), _win(win), + _lastWidth(0), _lastHeight(0), _lastResize(false), _lastIcon(), + _thumbSize(0.2), _thumb(), _grab() +{ +#ifdef KDE_3_2 + _info = KWin::windowInfo(_win, 0, 0); +#else + _info = KWin::info(_win); +#endif + // try to load icon via net_wm + _pixmap = KWin::icon(_win, 16, 16, true); + + // try to guess the icon from the classhint + if(_pixmap.isNull()) + KGlobal::instance()->iconLoader()->loadIcon(className().lower(), + KIcon::Small,KIcon::Small, + KIcon::DefaultState, 0, true); + + // load xapp icon + if (_pixmap.isNull()) + _pixmap = SmallIcon("kcmx"); +} + +Task::~Task() +{ +} + +void Task::refresh(bool icon) +{ +#ifdef KDE_3_2 + _info = KWin::windowInfo(_win, 0, 0); +#else + _info = KWin::info(_win); +#endif + if (icon) + { + // try to load icon via net_wm + _pixmap = KWin::icon(_win, 16, 16, true); + + // try to guess the icon from the classhint + if(_pixmap.isNull()) + { + KGlobal::instance()->iconLoader()->loadIcon(className().lower(), + KIcon::Small, KIcon::Small, KIcon::DefaultState, 0, true); + } + + // load xapp icon + if (_pixmap.isNull()) + _pixmap = SmallIcon("kcmx"); + + _lastIcon.resize(0,0); + emit iconChanged(); + } + emit changed(); +} + +void Task::setActive(bool a) +{ + _active = a; + emit changed(); + if ( a ) + emit activated(); + else + emit deactivated(); +} + +bool Task::isMaximized() const +{ +#ifdef KDE_3_2 + return(_info.state() & NET::Max); +#else + return(_info.state & NET::Max); +#endif +} + +bool Task::isIconified() const +{ +#ifdef KDE_3_2 + return (_info.mappingState() == NET::Iconic); +#else + return (_info.mappingState == NET::Iconic); +#endif +} + +bool Task::isAlwaysOnTop() const +{ +#ifdef KDE_3_2 + return (_info.state() & NET::StaysOnTop); +#else + return (_info.state & NET::StaysOnTop); +#endif +} + +bool Task::isShaded() const +{ +#ifdef KDE_3_2 + return (_info.state() & NET::Shaded); +#else + return (_info.state & NET::Shaded); +#endif +} + +bool Task::isOnCurrentDesktop() const +{ +#ifdef KDE_3_2 + return (_info.onAllDesktops() || _info.desktop() == kwin_module->currentDesktop()); +#else + return (_info.onAllDesktops || _info.desktop == kwin_module->currentDesktop()); +#endif +} + +bool Task::isOnAllDesktops() const +{ +#ifdef KDE_3_2 + return _info.onAllDesktops(); +#else + return _info.onAllDesktops; +#endif +} + +bool Task::isActive() const +{ + return _active; +} + +bool Task::isOnTop() const +{ + return taskManager()->isOnTop( this ); +} + +bool Task::isModified() const +{ + static QString modStr = QString::fromUtf8("[") + i18n("modified") + QString::fromUtf8("]"); +#ifdef KDE_3_2 + int modStrPos = _info.visibleName().find(modStr); +#else + int modStrPos = _info.visibleName.find(modStr); +#endif + + return ( modStrPos != -1 ); +} + +QString Task::iconName() const +{ + NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMIconName); + return QString::fromUtf8(ni.iconName()); +} +QString Task::visibleIconName() const +{ + NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMVisibleIconName); + return QString::fromUtf8(ni.visibleIconName()); +} + +QString Task::className() +{ + XClassHint hint; + if(XGetClassHint(qt_xdisplay(), _win, &hint)) { + QString nh( hint.res_name ); + XFree( hint.res_name ); + XFree( hint.res_class ); + return nh; + } + return QString::null; +} + +QString Task::classClass() +{ + XClassHint hint; + if(XGetClassHint(qt_xdisplay(), _win, &hint)) { + QString ch( hint.res_class ); + XFree( hint.res_name ); + XFree( hint.res_class ); + return ch; + } + return QString::null; +} + +QPixmap Task::icon( int width, int height, bool allowResize ) +{ + if ( (width == _lastWidth) + && (height == _lastHeight) + && (allowResize == _lastResize ) + && (!_lastIcon.isNull()) ) + return _lastIcon; + + QPixmap newIcon = KWin::icon( _win, width, height, allowResize ); + if ( !newIcon.isNull() ) { + _lastIcon = newIcon; + _lastWidth = width; + _lastHeight = height; + _lastResize = allowResize; + } + + return newIcon; +} + +QPixmap Task::bestIcon( int size, bool &isStaticIcon ) +{ + QPixmap pixmap; + isStaticIcon = false; + + switch( size ) { + case KIcon::SizeSmall: + { + pixmap = icon( 16, 16, true ); + + // Icon of last resort + if( pixmap.isNull() ) { + pixmap = KGlobal::iconLoader()->loadIcon( "go", + KIcon::NoGroup, + KIcon::SizeSmall ); + isStaticIcon = true; + } + } + break; + case KIcon::SizeMedium: + { + // + // Try 34x34 first for KDE 2.1 icons with shadows, if we don't + // get one then try 32x32. + // + pixmap = icon( 34, 34, false ); + + if ( ( pixmap.width() != 34 ) || ( pixmap.height() != 34 ) ) { + if ( ( pixmap.width() != 32 ) || ( pixmap.height() != 32 ) ) { + pixmap = icon( 32, 32, true ); + } + } + + // Icon of last resort + if( pixmap.isNull() ) { + pixmap = KGlobal::iconLoader()->loadIcon( "go", + KIcon::NoGroup, + KIcon::SizeMedium ); + isStaticIcon = true; + } + } + break; + case KIcon::SizeLarge: + { + // If there's a 48x48 icon in the hints then use it + pixmap = icon( size, size, false ); + + // If not, try to get one from the classname + if ( pixmap.isNull() || pixmap.width() != size || pixmap.height() != size ) { + pixmap = KGlobal::iconLoader()->loadIcon( className(), + KIcon::NoGroup, + size, + KIcon::DefaultState, + 0L, + true ); + isStaticIcon = true; + } + + // If we still don't have an icon then scale the one in the hints + if ( pixmap.isNull() || ( pixmap.width() != size ) || ( pixmap.height() != size ) ) { + pixmap = icon( size, size, true ); + isStaticIcon = false; + } + + // Icon of last resort + if( pixmap.isNull() ) { + pixmap = KGlobal::iconLoader()->loadIcon( "go", + KIcon::NoGroup, + size ); + isStaticIcon = true; + } + } + } + + return pixmap; +} + +bool Task::idMatch( const QString& id1, const QString& id2 ) +{ + if ( id1.isEmpty() || id2.isEmpty() ) + return false; + + if ( id1.contains( id2 ) > 0 ) + return true; + + if ( id2.contains( id1 ) > 0 ) + return true; + + return false; +} + + +void Task::maximize() +{ + NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMState); + ni.setState( NET::Max, NET::Max ); + +#ifdef KDE_3_2 + if (_info.mappingState() == NET::Iconic) +#else + if (_info.mappingState == NET::Iconic) +#endif + activate(); +} + +void Task::restore() +{ + NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMState); + ni.setState( 0, NET::Max ); +#ifdef KDE_3_2 + if (_info.mappingState() == NET::Iconic) +#else + if (_info.mappingState == NET::Iconic) +#endif + activate(); +} + +void Task::iconify() +{ + XIconifyWindow( qt_xdisplay(), _win, qt_xscreen() ); +} + +void Task::close() +{ + NETRootInfo ri( qt_xdisplay(), NET::CloseWindow ); + ri.closeWindowRequest( _win ); +} + +void Task::raise() +{ +// kdDebug(1210) << "Task::raise(): " << name() << endl; + XRaiseWindow( qt_xdisplay(), _win ); +} + +void Task::lower() +{ +// kdDebug(1210) << "Task::lower(): " << name() << endl; + XLowerWindow( qt_xdisplay(), _win ); +} + +void Task::activate() +{ +// kdDebug(1210) << "Task::activate():" << name() << endl; + NETRootInfo ri( qt_xdisplay(), 0 ); + ri.setActiveWindow( _win ); +} + +void Task::activateRaiseOrIconify() +{ + if ( !isActive() || isIconified() ) { + activate(); + } else if ( !isOnTop() ) { + raise(); + } else { + iconify(); + } +} + +void Task::toDesktop(int desk) +{ + NETWinInfo ni(qt_xdisplay(), _win, qt_xrootwin(), NET::WMDesktop); + if (desk == 0) + { +#ifdef KDE_3_2 + if (_info.onAllDesktops()) + { + ni.setDesktop(kwin_module->currentDesktop()); + KWin::forceActiveWindow(_win); + } +#else + if (_info.onAllDesktops) + { + ni.setDesktop(kwin_module->currentDesktop()); + KWin::setActiveWindow(_win); + } +#endif + else + ni.setDesktop(NETWinInfo::OnAllDesktops); + return; + } + ni.setDesktop(desk); + if (desk == kwin_module->currentDesktop()) +#ifdef KDE_3_2 + KWin::forceActiveWindow(_win); +#else + KWin::setActiveWindow(_win); +#endif +} + +void Task::toCurrentDesktop() +{ + toDesktop(kwin_module->currentDesktop()); +} + +void Task::setAlwaysOnTop(bool stay) +{ + NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMState); + if(stay) + ni.setState( NET::StaysOnTop, NET::StaysOnTop ); + else + ni.setState( 0, NET::StaysOnTop ); +} + +void Task::toggleAlwaysOnTop() +{ + setAlwaysOnTop( !isAlwaysOnTop() ); +} + +void Task::setShaded(bool shade) +{ + NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMState); + if(shade) + ni.setState( NET::Shaded, NET::Shaded ); + else + ni.setState( 0, NET::Shaded ); +} + +void Task::toggleShaded() +{ + setShaded( !isShaded() ); +} + +void Task::publishIconGeometry(QRect rect) +{ + NETWinInfo ni( qt_xdisplay(), _win, qt_xrootwin(), NET::WMIconGeometry); + NETRect r; + r.pos.x = rect.x(); + r.pos.y = rect.y(); + r.size.width = rect.width(); + r.size.height = rect.height(); + ni.setIconGeometry(r); +} + +void Task::updateThumbnail() +{ + if ( !isOnCurrentDesktop() ) + return; + if ( !isActive() ) + return; + if ( !_grab.isNull() ) // We're already processing one... + return; + + // + // We do this as a two stage process to remove the delay caused + // by the thumbnail generation. This makes things much smoother + // on slower machines. + // + QWidget *rootWin = qApp->desktop(); +#ifdef KDE_3_2 + QRect geom = _info.geometry(); +#else + QRect geom = _info.geometry; +#endif + _grab = QPixmap::grabWindow( rootWin->winId(), + geom.x(), geom.y(), + geom.width(), geom.height() ); + + if ( !_grab.isNull() ) + QTimer::singleShot( 200, this, SLOT( generateThumbnail() ) ); +} + +void Task::generateThumbnail() +{ + if ( _grab.isNull() ) + return; + + QImage img = _grab.convertToImage(); + + double width = img.width(); + double height = img.height(); + width = width * _thumbSize; + height = height * _thumbSize; + + img = img.smoothScale( (int) width, (int) height ); + _thumb = img; + _grab.resize( 0, 0 ); // Makes grab a null image. + + emit thumbnailChanged(); +} + +Startup::Startup( const KStartupInfoId& id, const KStartupInfoData& data, + QObject * parent, const char *name) + : QObject(parent, name), _id( id ), _data( data ) +{ +} + +Startup::~Startup() +{ + +} + +void Startup::update( const KStartupInfoData& data ) +{ + _data.update( data ); + emit changed(); +} + +int TaskManager::currentDesktop() const +{ + return kwin_module->currentDesktop(); +} diff --git a/superkaramba/src/taskmanager.h b/superkaramba/src/taskmanager.h new file mode 100644 index 0000000..86e4a74 --- /dev/null +++ b/superkaramba/src/taskmanager.h @@ -0,0 +1,550 @@ +/***************************************************************** + +Copyright (c) 2000-2001 Matthias Elter +Copyright (c) 2001 Richard Moore + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef __taskmanager_h__ +#define __taskmanager_h__ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include "karambaapp.h" + +class TaskManager; + +/** + * A dynamic interface to a task (main window). + * + * @see TaskManager + * @see KWinModule + */ +class Task: public QObject +{ + Q_OBJECT + Q_PROPERTY( QString name READ name ) + Q_PROPERTY( QString visibleName READ visibleName ) + Q_PROPERTY( QString visibleNameWithState READ visibleNameWithState ) + Q_PROPERTY( QString iconName READ iconName ) + Q_PROPERTY( QString visibleIconName READ visibleIconName ) + Q_PROPERTY( QPixmap pixmap READ pixmap ) + Q_PROPERTY( bool maximized READ isMaximized ) + Q_PROPERTY( bool iconified READ isIconified ) + Q_PROPERTY( bool shaded READ isShaded WRITE setShaded ) + Q_PROPERTY( bool active READ isActive ) + Q_PROPERTY( bool onCurrentDesktop READ isOnCurrentDesktop ) + Q_PROPERTY( bool onAllDesktops READ isOnAllDesktops ) + Q_PROPERTY( bool alwaysOnTop READ isAlwaysOnTop WRITE setAlwaysOnTop ) + Q_PROPERTY( bool modified READ isModified ) + Q_PROPERTY( int desktop READ desktop ) + Q_PROPERTY( double thumbnailSize READ thumbnailSize WRITE setThumbnailSize ) + Q_PROPERTY( bool hasThumbnail READ hasThumbnail ) + Q_PROPERTY( QPixmap thumbnail READ thumbnail ) + +public: + Task( WId win, TaskManager * parent, const char *name = 0 ); + virtual ~Task(); + + TaskManager* taskManager() const { return (TaskManager*) parent(); } + + WId window() const { return _win; } +#ifdef KDE_3_2 + QString name() const { return _info.name(); } + QString visibleName() const { return _info.visibleName(); } + /** + * Returns the desktop on which this task's window resides. + */ + int desktop() const { return _info.desktop(); } +#else + QString name() const { return _info.name; } + QString visibleName() const { return _info.visibleName; } + /** + * Returns the desktop on which this task's window resides. + */ + int desktop() const { return _info.desktop; } +#endif + QString visibleNameWithState() const { return _info.visibleNameWithState(); } + QString iconName() const; + QString visibleIconName() const; + QString className(); + QString classClass(); + + /** + * A list of the window ids of all transient windows (dialogs) associated + * with this task. + */ + QValueList transients() const { return _transients; } + + /** + * Returns a 16x16 (KIcon::Small) icon for the task. This method will + * only fall back to a static icon if there is no icon of any size in + * the WM hints. + */ + QPixmap pixmap() const { return _pixmap; } + + /** + * Returns the best icon for any of the KIcon::StdSizes. If there is no + * icon of the specified size specified in the WM hints, it will try to + * get one using KIconLoader. + * + *
    +     *   bool gotStaticIcon;
    +     *   QPixmap icon = myTask->icon( KIcon::SizeMedium, gotStaticIcon );
    +     * 
    + * + * @param size Any of the constants in KIcon::StdSizes. + * @param isStaticIcon Set to true if KIconLoader was used, false otherwise. + * @see KIcon + */ + QPixmap bestIcon( int size, bool &isStaticIcon ); + + /** + * Tries to find an icon for the task with the specified size. If there + * is no icon that matches then it will either resize the closest available + * icon or return a null pixmap depending on the value of allowResize. + * + * Note that the last icon is cached, so a sequence of calls with the same + * parameters will only query the NET properties if the icon has changed or + * none was found. + */ + QPixmap icon( int width, int height, bool allowResize = false ); + + /** + * Returns true iff the windows with the specified ids should be grouped + * together in the task list. + */ + static bool idMatch(const QString &, const QString &); + + // state + + /** + * Returns true if the task's window is maximized. + */ + bool isMaximized() const; + + /** + * Returns true if the task's window is iconified. + */ + bool isIconified() const; + + /** + * Returns true if the task's window is shaded. + */ + bool isShaded() const; + + /** + * Returns true if the task's window is the active window. + */ + bool isActive() const; + + /** + * Returns true if the task's window is the topmost non-iconified, + * non-always-on-top window. + */ + bool isOnTop() const; + + /** + * Returns true if the task's window is on the current virtual desktop. + */ + bool isOnCurrentDesktop() const; + + /** + * Returns true if the task's window is on all virtual desktops. + */ + bool isOnAllDesktops() const; + + /** + * Returns true if the task's window will remain at the top of the + * stacking order. + */ + bool isAlwaysOnTop() const; + + /** + * Returns true if the document the task is editing has been modified. + * This is currently handled heuristically by looking for the string + * '[i18n_modified]' in the window title where i18n_modified is the + * word 'modified' in the current language. + */ + bool isModified() const ; + + // internal + + //* @internal + void refresh(bool icon = false); + //* @internal + void addTransient( WId w ) { _transients.append( w ); } + //* @internal + void removeTransient( WId w ) { _transients.remove( w ); } + //* @internal + bool hasTransient( WId w ) const { return _transients.contains( w ); } + //* @internal + void setActive(bool a); + + // For thumbnails + + /** + * Returns the current thumbnail size. + */ + double thumbnailSize() const { return _thumbSize; } + + /** + * Sets the size for the window thumbnail. For example a size of + * 0.2 indicates the thumbnail will be 20% of the original window + * size. + */ + void setThumbnailSize( double size ) { _thumbSize = size; } + + /** + * Returns true if this task has a thumbnail. Note that this method + * can only ever return true after a call to updateThumbnail(). + */ + bool hasThumbnail() const { return !_thumb.isNull(); } + + /** + * Returns the thumbnail for this task (or a null image if there is + * none). + */ + const QPixmap &thumbnail() const { return _thumb; } + +public slots: + // actions + + /** + * Maximise the main window of this task. + */ + void maximize(); + + /** + * Restore the main window of the task (if it was iconified). + */ + void restore(); + + /** + * Iconify the task. + */ + void iconify(); + + /** + * Activate the task's window. + */ + void close(); + + /** + * Raise the task's window. + */ + void raise(); + + /** + * Lower the task's window. + */ + void lower(); + + /** + * Activate the task's window. + */ + void activate(); + + /** + * Perform the action that is most appropriate for this task. If it + * is not active, activate it. Else if it is not the top window, raise + * it. Otherwise, iconify it. + */ + void activateRaiseOrIconify(); + + /** + * If true, the task's window will remain at the top of the stacking order. + */ + void setAlwaysOnTop(bool); + void toggleAlwaysOnTop(); + + /** + * If true then the task's window will be shaded. Most window managers + * represent this state by displaying on the window's title bar. + */ + void setShaded(bool); + void toggleShaded(); + + /** + * Moves the task's window to the specified virtual desktop. + */ + void toDesktop(int); + + /** + * Moves the task's window to the current virtual desktop. + */ + void toCurrentDesktop(); + + /** + * This method informs the window manager of the location at which this + * task will be displayed when iconised. It is used, for example by the + * KWin inconify animation. + */ + void publishIconGeometry(QRect); + + /** + * Tells the task to generate a new thumbnail. When the thumbnail is + * ready the thumbnailChanged() signal will be emitted. + */ + void updateThumbnail(); + +signals: + /** + * Indicates that this task has changed in some way. + */ + void changed(); + + /** + * Indicates that the icon for this task has changed. + */ + void iconChanged(); + + /** + * Indicates that this task is now the active task. + */ + void activated(); + + /** + * Indicates that this task is no longer the active task. + */ + void deactivated(); + + /** + * Indicates that the thumbnail for this task has changed. + */ + void thumbnailChanged(); + +protected slots: + //* @internal + void generateThumbnail(); + +private: + bool _active; + WId _win; + QPixmap _pixmap; +#ifdef KDE_3_2 + KWin::WindowInfo _info; +#else + KWin::Info _info; +#endif + QValueList _transients; + + int _lastWidth; + int _lastHeight; + bool _lastResize; + QPixmap _lastIcon; + + double _thumbSize; + QPixmap _thumb; + QPixmap _grab; + + class TaskPrivate *d; +}; + +/** + * Represents a task which is in the process of starting. + * + * @see TaskManager + */ +class Startup: public QObject +{ + Q_OBJECT + Q_PROPERTY( QString text READ text ) + Q_PROPERTY( QString bin READ bin ) + Q_PROPERTY( QString icon READ icon ) + +public: + Startup( const KStartupInfoId& id, const KStartupInfoData& data, QObject * parent, + const char *name = 0); + virtual ~Startup(); + + /** + * The name of the starting task (if known). + */ + QString text() const { return _data.findName(); } + + /** + * The name of the executable of the starting task. + */ + QString bin() const { return _data.bin(); } + + /** + * The name of the icon to be used for the starting task. + */ + QString icon() const { return _data.findIcon(); } + void update( const KStartupInfoData& data ); + const KStartupInfoId& id() const { return _id; } + +signals: + /** + * Indicates that this startup has changed in some way. + */ + void changed(); + +private: + KStartupInfoId _id; + KStartupInfoData _data; + class StartupPrivate *d; +}; + +typedef QPtrList TaskList; +typedef QPtrList StartupList; + + +/** + * A generic API for task managers. This class provides an easy way to + * build NET compliant task managers. It provides support for startup + * notification, virtual desktops and the full range of WM properties. + * + * @see Task + * @see Startup + * @see KWinModule + * @version $Id: taskmanager.h,v 1.2 2004/11/17 10:16:47 kodaaja Exp $ + */ +class TaskManager : public QObject +{ + Q_OBJECT + Q_PROPERTY( int currentDesktop READ currentDesktop ) + Q_PROPERTY( int numberOfDesktops READ numberOfDesktops ) + +public: + TaskManager( QObject *parent = 0, const char *name = 0 ); + virtual ~TaskManager(); + + /** + * Returns a list of all current tasks. Return type changed to + * QPtrList in KDE 3. + */ + TaskList tasks() const { return _tasks; } + + /** + * Returns a list of all current startups. Return type changed to + * QPtrList in KDE 3. + */ + StartupList startups() const { return _startups; } + + /** + * Returns the name of the nth desktop. + */ + QString desktopName(int n) const; + + /** + * Returns the number of virtual desktops. + */ + int numberOfDesktops() const; + + /** + * Returns the number of the current desktop. + */ + int currentDesktop() const; + + /** + * Returns true if the specified task is on top. + */ + bool isOnTop( const Task*); +signals: + /** + * Emitted when the active window changed. + */ + void activeTaskChanged(Task*); + + /** + * Emitted when a new task has started. + */ + void taskAdded(Task*); + + /** + * Emitted when a task has terminated. + */ + void taskRemoved(Task*); + + /** + * Emitted when a new task is expected. + */ + void startupAdded(Startup*); + + /** + * Emitted when a startup item should be removed. This could be because + * the task has started, because it is known to have died, or simply + * as a result of a timeout. + */ + void startupRemoved(Startup*); + + /** + * Emitted when the current desktop changes. + */ + void desktopChanged(int desktop); + + /** + * Emitted when a window changes desktop. + */ + void windowChanged(WId); + +protected slots: + //* @internal + void windowAdded(WId); + //* @internal + void windowRemoved(WId); + //* @internal + void windowChanged(WId, unsigned int); + + //* @internal + void activeWindowChanged(WId); + //* @internal + void currentDesktopChanged(int); + //* @internal + void killStartup( const KStartupInfoId& ); + //* @internal + void killStartup(Startup*); + + //* @internal + void gotNewStartup( const KStartupInfoId&, const KStartupInfoData& ); + //* @internal + void gotStartupChange( const KStartupInfoId&, const KStartupInfoData& ); + //* @internal + void gotRemoveStartup( const KStartupInfoId& ); + +protected: + /** + * Returns the task for a given WId, or 0 if there is no such task. + */ + Task* findTask(WId w); + void configure_startup(); + +private: + Task* _active; + TaskList _tasks; + QValueList< WId > _skiptaskbar_windows; + StartupList _startups; + KStartupInfo* _startup_info; + + class TaskManagerPrivate *d; +}; + +#endif diff --git a/superkaramba/src/textfield.cpp b/superkaramba/src/textfield.cpp new file mode 100644 index 0000000..6578466 --- /dev/null +++ b/superkaramba/src/textfield.cpp @@ -0,0 +1,159 @@ +/*************************************************************************** + * Copyright (C) 2003 by Ralph M. Churchill * + * mrchucho@yahoo.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "textfield.h" +#include +#include + +TextField::TextField( ) +{ + setFontSize(12); + setColor(QColor(192, 192, 192)); + setBGColor(QColor(0, 0, 0)); + setFont("Helvetica"); + setAlignment(Qt::AlignLeft); + setFixedPitch(false); + setShadow(0); +} + +TextField::~TextField() +{ +} + +TextField::TextField( const TextField& def ) +{ + setFontSize( def.getFontSize() ); + + setColor(def.getColor()); + setBGColor(def.getBGColor()); + + setFont( def.getFont() ); + setAlignment( def.getAlignment() ); + setFixedPitch( def.getFixedPitch() ); + setShadow( def.getShadow() ); +} + +TextField& TextField::operator=(const TextField& rhs) +{ + if( this == &rhs) + return *this; + + setFontSize( rhs.getFontSize() ); + + setColor(rhs.getColor()); + setBGColor(rhs.getBGColor()); + + setFont( rhs.getFont() ); + setAlignment( rhs.getAlignment() ); + setFixedPitch( rhs.getFixedPitch() ); + setShadow( rhs.getShadow() ); + + return *this; +} + +void TextField::setColor(QColor clr) +{ + color = clr; +} + +QColor TextField::getColor() const +{ + return color; +} + +void TextField::setBGColor(QColor clr) +{ + bgColor = clr; +} + +QColor TextField::getBGColor() const +{ + return bgColor; +} + + +void TextField::setFont(const QString &f) +{ + font.setFamily(f); + lineHeight = QFontMetrics(font).height(); +} + + +QString TextField::getFont() const +{ + return font.family(); +} + +void TextField::setFontSize(int size) +{ + font.setPointSize(size); + lineHeight = QFontMetrics(font).height(); +} + +int TextField::getFontSize() const +{ + return font.pointSize(); +} + +void TextField::setAlignment( const QString &align ) +{ + QString a = align.upper(); + if( a == "LEFT" || a.isEmpty() ) + alignment = Qt::AlignLeft; + if( a == "RIGHT" ) + alignment = Qt::AlignRight; + if( a == "CENTER" ) + alignment = Qt::AlignHCenter; +} + +void TextField::setAlignment( int af ) +{ + alignment = af; +} + +int TextField::getAlignment() const +{ + return alignment; +} + +QString TextField::getAlignmentAsString() const +{ + if( alignment == Qt::AlignHCenter ) + return "CENTER"; + else if( alignment == Qt::AlignRight ) + return "RIGHT"; + else + return "LEFT"; +} + +void TextField::setFixedPitch( bool fp) +{ + font.setFixedPitch( fp ); +} + +bool TextField::getFixedPitch() const +{ + return font.fixedPitch(); +} + +void TextField::setShadow ( int s ) +{ + shadow = s; +} + +int TextField::getShadow() const +{ + return shadow; +} + +int TextField::getLineHeight() const +{ + return lineHeight; +} diff --git a/superkaramba/src/textfield.h b/superkaramba/src/textfield.h new file mode 100644 index 0000000..b24fff3 --- /dev/null +++ b/superkaramba/src/textfield.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2003 by Ralph M. Churchill * + * mrchucho@yahoo.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef TEXTFIELD_H +#define TEXTFIELD_H +#include +#include +#include + +/** + * + * Ralph M. Churchill + **/ +class TextField +{ +public: + TextField(); + TextField( const TextField& ); + ~TextField(); + + TextField& operator=(const TextField& ); + + void setFontSize( int ); + void setColor(QColor clr); + void setBGColor(QColor clr); + void setFont( const QString& ); + void setAlignment( int ); + void setAlignment( const QString& ); + void setFixedPitch( bool ); + void setShadow( int ); + + int getFontSize() const; + QColor getColor() const; + QColor getBGColor() const; + QString getFont() const; + int getAlignment() const; + QString getAlignmentAsString() const; + bool getFixedPitch() const; + int getShadow() const; + int getLineHeight() const; + +protected: + int alignment; + QFont font; + QColor color; + QColor bgColor; + int shadow; + int lineHeight; + +} +; +#endif // TEXTFIELD_H diff --git a/superkaramba/src/textfilesensor.cpp b/superkaramba/src/textfilesensor.cpp new file mode 100644 index 0000000..cad696f --- /dev/null +++ b/superkaramba/src/textfilesensor.cpp @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "textfilesensor.h" +#include "qdom.h" + +TextFileSensor::TextFileSensor( const QString &fn, bool iRdf, int interval, const QString &encoding ) + : Sensor( interval ) +{ + fileName = fn; + rdf = iRdf; + + if( !encoding.isEmpty() ) + { + codec = QTextCodec::codecForName( encoding.ascii() ); + if ( codec == 0) + codec = QTextCodec::codecForLocale(); + } + else + codec = QTextCodec::codecForLocale(); +} + +TextFileSensor::~TextFileSensor() +{} + +void TextFileSensor::update() +{ + QValueVector lines; + QFile file(fileName); + QString line; + if ( file.open(IO_ReadOnly | IO_Translate) ) + { + if (rdf) + { + QDomDocument doc; + if ( !doc.setContent( &file ) ) + { + file.close(); + return; + } + QDomElement docElem = doc.documentElement(); + QDomNode n = docElem.firstChild(); + if (!n.isNull()) + { + QDomNodeList titles = docElem.elementsByTagName( "title" ); + QDomNodeList links = docElem.elementsByTagName( "link" ); + + uint i; + for ( i = 0; i < titles.count(); ++i ) + { + QDomElement element = titles.item( i ).toElement(); + lines.push_back(element.text()); + + element = links.item( i ).toElement(); + lines.push_back(element.text()); + } + } + } + else + { + QTextStream t( &file ); // use a text stream + while( (line = t.readLine()) !=0 ) + { + lines.push_back(line); + } + } + file.close(); + } + + int lineNbr; + SensorParams *sp; + Meter *meter; + + int count = (int) lines.size(); + QObjectListIt it( *objList ); + while (it != 0) + { + sp = (SensorParams*)(*it); + meter = sp->getMeter(); + lineNbr = (sp->getParam("LINE")).toInt(); + if ( lineNbr >= 1 && lineNbr <= (int) count ) + { + meter->setValue(lines[lineNbr-1]); + } + if ( -lineNbr >= 1 && -lineNbr <= (int) count ) + { + meter->setValue(lines[count+lineNbr]); + } + + if ( lineNbr == 0 ) + { + QString text; + for( int i=0; i < count; i++ ) + { + text += lines[i] + "\n"; + } + meter->setValue( text ); + } + ++it; + } +} + +#include "textfilesensor.moc" diff --git a/superkaramba/src/textfilesensor.h b/superkaramba/src/textfilesensor.h new file mode 100644 index 0000000..1d5951b --- /dev/null +++ b/superkaramba/src/textfilesensor.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2003 Hans Karlsson + * Copyright (C) 2003-2004 Adam Geitgey + * Copyright (c) 2005 Ryan Nickell + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#ifndef TEXTFILESENSOR_H +#define TEXTFILESENSOR_H + + +#include +#include +#include +#include +#include +#include +/** + * + * Hans Karlsson + **/ +class TextFileSensor : public Sensor +{ + +Q_OBJECT +public: + TextFileSensor( const QString &fileName, bool rdf, int interval, const QString &encoding=QString::null ); + + ~TextFileSensor(); + + void update(); + +private: +QTextCodec *codec; +QString fileName; +bool rdf; +}; + +#endif // TEXTFILESENSOR_H diff --git a/superkaramba/src/textlabel.cpp b/superkaramba/src/textlabel.cpp new file mode 100644 index 0000000..69fb841 --- /dev/null +++ b/superkaramba/src/textlabel.cpp @@ -0,0 +1,379 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include +#include +#include "textlabel.h" + +TextLabel::TextLabel(karamba *k, int x,int y,int w,int h): + Meter(k, x,y,w,h), alignment(Qt::AlignLeft), clip(0), bgColor(0, 0, 0), + lineHeight(0), shadow(0), scrollSpeed(0, 0), scrollPos(0, 0), scrollGap(0), + scrollPause(0), pauseCounter(0), scrollType(ScrollNone) +{ + calculateTextSize(); + if( h != 0 || w != 0) + clip = 0; + else + clip = Qt::DontClip; + + if( h == 0 || w == 0) + { + setWidth(-1); + setHeight(-1); + } +} + +TextLabel::TextLabel(karamba *k): + Meter(k, 0, 0, 0, 0), alignment(Qt::AlignLeft), clip(0), bgColor(0, 0, 0), + lineHeight(0), shadow(0), scrollSpeed(0, 0), scrollPos(0, 0), scrollGap(0), + scrollPause(0), pauseCounter(0), scrollType(ScrollNone) +{ +} + +TextLabel::~TextLabel() +{ +} + +void TextLabel::show() +{ + Meter::show(); + setEnabled(true); +} + +void TextLabel::hide() +{ + Meter::hide(); + setEnabled(false); +} + +void TextLabel::setTextProps( TextField* t ) +{ + if(t) + { + text = *t; + //lineHeight = t->getLineHeight(); + shadow = t->getShadow(); + alignment = t->getAlignment(); + setFontSize(t->getFontSize()); + setFont(t->getFont()); + + setColor(t->getColor()); + setBGColor(t->getBGColor()); + } + calculateTextSize(); +} + +void TextLabel::calculateTextSize() +{ + int tmp; + QFontMetrics fm(font); + lineHeight = fm.height(); + textSize.setWidth(0); + textSize.setHeight(lineHeight * value.count()); + QStringList::Iterator it = value.begin(); + while(it != value.end()) + { + tmp = fm.width(*it); + if(tmp > textSize.width()) + textSize.setWidth(tmp); + ++it; + } +} + +void TextLabel::setValue( QString text) +{ + value = QStringList::split('\n',text); + calculateTextSize(); +} + +void TextLabel::setValue( long v) +{ + value = QStringList( QString::number( v ) ); + calculateTextSize(); +} + +void TextLabel::setBGColor(QColor clr) +{ + bgColor = clr; +} + +QColor TextLabel::getBGColor() const +{ + return bgColor; +} + +void TextLabel::setFont(QString f) +{ + font.setFamily(f); + calculateTextSize(); +} + +QString TextLabel::getFont() const +{ + return font.family(); +} + +void TextLabel::setFontSize(int size) +{ + font.setPixelSize(size); + calculateTextSize(); +} + +int TextLabel::getFontSize() const +{ + return font.pixelSize(); +} + +void TextLabel::setAlignment( QString align ) +{ + QString a = align.upper(); + if( a == "LEFT" || a.isEmpty() ) + alignment = Qt::AlignLeft; + if( a == "RIGHT" ) + alignment = Qt::AlignRight; + if( a == "CENTER" ) + alignment = Qt::AlignHCenter; +} + +QString TextLabel::getAlignment() const +{ + if( alignment == Qt::AlignHCenter ) + return "CENTER"; + else if( alignment == Qt::AlignRight ) + return "RIGHT"; + else + return "LEFT"; +} + +void TextLabel::setFixedPitch( bool fp) +{ + font.setFixedPitch( fp ); +} + +bool TextLabel::getFixedPitch() const +{ + return font.fixedPitch(); +} + +void TextLabel::setShadow ( int s ) +{ + shadow = s; +} + +int TextLabel::getShadow() const +{ + return shadow; +} + +void TextLabel::setScroll(char* type, QPoint speed, int gap, int pause) +{ + ScrollType t = TextLabel::ScrollNone; + QString a = type; + a = a.upper(); + if(a == "NONE") + t = TextLabel::ScrollNone; + else if( a == "NORMAL" ) + t = TextLabel::ScrollNormal; + else if( a == "BACKANDFORTH" ) + t = TextLabel::ScrollBackAndForth; + else if( a == "ONEPASS" ) + t = TextLabel::ScrollOnePass; + setScroll(t, speed, gap, pause); +} + +void TextLabel::setScroll(ScrollType type, QPoint speed, int gap, int pause) +{ + scrollType = type; + scrollSpeed = speed; + switch(scrollType) + { + case ScrollNormal: + case ScrollOnePass: + { + int x = 0, y = 0; + + if(speed.x() > 0) + x = -1 * textSize.width(); + else if(speed.x() < 0) + x = getWidth()-1; + if(speed.y() > 0) + x = -1 * textSize.height(); + else if(speed.y() < 0) + x = getHeight()-1; + scrollPos = QPoint(x,y); + break; + } + case ScrollNone: + case ScrollBackAndForth: + default: + scrollPos = QPoint(0,0); + break; + } + scrollGap = gap; + scrollPause = pause; + pauseCounter = 1; +} + +int TextLabel::drawText(QPainter *p, int x, int y, int width, int height, + QString text) +{ + if( shadow != 0) + { + p->setPen(getBGColor()); + p->drawText(x + shadow, y + shadow, width, height, + alignment | clip | Qt::ExpandTabs, text); + } + p->setPen(getColor()); + p->drawText(x, y, width, height, alignment | clip | Qt::ExpandTabs, text); + return 0; +} + +bool TextLabel::calculateScrollCoords(QRect meterRect, QRect &textRect, + QPoint &next, int &x, int &y) +{ + if(scrollType == ScrollBackAndForth && + (scrollSpeed.x() != 0 && textSize.width() < getWidth() || + scrollSpeed.y() != 0 && textSize.height() < getHeight())) + return true; + + x += scrollPos.x(); + y += scrollPos.y(); + + if(pauseCounter < 1) + { + scrollPos += scrollSpeed; + + // -1 | 0 | 1 + QPoint direction(scrollSpeed.x()/abs((scrollSpeed.x() == 0)? + 1:scrollSpeed.x()), + scrollSpeed.y()/abs((scrollSpeed.y() == 0)? + 1:scrollSpeed.y())); + next = QPoint(-1 * direction.x() * (scrollGap + textSize.width()), + -1 * direction.y() * (scrollGap + textSize.height())); + textRect.setCoords(x, y, x + textSize.width(), y + textSize.height()); + + if(scrollType == ScrollBackAndForth) + { + if(direction.x() < 0 && textRect.right() <= meterRect.right() || + direction.x() > 0 && textRect.left() >= meterRect.left()) + { + scrollSpeed.setX(scrollSpeed.x() * -1); + pauseCounter = scrollPause; + } + if(direction.y() < 0 && textRect.bottom() <= meterRect.bottom() || + direction.y() > 0 && textRect.top() >= meterRect.top()) + { + scrollSpeed.setY(scrollSpeed.y() * -1); + pauseCounter = scrollPause; + } + } + else if(!textRect.intersects(meterRect)) + { + if(scrollType == ScrollNormal) + scrollPos += next; + else if(scrollType == ScrollOnePass) + return false; + } + } + else + --pauseCounter; + return true; +} + +void TextLabel::mUpdate(QPainter *p) +{ + if (hidden != 1) + { + int i = 0; //lineHeight; + int row = 1; + int x = getX(); + int y = getY(); + int width = getWidth(); + int height = getHeight(); + QRect meterRect(x, y, width, height); + QRect textRect; + QPoint next; + + p->setFont(font); + if(scrollType != ScrollNone) + { + p->setClipRect(x, y, width, height); + if(!calculateScrollCoords(meterRect, textRect, next, x, y)) + { + p->setClipping(false); + return; + } + width = textSize.width(); + height = textSize.height(); + } + QStringList::Iterator it = value.begin(); + while(it != value.end() && (row <= height || height == -1 )) + { + drawText(p, x, y + i, width, height, *it); + + // Draw more instances of text if scroll type is normal scroll + if(scrollType == ScrollNormal) + { + textRect.addCoords(next.x(), next.y(), next.x(), next.y()); + while(textRect.intersects(meterRect)) + { + drawText(p, textRect.x(), textRect.y() + i, width, height, *it); + textRect.addCoords(next.x(), next.y(), next.x(), next.y()); + } + } + i += lineHeight; + it++; + row++; + } + if(scrollType != ScrollNone) + p->setClipping(false); + } +} + +bool TextLabel::click(QMouseEvent* e) +{ + if (getBoundingBox().contains(e -> x(), e -> y()) && isEnabled()) + { + QString program; + if (e -> button() == Qt::LeftButton) + { + program = leftButtonAction; + } + else if (e -> button() == Qt::MidButton) + { + program = middleButtonAction; + } + else if (e -> button() == Qt::RightButton) + { + program = rightButtonAction; + } + + if( !program.isEmpty() ) + { + KRun::runCommand(program); + } + else + { + return true; + } + } + return false; +} + +void TextLabel::attachClickArea(QString leftMouseButton, + QString middleMouseButton, + QString rightMouseButton) +{ + leftButtonAction = leftMouseButton; + middleButtonAction = middleMouseButton; + rightButtonAction = rightMouseButton; +} + +#include "textlabel.moc" diff --git a/superkaramba/src/textlabel.h b/superkaramba/src/textlabel.h new file mode 100644 index 0000000..e8fc9e4 --- /dev/null +++ b/superkaramba/src/textlabel.h @@ -0,0 +1,87 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef TEXTLABEL_H +#define TEXTLABEL_H +#include "meter.h" +#include +#include +#include +#include +#include +#include +#include + +#include "textfield.h" + +class TextLabel : public Meter +{ +Q_OBJECT +public: + enum ScrollType { ScrollNone, ScrollNormal, + ScrollBackAndForth, ScrollOnePass }; + + TextLabel(karamba *k, int x,int y,int w,int h); + TextLabel(karamba *k); + ~TextLabel(); + + void setTextProps( TextField* ); + void setValue( QString ); + void setValue( long ); + //virtual QString getStringValue() const { return value.join("\n"); }; + QString getStringValue() const { return value.join("\n"); }; + void setFontSize( int ); + void setBGColor(QColor clr); + void setFont( QString ); + void setAlignment( QString ); + void setFixedPitch( bool ); + void setShadow( int ); + void mUpdate( QPainter * ); + + virtual void show(); + virtual void hide(); + int getFontSize() const; + QColor getBGColor() const; + QString getFont() const; + QString getAlignment() const; + bool getFixedPitch() const; + int getShadow() const; + void setScroll(ScrollType type, QPoint speed, int gap, int pause); + void setScroll(char* type, QPoint speed, int gap, int pause); + + void attachClickArea(QString leftMouseButton, QString middleMouseButton, + QString rightMouseButton); + + virtual bool click(QMouseEvent*); + +private: + int alignment; + int clip; + QStringList value; + QFont font; + QColor bgColor; + int lineHeight; + QSize textSize; + int shadow; + TextField text; + QPoint scrollSpeed; + QPoint scrollPos; + int scrollGap; + int scrollPause; + int pauseCounter; + ScrollType scrollType; + + int drawText(QPainter *p, int x, int y, int width, int height, + QString text); + bool calculateScrollCoords(QRect meterRect, QRect &textRect, + QPoint &next, int &x, int &y); + void calculateTextSize(); +}; + +#endif // TEXTLABEL_H diff --git a/superkaramba/src/textlabel_python.cpp b/superkaramba/src/textlabel_python.cpp new file mode 100644 index 0000000..0802be9 --- /dev/null +++ b/superkaramba/src/textlabel_python.cpp @@ -0,0 +1,235 @@ +/**************************************************************************** +* textlabel_python.cpp - Functions for textlabel python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "textlabel.h" +#include "meter_python.h" +#include "textlabel_python.h" + +PyObject* py_createText(PyObject *, PyObject *args) +{ + long widget, x, y, w, h; + PyObject *text; + if (!PyArg_ParseTuple(args, (char*)"lllllO:createText", &widget, &x, &y, &w, &h, &text)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + TextLabel *tmp = + new TextLabel((karamba*)widget, (int)x, (int)y, (int)w, (int)h); + tmp->setValue(PyString2QString(text)); + tmp->setTextProps(((karamba*)widget)->getDefaultTextProps()); + ((karamba*)widget)->meterList->append(tmp); + return (Py_BuildValue((char*)"l", (long)tmp)); +} + +PyObject* py_deleteText(PyObject *, PyObject *args) +{ + long widget, meter; + if (!PyArg_ParseTuple(args, (char*)"ll:deleteText", &widget, &meter)) + return NULL; + if (!checkKarambaAndMeter(widget, meter, "TextLabel")) + return NULL; + + ((karamba*)widget)->deleteMeterFromSensors((Meter*)meter); + ((karamba*)widget)->clickList->removeRef((Meter*)meter); + return Py_BuildValue((char*)"l", + ((karamba*)widget)->meterList->removeRef((Meter*)meter)); +} + +PyObject* py_getThemeText(PyObject *self, PyObject *args) +{ + return py_getThemeMeter(self, args, "TextLabel"); +} + +PyObject* py_getTextSize(PyObject *self, PyObject *args) +{ + return py_getSize(self, args, "TextLabel"); +} + +PyObject* py_resizeText(PyObject *self, PyObject *args) +{ + return py_resize(self, args, "TextLabel"); +} + +PyObject* py_getTextPos(PyObject *self, PyObject *args) +{ + return py_getPos(self, args, "TextLabel"); +} + +PyObject* py_moveText(PyObject *self, PyObject *args) +{ + return py_move(self, args, "TextLabel"); +} + +PyObject* py_hideText(PyObject *self, PyObject *args) +{ + return py_hide(self, args, "TextLabel"); +} + +PyObject* py_showText(PyObject *self, PyObject *args) +{ + return py_show(self, args, "TextLabel"); +} + +PyObject* py_getTextValue(PyObject *self, PyObject *args) +{ + return py_getStringValue(self, args, "TextLabel"); +} + +PyObject* py_setTextValue(PyObject *self, PyObject *args) +{ + return py_setStringValue(self, args, "TextLabel"); +} + +PyObject* py_getTextSensor(PyObject *self, PyObject *args) +{ + return py_getSensor(self, args, "TextLabel"); +} + +PyObject* py_setTextSensor(PyObject *self, PyObject *args) +{ + return py_setSensor(self, args, "TextLabel"); +} + +PyObject* py_getTextColor(PyObject *self, PyObject *args) +{ + return py_getColor(self, args, "TextLabel"); +} + +PyObject* py_setTextColor(PyObject *self, PyObject *args) +{ + return py_setColor(self, args, "TextLabel"); +} + +PyObject* py_setTextShadow(PyObject *, PyObject *args) +{ + long widget, textSensor; + long shadow; + if (!PyArg_ParseTuple(args, (char*)"lll:changeTextShadow", + &widget, &textSensor, &shadow)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "TextLabel")) + return NULL; + ((TextLabel*)textSensor)->setShadow( shadow ); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getTextShadow(PyObject *, PyObject *args) +{ + long widget, textSensor; + if (!PyArg_ParseTuple(args, (char*)"ll:getTextShadow", &widget, &textSensor)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "TextLabel")) + return NULL; + return Py_BuildValue((char*)"l", ((TextLabel*)textSensor)->getShadow()); +} + +PyObject* py_setTextFontSize(PyObject *, PyObject *args) +{ + long widget, textSensor; + long size; + if (!PyArg_ParseTuple(args, (char*)"lll:changeTextSize", + &widget, &textSensor, &size)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "TextLabel")) + return NULL; + ((TextLabel*)textSensor)->setFontSize( size ); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getTextFontSize(PyObject *, PyObject *args) +{ + long widget, textSensor; + if (!PyArg_ParseTuple(args, (char*)"ll:getTextSize", &widget, &textSensor)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "TextLabel")) + return NULL; + return Py_BuildValue((char*)"l", ((TextLabel*)textSensor)->getFontSize()); +} + +PyObject* py_setTextFont(PyObject *, PyObject *args) +{ + long widget, textSensor; + char* text; + if (!PyArg_ParseTuple(args, (char*)"lls:changeTextFont", + &widget, &textSensor, &text)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "TextLabel")) + return NULL; + ((TextLabel*)textSensor)->setFont( text ); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getTextFont(PyObject *, PyObject *args) +{ + long widget, textSensor; + if (!PyArg_ParseTuple(args, (char*)"ll:getTextFont", &widget, &textSensor)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "TextLabel")) + return NULL; + return Py_BuildValue((char*)"s", ((TextLabel*)textSensor)->getFont().ascii()); +} + +PyObject* py_setTextAlign(PyObject *, PyObject *args) +{ + long widget, textSensor; + char* text; + if (!PyArg_ParseTuple(args, (char*)"lls:changeTextFont", + &widget, &textSensor, &text)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "TextLabel")) + return NULL; + ((TextLabel*)textSensor)->setAlignment( text ); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_getTextAlign(PyObject *, PyObject *args) +{ + long widget, textSensor; + if (!PyArg_ParseTuple(args, (char*)"ll:getTextFont", &widget, &textSensor)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "TextLabel")) + return NULL; + return Py_BuildValue((char*)"s", ((TextLabel*)textSensor)->getAlignment().ascii()); +} + +PyObject* py_setTextScroll(PyObject *, PyObject *args) +{ + long widget, textSensor; + char* type; + int x=0, y=0, pause=0, gap=0; + if (!PyArg_ParseTuple(args, (char*)"lls|llll:setScroll", + &widget, &textSensor, &type, &x, &y, &gap, &pause)) + return NULL; + if (!checkKarambaAndMeter(widget, textSensor, "TextLabel")) + return NULL; + ((TextLabel*)textSensor)->setScroll(type, QPoint(x,y), gap, pause); + return Py_BuildValue((char*)"l", 1); +} diff --git a/superkaramba/src/textlabel_python.h b/superkaramba/src/textlabel_python.h new file mode 100644 index 0000000..78e047a --- /dev/null +++ b/superkaramba/src/textlabel_python.h @@ -0,0 +1,397 @@ +/**************************************************************************** +* textlabel_python.h - Functions for textlabel python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef TEXTLABEL_PYTHON_H +#define TEXTLABEL_PYTHON_H + +/** Text/createText +* +* SYNOPSIS +* long createText(widget, x, y, w, h, text) +* DESCRIPTION +* This creates a text at x,y with width and height w,h. You need to save +* the return value of this function to call other functions on your text +* field, such as changeText() +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* * long w -- width +* * long h -- height +* * string text -- text for the textlabel +* RETURN VALUE +* Pointer to new text meter +*/ +PyObject* py_createText(PyObject *self, PyObject *args); + +/** Text/deleteText +* +* SYNOPSIS +* long deleteText(widget, text) +* DESCRIPTION +* This removes a text object from memory. Please do not call functions on +* "text" after calling deleteText, as it does not exist anymore and that +* could cause crashes in some cases. +* ARGUMENTS +* * long widget -- karamba +* * long widget -- text +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_deleteText(PyObject *self, PyObject *args); + +/** Text/getThemeText +* +* SYNOPSIS +* long getThemeText(widget, name) +* DESCRIPTION +* You can reference text in your python code that was created in the +* theme file. Basically, you just add a NAME= value to the TEXT line in +* the .theme file. Then if you want to use that object, instead of calling +* createText, you can call this function. +* +* The name you pass to the function is the same one that you gave it for +* the NAME= parameter in the .theme file. +* ARGUMENTS +* * long widget -- karamba +* * string name -- name of the text to get +* RETURN VALUE +* Pointer to text +*/ +PyObject* py_getThemeText(PyObject *self, PyObject *args); + +/** Text/getTextSize +* +* SYNOPSIS +* tuple getTextSize(widget, text) +* DESCRIPTION +* Given a reference to a text object, this will return a tuple +* containing the height and width of a text object. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* size +*/ +PyObject* py_getTextSize(PyObject *self, PyObject *args); + +/** Text/resizeText +* +* SYNOPSIS +* long resizeText(widget, text, w, h) +* DESCRIPTION +* This will resize text to new height and width. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* * long w -- new width +* * long h -- new height +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_resizeText(PyObject *self, PyObject *args); + +/** Text/getTextPos +* +* SYNOPSIS +* tuple getTextPos(widget, text) +* DESCRIPTION +* Given a reference to a text object, this will return a tuple +* containing the x and y coordinate of a text object. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* pos +*/ +PyObject* py_getTextPos(PyObject *self, PyObject *args); + +/** Text/moveText +* +* SYNOPSIS +* long moveText(widget, text, x, y) +* DESCRIPTION +* This moves a text object to a new x, y relative to your widget. In other +* words, (0,0) is the top corner of your widget, not the screen. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* * long x -- x coordinate +* * long y -- y coordinate +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_moveText(PyObject *self, PyObject *args); + +/** Text/hideText +* +* SYNOPSIS +* long hideText(widget, text) +* DESCRIPTION +* Hides text that is visible. You need to call redrawWidget() afterwords +* to actually hide the text on screen. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_hideText(PyObject *self, PyObject *args); + +/** Text/showText +* +* SYNOPSIS +* long showText(widget, text) +* DESCRIPTION +* Shows text that has been hidden with hideText() +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_showText(PyObject *self, PyObject *args); + +/** Text/getTextValue +* +* SYNOPSIS +* string getTextValue(widget, text) +* DESCRIPTION +* Returns current text value. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* value +*/ +PyObject* py_getTextValue(PyObject *self, PyObject *args); + +/** Text/changeText +* +* SYNOPSIS +* long changeText(widget, text, value) +* DESCRIPTION +* This will change the contents of a text widget. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* * long value -- new value +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setTextValue(PyObject *self, PyObject *args); + +/** Text/getTextSensor +* +* SYNOPSIS +* string getTextSensor(widget, text) +* DESCRIPTION +* Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* sensor string +*/ +PyObject* py_getTextSensor(PyObject *self, PyObject *args); + +/** Text/setTextSensor +* +* SYNOPSIS +* long setTextSensor(widget, text, sensor) +* DESCRIPTION +* Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* * string sensor -- new sensor as in theme files +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setTextSensor(PyObject *self, PyObject *args); + +/** Text/changeTextShadow +* +* SYNOPSIS +* long changeTextShadow(widget, text, shadow) +* DESCRIPTION +* This will change the shadow size of a text widget (only ones you +* created through python currently). textToChange is the reference to the +* text object to change that you saved from the createText() call. size +* is the offset of the shadow in pixels. 1 or 2 is a good value in most +* cases. Get current sensor string +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* * long shadow -- shadow offset +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setTextShadow(PyObject *self, PyObject *args); + +/** Text/getTextShadow +* +* SYNOPSIS +* long getTextShadow(widget, text) +* DESCRIPTION +* Get current shadow offset +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* shadow offset +*/ +PyObject* py_getTextShadow(PyObject *self, PyObject *args); + +/** Text/changeTextSize +* +* SYNOPSIS +* long changeTextSize(widget, text, size) +* DESCRIPTION +* This will change the font size of a text widget (only ones you created +* through python currently). textToChange is the reference to the text +* object to change that you saved from the createText() call. size is the +* new font point size. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* * long size -- new size for text +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setTextFontSize(PyObject *self, PyObject *args); + +/** Text/getTextFontSize +* +* SYNOPSIS +* long getTextFontSize(widget, text) +* DESCRIPTION +* Get current text font size +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* text font size +*/ +PyObject* py_getTextFontSize(PyObject *self, PyObject *args); + +/** Text/changeTextColor +* +* SYNOPSIS +* long changeTextColor(widget, text, r, g, b) +* DESCRIPTION +* This will change the color of a text widget (only ones you created +* through python currently). textToChange is the reference to the text +* object to change that you saved from the createText() call. r, g, b are +* ints from 0 to 255 that represent red, green, and blue. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* * long red -- red component of color +* * long green -- green component of color +* * long blue -- blue component of color +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setTextColor(PyObject *self, PyObject *args); + +/** Text/getTextColor +* +* SYNOPSIS +* tuple getTextColor(widget, text) +* DESCRIPTION +* Get current text color +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* (red, green, blue) +*/ +PyObject* py_getTextColor(PyObject *self, PyObject *args); + +/** Text/changeTextFont +* +* SYNOPSIS +* long changeTextFont(widget, text, font) +* DESCRIPTION +* This will change the font of a text widget (only ones you created +* through python currently). Text is the reference to the text +* object to change that you saved from the createText() call. Font is a +* string the the name of the font to use. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* * string font -- font name +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setTextFont(PyObject *self, PyObject *args); + +/** Text/getTextFont +* +* SYNOPSIS +* string getTextFont(widget, text) +* DESCRIPTION +* Get current text font name +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* font name +*/ +PyObject* py_getTextFont(PyObject *self, PyObject *args); + +/** Text/setTextAlign +* +* SYNOPSIS +* long setTextAlign(widget, text, align) +* DESCRIPTION +* Sets text label align. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* * string align -- LEFT, CENTER or RIGHT +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_setTextAlign(PyObject *self, PyObject *args); + +/** Text/getTextAlign +* +* SYNOPSIS +* string getTextAlign(widget, text) +* DESCRIPTION +* Get current text align. +* ARGUMENTS +* * long widget -- karamba +* * long text -- pointer to text +* RETURN VALUE +* LEFT, CENTER or RIGHT +*/ +PyObject* py_getTextAlign(PyObject *self, PyObject *args); + +// XXX: Is this valid for new release +PyObject* py_setTextScroll(PyObject *self, PyObject *args); + +#endif // TEXTLABEL_PYTHON_H diff --git a/superkaramba/src/themefile.cpp b/superkaramba/src/themefile.cpp new file mode 100644 index 0000000..ac02e2f --- /dev/null +++ b/superkaramba/src/themefile.cpp @@ -0,0 +1,414 @@ +/**************************************************************************** +* themefile.cpp - Theme file handling +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damst� +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ +#include "themefile.h" +#include "lineparser.h" +#include "themelocale.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ZipFile +{ + public: + ZipFile() : + m_zip(0), m_file(0) + { + } + void setFile(const QString& filename) + { + m_filename = filename; + if(filename.isEmpty()) + return; + + const KArchiveEntry* entry; + + entry = m_dir->entry(filename); + if(entry == 0 || !entry->isFile()) + { + m_file = 0; + return; + } + m_file = static_cast(entry); + } + void setZip(const QString& zipfile) + { + closeZip(); + + m_zip = new KZip(zipfile); + + if(!m_zip->open(IO_ReadOnly)) + { + qDebug("Unable to open '%s' for reading.", zipfile.ascii()); + return; + } + m_dir = m_zip->directory(); + if(m_dir == 0) + { + qDebug("Error reading directory contents of file %s", zipfile.ascii()); + return; + } + } + + virtual ~ZipFile() + { + closeZip(); + } + + void closeZip() + { + if(m_zip) + { + m_zip->close(); + delete m_zip; + } + } + + QByteArray data() + { + if(m_file) + return m_file->data(); + else + { + if(!m_filename.isEmpty()) + qDebug("Error reading file %s from zip", m_filename.ascii()); + return QByteArray(); + } + } + + bool exists() + { + return (m_file != 0); + } + + private: + KZip* m_zip; + const KArchiveFile* m_file; + QString m_filename; + const KArchiveDirectory* m_dir; +}; + +ThemeFile::ThemeFile(const KURL& url) + : m_stream(0), m_locale(0), m_zip(0) +{ + if(url.isValid()) + set(url); +} + +ThemeFile::~ThemeFile() +{ + delete m_stream; + delete m_locale; + delete m_zip; +} + +bool ThemeFile::open() +{ + bool result = false; + + close(); + + if(m_zipTheme) + { + m_zip->setFile(m_theme); + m_ba = m_zip->data(); + if(m_ba.size() > 0) + { + m_stream = new QTextStream(m_ba, IO_ReadOnly); + result = true; + } + } + else + { + m_fl.setName(m_file); + + if(m_fl.open(IO_ReadOnly|IO_Translate)) + { + m_stream = new QTextStream(&m_fl); // use a text stream + result = true; + } + } + return result; +} + +bool ThemeFile::nextLine(LineParser& parser) +{ + parser.set(""); + + if(m_stream) + { + QString result = m_stream->readLine(); + + if(result.isNull()) + return false; + parser.set(result); + return true; + } + return false; +} + +bool ThemeFile::close() +{ + if(m_stream) + { + delete m_stream; + m_stream = 0; + m_fl.close(); + m_ba.resize(0); + return true; + } + return false; +} + +bool ThemeFile::isValid() const +{ + return (exists() && !m_name.isEmpty() && !m_theme.isEmpty()); +} + +bool ThemeFile::exists() const +{ + QFileInfo file(m_file); + return file.exists(); +} + +QPixmap ThemeFile::icon() const +{ + return QPixmap(readThemeFile(m_icon)); +} + +bool ThemeFile::set(const KURL &url) +{ + if(!url.isLocalFile() && !url.protocol().isEmpty()) + { + if(KMessageBox::warningContinueCancel(kapp->activeWindow(), + i18n("You are about to install and run %1 SuperKaramba theme. Since " + "themes can contain executable code you should only install themes " + "from sources that you trust. Continue?"), i18n("Executable Code Warning"), i18n("Install") + .arg(url.prettyURL())) + == KMessageBox::Cancel) + { + return false; + } + + QDir themeDir(locateLocal("appdata", "themes/", true)); + QFileInfo localFile = themeDir.filePath(url.fileName()); + + if(localFile.exists()) + { + if(KMessageBox::warningContinueCancel(kapp->activeWindow(), + i18n("%1 already exists. Do you want to overwrite it?") + .arg(localFile.filePath()),i18n("File Exists"),i18n("Overwrite")) + == KMessageBox::Cancel) + { + return false; + } + } + if(!KIO::NetAccess::file_copy(url, localFile.filePath(), -1, true, + false, kapp->mainWidget())) + { + return false; + } + m_file = localFile.filePath(); + } + else + { + if(url.directory().isEmpty() || url.directory() == "/") + m_file = canonicalFile(QDir::current().filePath(url.fileName())); + else + m_file = canonicalFile(url.path()); + if(!exists()) + return false; + } + + QFileInfo fi(m_file); + + m_name = fi.baseName( TRUE ); + m_theme = m_name + ".theme"; + m_python = m_name; + m_id = m_name; + + if(isZipFile(m_file)) + { + m_path = m_file; + m_zipTheme = true; + m_zip = new ZipFile(); + m_zip->setZip(m_file); + } + else + { + m_path = fi.dirPath(true) + "/"; + m_zipTheme = false; + } + parseXml(); + + QFileInfo fimo(m_python); + if(m_python.isEmpty()) + fimo.setFile(m_theme); + else + fimo.setFile(m_python); + m_mo = fimo.baseName( TRUE ); + + m_locale = new ThemeLocale(this); + return isValid(); +} + +void ThemeFile::parseXml() +{ + if(!fileExists("maindata.xml")) + return; + QByteArray ba = readThemeFile("maindata.xml"); + QDomDocument doc("superkaramba_theme"); + doc.setContent(ba); + QDomElement element = doc.documentElement(); + + QDomNode n = element.firstChild(); + while(!n.isNull()) + { + QDomElement e = n.toElement(); + if(!e.isNull()) + { + if(e.tagName() == "name") + m_name = e.text(); + else if(e.tagName() == "themefile") + m_theme = e.text(); + else if(e.tagName() == "python_module") + { + m_python = e.text(); + if(m_python.right(3).lower() == ".py") + m_python.remove(m_python.length() - 3, 3); + } + else if(e.tagName() == "description") + m_description = e.text(); + else if(e.tagName() == "author") + m_author = e.text(); + else if(e.tagName() == "author_email") + m_authorEmail = e.text(); + else if(e.tagName() == "homepage") + m_homepage = e.text(); + else if(e.tagName() == "icon") + m_icon = e.text(); + else if(e.tagName() == "version") + m_version = e.text(); + else if(e.tagName() == "license") + m_license = e.text(); + } + n = n.nextSibling(); + } +} + +bool ThemeFile::canUninstall() const +{ + QFileInfo fi(file()); + if(fi.permission(QFileInfo::WriteUser) || + fi.permission(QFileInfo::WriteGroup) || + fi.permission(QFileInfo::WriteOther)) + return true; + return false; +} + +bool ThemeFile::isThemeFile(const QString& filename) const +{ + QFileInfo fileInfo(filename); + + return fileInfo.isRelative(); +} + +bool ThemeFile::fileExists(const QString& filename) const +{ + if(isThemeFile(filename)) + { + if(isZipTheme()) + { + m_zip->setFile(filename); + return m_zip->exists(); + } + else + return QFileInfo(path() + "/" + filename).exists(); + } + else + return QFileInfo(filename).exists(); +} + +QByteArray ThemeFile::readThemeFile(const QString& filename) const +{ + //QTime time; + //time.start(); + QByteArray ba; + + if(isZipTheme()) + { + m_zip->setFile(filename); + ba = m_zip->data(); + } + else + { + QFile file(path() + "/" + filename); + + if(file.open(IO_ReadOnly)) + { + ba = file.readAll(); + file.close(); + } + } + //kdDebug() << "Read theme file: " << filename << ", " << time.elapsed() + // << "ms" << endl; + return ba; +} + +bool ThemeFile::isZipFile(const QString& filename) +{ + QFile file(filename); + + if(file.open(IO_ReadOnly)) + { + unsigned char buf[5]; + + if(file.readBlock((char*)buf, 4) == 4) + { + if(buf[0] == 'P' && buf[1] == 'K' && buf[2] == 3 && buf[3] == 4) + return true; + } + } + return false; +} + +bool ThemeFile::pythonModuleExists() const +{ + return (!m_python.isEmpty() && fileExists(m_python + ".py")); +} + +QString ThemeFile::canonicalFile(const QString& file) +{ + // Get absolute path with NO symlinks + QFileInfo fi(file); + return QDir(fi.dir().canonicalPath()).filePath(fi.fileName()); +} diff --git a/superkaramba/src/themefile.h b/superkaramba/src/themefile.h new file mode 100644 index 0000000..c8259d6 --- /dev/null +++ b/superkaramba/src/themefile.h @@ -0,0 +1,107 @@ +/**************************************************************************** +* themefile.h - Theme file handling +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ +#ifndef THEMEFILE_H +#define THEMEFILE_H + +#include +#include +#include +#include +#include +#include + +class LineParser; +class QTextStream; +class ThemeLocale; +class ZipFile; + +/** +@author See README for the list of authors +*/ +class ThemeFile +{ + public: + typedef QValueVector List; + + ThemeFile(const KURL& url = KURL()); + ~ThemeFile(); + + bool isZipTheme() const { return m_zipTheme; }; + const QString& name() const { return m_name; }; + const QString& version() const { return m_version; }; + const QString& license() const { return m_license; }; + const QString& id() const { return m_id; }; + const QString& mo() const { return m_mo; }; + const QString& file() const { return m_file; }; + const QString& pythonModule() const { return m_python; }; + bool pythonModuleExists() const; + const QString& path() const { return m_path; }; + const QString& description() const { return m_description; }; + const QString& author() const { return m_author; }; + const QString& authorEmail() const { return m_authorEmail; }; + const QString& homepage() const { return m_homepage; }; + QPixmap icon() const; + bool exists() const; + bool isThemeFile(const QString& filename) const; + bool isValid() const; + QByteArray readThemeFile(const QString& filename) const; + bool fileExists(const QString& filename) const; + const ThemeLocale* locale() const { return m_locale; }; + bool canUninstall() const; + + bool set(const KURL& url); + bool open(); + bool nextLine(LineParser& parser); + bool close(); + + static bool isZipFile(const QString& filename); + static QString canonicalFile(const QString& file); + + private: + void parseXml(); + void mkdir(QDir dir); + + QString m_path; + bool m_zipTheme; + QString m_file; + QString m_id; + QString m_mo; + QString m_name; + QString m_theme; + QString m_python; + QString m_icon; + QString m_version; + QString m_license; + QTextStream* m_stream; + QByteArray m_ba; + QFile m_fl; + QString m_description; + QString m_author; + QString m_authorEmail; + QString m_homepage; + ThemeLocale* m_locale; + ZipFile* m_zip; +}; + +#endif diff --git a/superkaramba/src/themelocale.cpp b/superkaramba/src/themelocale.cpp new file mode 100644 index 0000000..76fa62b --- /dev/null +++ b/superkaramba/src/themelocale.cpp @@ -0,0 +1,438 @@ +/* + * languageList from klocale.cpp + * Copyright (c) 1997,2001 Stephan Kulow + * Copyright (c) 1999 Preston Brown + * Copyright (c) 1999-2002 Hans Petter Bieker + * Copyright (c) 2002 Lukas Tinkl + * + * libintl.cpp -- gettext related functions from glibc-2.0.5 + * Copyright (C) 1995 Software Foundation, Inc. + * + * This file is part of SuperKaramba. + * Copyright (c) 2005 Petri Damsten + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#include + +#include "themelocale.h" +#include "themefile.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifndef W +# define W(flag, data) ((flag) ? SWAP (data) : (data)) +#endif + +typedef Q_UINT32 nls_uint32; + +struct loaded_domain +{ + const char *data; + int must_swap; + nls_uint32 nstrings; + struct string_desc *orig_tab; + struct string_desc *trans_tab; + nls_uint32 hash_size; + nls_uint32 *hash_tab; +}; + +static inline nls_uint32 SWAP (nls_uint32 i) +{ + return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); +} + +/* @@ end of prolog @@ */ + +/* The magic number of the GNU message catalog format. */ +#define _MAGIC 0x950412de +#define _MAGIC_SWAPPED 0xde120495 + +/* Revision number of the currently used .mo (binary) file format. */ +#define MO_REVISION_NUMBER 0 + + +/* Defines the so called `hashpjw' function by P.J. Weinberger + [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, + 1986, 1987 Bell Telephone Laboratories, Inc.] */ +static inline unsigned long hash_string (const char *__str_param); + +/* @@ end of prolog @@ */ + +/* Header for binary .mo file format. */ +struct mo_file_header +{ + /* The magic number. */ + nls_uint32 magic; + /* The revision number of the file format. */ + nls_uint32 revision; + /* The number of strings pairs. */ + nls_uint32 nstrings; + /* Offset of table with start offsets of original strings. */ + nls_uint32 orig_tab_offset; + /* Offset of table with start offsets of translation strings. */ + nls_uint32 trans_tab_offset; + /* Size of hashing table. */ + nls_uint32 hash_tab_size; + /* Offset of first hashing entry. */ + nls_uint32 hash_tab_offset; +}; + +struct string_desc +{ + /* Length of addressed string. */ + nls_uint32 length; + /* Offset of string in file. */ + nls_uint32 offset; +}; + +void tl_nl_load_domain(QIODevice* device, int size, + struct sk_kde_loaded_l10nfile *domain_file); +char* tl_nl_find_msg(const struct sk_kde_loaded_l10nfile *domain_file, + const char *msgid); +void tl_nl_unload_domain(struct loaded_domain *domain); + +ThemeLocale::ThemeLocale(ThemeFile* theme) + : m_theme(theme) +{ + setLanguage(languageList()); +} + +ThemeLocale::~ThemeLocale() +{ + unload(); +} + +void ThemeLocale::unload() +{ + if(m_domain.data) + { + tl_nl_unload_domain((struct loaded_domain *)m_domain.data); + m_domain.data = 0; + } +} + +QString ThemeLocale::translate(QString text) const +{ + if(text == 0) + return QString::null; + if(m_domain.data) + { + QString result = QString::fromUtf8(tl_nl_find_msg(&m_domain, text.ascii())); + if(result.isEmpty()) + return text; + else + return result; + } + return text; +} + +void ThemeLocale::setLanguage(const QStringList &languages) +{ + unload(); + for(QStringList::ConstIterator it = languages.begin(); + it != languages.end(); + ++it) + { + QString file = + QString("locale/%1/LC_MESSAGES/%2.mo").arg(*it).arg(m_theme->mo()); + + if(m_theme->fileExists(file)) + { + QBuffer buffer(m_theme->readThemeFile(file)); + tl_nl_load_domain(&buffer, buffer.size(), &m_domain); + m_language = *it; + return; + } + } +} + +QStringList ThemeLocale::languageList() +{ + KConfig* config = KGlobal::instance()->config(); + // Reset the list and add the new languages + QStringList languageList; + languageList += + QStringList::split(':', QFile::decodeName(::getenv("KDE_LANG"))); + + languageList += config->readListEntry("Language", ':'); + + // same order as setlocale use + // HPB: Only run splitLocale on the environment variables.. + QStringList langs; + + langs << QFile::decodeName(::getenv("LC_ALL")); + langs << QFile::decodeName(::getenv("LC_MESSAGES")); + langs << QFile::decodeName(::getenv("LANG")); + + for(QStringList::Iterator it = langs.begin(); + it != langs.end(); + ++it ) + { + QString ln, ct, chrset; + KLocale::splitLocale(*it, ln, ct, chrset); + /* + We don't use these in zip themes... + if (!ct.isEmpty()) + { + langs.insert(it, ln + '_' + ct); + if (!chrset.isEmpty()) + langs.insert(it, ln + '_' + ct + '.' + chrset); + } + */ + langs.insert(it, ln); + } + languageList += langs; + // Remove empty strings + QStringList::Iterator end( languageList.end() ); + for(QStringList::Iterator it=languageList.begin(); it!=end;) + { + if((*it).isEmpty()) + it = languageList.remove(it); + else + ++it; + } + return languageList; +} + +char* tl_nl_find_msg (const struct sk_kde_loaded_l10nfile *domain_file, + const char *msgid) +{ + size_t top, act, bottom; + struct loaded_domain *domain; + + if (domain_file->decided == 0) + return NULL; + + if (domain_file->data == NULL) + return NULL; + + domain = (struct loaded_domain *) domain_file->data; + + /* Locate the MSGID and its translation. */ + if (domain->hash_size > 2 && domain->hash_tab != NULL) + { + /* Use the hashing table. */ + nls_uint32 len = strlen (msgid); + nls_uint32 hash_val = hash_string (msgid); + nls_uint32 idx = hash_val % domain->hash_size; + nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); + nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]); + + if (nstr == 0) + /* Hash table entry is empty. */ + return NULL; + + if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len + && strcmp (msgid, + domain->data + W (domain->must_swap, + domain->orig_tab[nstr - 1].offset)) == 0) + return (char *) domain->data + W (domain->must_swap, + domain->trans_tab[nstr - 1].offset); + + while (1) + { + if (idx >= domain->hash_size - incr) + idx -= domain->hash_size - incr; + else + idx += incr; + + nstr = W (domain->must_swap, domain->hash_tab[idx]); + if (nstr == 0) + /* Hash table entry is empty. */ + return NULL; + + if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len + && strcmp (msgid, + domain->data + W (domain->must_swap, + domain->orig_tab[nstr - 1].offset)) + == 0) + return (char *) domain->data + + W (domain->must_swap, domain->trans_tab[nstr - 1].offset); + } + /* NOTREACHED */ + } + + /* Now we try the default method: binary search in the sorted + array of messages. */ + bottom = 0; + top = domain->nstrings; + act = top; + while (bottom < top) + { + int cmp_val; + + act = (bottom + top) / 2; + cmp_val = strcmp (msgid, domain->data + + W (domain->must_swap, + domain->orig_tab[act].offset)); + if (cmp_val < 0) + top = act; + else if (cmp_val > 0) + bottom = act + 1; + else + break; + } + + /* If an translation is found return this. */ + return bottom >= top ? NULL : (char *) domain->data + + W (domain->must_swap, + domain->trans_tab[act].offset); +} + +/* @@ begin of epilog @@ */ +/* We assume to have `unsigned long int' value with at least 32 bits. */ +#define HASHWORDBITS 32 + +static inline unsigned long +hash_string (const char *str_param) +{ + unsigned long int hval, g; + const char *str = str_param; + + /* Compute the hash value for the given string. */ + hval = 0; + while (*str != '\0') + { + hval <<= 4; + hval += (unsigned long) *str++; + g = hval & ((unsigned long) 0xf << (HASHWORDBITS - 4)); + if (g != 0) + { + hval ^= g >> (HASHWORDBITS - 8); + hval ^= g; + } + } + return hval; +} + +/* Load the message catalogs specified by device. If it is no valid + message catalog do nothing. */ +void tl_nl_load_domain (QIODevice* device, int size, + struct sk_kde_loaded_l10nfile *domain_file) +{ + struct mo_file_header *data = (struct mo_file_header *) -1; + struct loaded_domain *domain; + + domain_file->decided = 1; + domain_file->data = NULL; + + /* If the record does not represent a valid locale the FILENAME + might be NULL. This can happen when according to the given + specification the locale file name is different for XPG and CEN + syntax. */ + if (device == NULL) + return; + + /* Try to open the addressed file. */ + if (device->open(IO_ReadOnly) == false) + return; + + /* We must know about the size of the file. */ + if (size < (off_t) sizeof (struct mo_file_header)) + { + /* Something went wrong. */ + device->close(); + return; + } + + /* If the data is not yet available (i.e. mmap'ed) we try to load + it manually. */ + if (data == (struct mo_file_header *) -1) + { + off_t to_read; + char *read_ptr; + + data = (struct mo_file_header *) malloc (size); + if (data == NULL) + return; + + to_read = size; + read_ptr = (char *) data; + do + { + long int nb = (long int) device->readBlock (read_ptr, to_read); + if (nb == -1) + { + device->close(); + return; + } + + read_ptr += nb; + to_read -= nb; + } + while (to_read > 0); + + device->close(); + } + + /* Using the magic number we can test whether it really is a message + catalog file. */ + if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED) + { + /* The magic number is wrong: not a message catalog file. */ + free (data); + return; + } + + domain_file->data + = (struct loaded_domain *) malloc (sizeof (struct loaded_domain)); + if (domain_file->data == NULL) + return; + + domain = (struct loaded_domain *) domain_file->data; + domain->data = (char *) data; + domain->must_swap = data->magic != _MAGIC; + + /* Fill in the information about the available tables. */ + switch (W (domain->must_swap, data->revision)) + { + case 0: + domain->nstrings = W (domain->must_swap, data->nstrings); + domain->orig_tab = (struct string_desc *) + ((char *) data + W (domain->must_swap, + data->orig_tab_offset)); + domain->trans_tab = (struct string_desc *) + ((char *) data + W (domain->must_swap, + data->trans_tab_offset)); + domain->hash_size = W (domain->must_swap, data->hash_tab_size); + domain->hash_tab = (nls_uint32 *) + ((char *) data + W (domain->must_swap, + data->hash_tab_offset)); + break; + default: + /* This is an illegal revision. */ + free (data); + free (domain); + domain_file->data = NULL; + return; + } +} + +void tl_nl_unload_domain (struct loaded_domain *domain) +{ + free ((void *) domain->data); + free (domain); +} diff --git a/superkaramba/src/themelocale.h b/superkaramba/src/themelocale.h new file mode 100644 index 0000000..33b6c4e --- /dev/null +++ b/superkaramba/src/themelocale.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2005 Petri Damsten + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#ifndef THEMELOCALE_H +#define THEMELOCALE_H + +#include +#include + +class ThemeFile; + +/** +@author See README for the list of authors +*/ + +struct sk_kde_loaded_l10nfile +{ + int decided; + const void *data; + sk_kde_loaded_l10nfile() : decided(0), data(0) {} +}; + +class ThemeLocale +{ + public: + ThemeLocale(ThemeFile* theme); + ~ThemeLocale(); + + QString translate(QString text) const; + void setLanguage(const QStringList &languages); + QString language() const { return m_language; }; + + static QStringList languageList(); + + private: + sk_kde_loaded_l10nfile m_domain; + ThemeFile* m_theme; + QString m_language; + + void unload(); +}; + + + +#endif diff --git a/superkaramba/src/themes_layout.ui b/superkaramba/src/themes_layout.ui new file mode 100644 index 0000000..d7d3ba5 --- /dev/null +++ b/superkaramba/src/themes_layout.ui @@ -0,0 +1,241 @@ + +ThemesLayout + + + ThemesLayout + + + + 0 + 0 + 399 + 517 + + + + + 0 + 0 + + + + SuperKaramba Themes + + + + unnamed + + + + layout2 + + + + unnamed + + + + labelSearch + + + &Search: + + + editSearch + + + + + editSearch + + + + + labelShow + + + S&how: + + + comboShow + + + + + + All + + + + + Running + + + + comboShow + + + + + + + tableThemes + + + + 7 + 7 + 0 + 0 + + + + StrongFocus + + + + + layoutButtons + + + + unnamed + + + + spacer + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + buttonAddToDesktop + + + + 0 + 0 + + + + 27 + + + &Add to Desktop + + + + + buttonClose + + + + 0 + 0 + + + + &Close + + + 13 + + + + + + + + + KWidgetListbox +
    kwidgetlistbox.h
    + + -1 + -1 + + 0 + + 5 + 5 + 0 + 0 + + image0 + selected(int) + doubleClicked(int, int, int, const QPoint&) +
    +
    + + + 789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f + + + + + buttonClose + clicked() + ThemesLayout + close() + + + buttonAddToDesktop + clicked() + ThemesLayout + addToDesktop() + + + tableThemes + selected(int) + ThemesLayout + selectionChanged(int) + + + editSearch + textChanged(const QString&) + ThemesLayout + search(const QString&) + + + comboShow + activated(const QString&) + ThemesLayout + search(const QString&) + + + tableThemes + doubleClicked(int,int,int,const QPoint&) + ThemesLayout + addToDesktop() + + + + editSearch + comboShow + tableThemes + buttonAddToDesktop + buttonClose + + + addToDesktop() + selectionChanged(int) + search(const QString&) + + + + + kwidgetlistbox.h + kpushbutton.h + kpushbutton.h + +
    diff --git a/superkaramba/src/themesdlg.cpp b/superkaramba/src/themesdlg.cpp new file mode 100644 index 0000000..655c982 --- /dev/null +++ b/superkaramba/src/themesdlg.cpp @@ -0,0 +1,543 @@ +/* + * Copyright (C) 2005 Petri Damstn + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#include "karambaapp.h" +#include "dcopinterface_stub.h" +#include "karambainterface.h" +#include "themesdlg.h" +#include "themewidget.h" +#include "kwidgetlistbox.h" +#include "karamba.h" + +#ifdef HAVE_CONFIG_H + #include +#endif + +#ifdef HAVE_KNEWSTUFF + #include "sknewstuff.h" +#endif + +#include "superkarambasettings.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +ThemesDlg::ThemesDlg(QWidget *parent, const char *name) + : ThemesLayout(parent, name) +{ + populateListbox(); +#ifdef HAVE_KNEWSTUFF + mNewStuff = 0; +#endif +} + +ThemesDlg::~ThemesDlg() +{ + //kdDebug() << k_funcinfo << endl; + saveUserAddedThemes(); +#ifdef HAVE_KNEWSTUFF + if(mNewStuff) + { + delete mNewStuff; + } +#endif +} + +void ThemesDlg::saveUserAddedThemes() +{ + KStandardDirs ksd; + QStringList t = themes(); + QStringList dirs = ksd.findDirs("data", QString(kapp->name()) + "/themes"); + QStringList::Iterator it = t.begin(); + bool remove; + + while(it != t.end()) + { + remove = false; + QStringList::Iterator jtend( dirs.end() ); + for(QStringList::Iterator jt = dirs.begin(); jt != jtend; ++jt) + { + if(QFileInfo(*it).dir().path() + "/" == *jt) + { + remove = true; + break; + } + } + if(remove) + it = t.remove(it); + else + ++it; + } + SuperKarambaSettings::setUserAddedThemes(t); + SuperKarambaSettings::writeConfig(); +} + +QStringList ThemesDlg::themes() +{ + QStringList result; + ThemeWidget* w; + + for(uint i = 2; i < tableThemes->count(); ++i) + { + w = static_cast(tableThemes->item(i)); + + result.append(w->themeFile()->file()); + } + return result; +} + +void ThemesDlg::populateListbox() +{ + ThemeWidget* item; + QDir dir; + QStringList dirs; + QStringList t; + KStandardDirs ksd; + + tableThemes->clear(); + + item = new ThemeWidget; + item->icon->setPixmap(KGlobal::iconLoader()->loadIcon("knewstuff", + KIcon::NoGroup, KIcon::SizeHuge)); + item->setHeaderText(i18n("Get New Stuff")); + item->setDescriptionText(i18n("Download new themes.")); + + item->buttonGo->setText(i18n("New Stuff...")); +#ifdef HAVE_KNEWSTUFF + item->buttonGo->setEnabled(true); + connect(item->buttonGo, SIGNAL(clicked()), + this, SLOT(getNewStuff())); +#else + item->buttonGo->setEnabled(false); +#endif + tableThemes->insertItem(item); + + item = new ThemeWidget; + item->icon->setPixmap(KGlobal::iconLoader()->loadIcon("ksysguard", + KIcon::NoGroup, KIcon::SizeHuge)); + item->setHeaderText(i18n("Open Local Theme")); + item->setDescriptionText(i18n("Add local theme to the list.")); + item->buttonGo->setProperty("stdItem", 18); + item->buttonGo->setText(i18n("Open...")); + connect(item->buttonGo, SIGNAL(clicked()), + this, SLOT(openLocalTheme())); + tableThemes->insertItem(item); + + dirs = ksd.findDirs("data", QString(kapp->name()) + "/themes"); + // Get custom dirs from config here? + QStringList::Iterator itend( dirs.end() ); + for(QStringList::Iterator it = dirs.begin(); it != itend; ++it ) + { + dir.setPath(*it); + t = dir.entryList("*.skz; *.theme"); + for(QStringList::Iterator it = t.begin(); it != t.end(); ++it ) + { + item = new ThemeWidget(new ThemeFile(dir.filePath(*it))); + tableThemes->insertItem(item); + item->buttonGo->setText(i18n("Uninstall")); + connect(item->buttonGo, SIGNAL(clicked()), + this, SLOT(uninstall())); + } + } + t = SuperKarambaSettings::userAddedThemes(); + for(QStringList::Iterator it = t.begin(); it != t.end(); ++it ) + { + ThemeFile* file = new ThemeFile(*it); + + if(file->isValid()) + { + item = new ThemeWidget(file); + tableThemes->insertItem(item); + item->buttonGo->setText(i18n("Uninstall")); + connect(item->buttonGo, SIGNAL(clicked()), + this, SLOT(uninstall())); + } + else + delete file; + } + tableThemes->setSelected(0); +} + +void ThemesDlg::addToDesktop() +{ + ThemeWidget* w = static_cast(tableThemes->selectedItem()); + if(w) + { + ThemeFile* tf = w->themeFile(); + if(tf) + { + (new karamba(tf->file(), QString()))->show(); + } + } +} + +void ThemesDlg::openLocalTheme() +{ + QStringList fileNames; + fileNames = KFileDialog::getOpenFileNames(":", + i18n("*.theme *.skz|Themes"), + this, i18n("Open Themes")); + for(QStringList::Iterator it = fileNames.begin(); it != fileNames.end(); ++it) + { + ThemeFile file(*it); + if(file.isValid()) + (new karamba(*it, QString()))->show(); + } +} + +void ThemesDlg::getNewStuff() +{ +#ifdef HAVE_KNEWSTUFF + KConfig* config = KGlobal::config(); + config->setGroup("KNewStuff"); + config->writePathEntry("ProvidersUrl", + QString::fromLatin1("http://download.kde.org/khotnewstuff/karamba-providers.xml")); + config->sync(); + m_newStuffStatus = config->entryMap("KNewStuffStatus").keys(); + //This check is b/c KNewStuff will download, throw an error, + //and still have the entry in the config that it was successful + configSanityCheck(); + + if ( !mNewStuff ) + { + mNewStuff = new SKNewStuff(this); + } + mNewStuff->download(); +#endif +} + +void ThemesDlg::selectionChanged(int index) +{ + buttonAddToDesktop->setEnabled(index > 1); + + for(uint i=2; i < tableThemes->count(); ++i) + { + ThemeWidget* w = static_cast(tableThemes->item(i)); + w->showButton(false); + } + ThemeWidget* w = static_cast(tableThemes->item(index)); + ThemeFile* themeFile = w->themeFile(); + if(themeFile && themeFile->canUninstall()) + w->showButton(true); +} + +int ThemesDlg::themeIndex(QString file) +{ + ThemeWidget* w; + file = ThemeFile::canonicalFile(file); + + for(uint i = 2; i < tableThemes->count(); ++i) + { + w = static_cast(tableThemes->item(i)); + + if(w->themeFile()->file() == file) + return i; + } + return -1; +} + +void ThemesDlg::addSkzThemeToDialog(const QString &file) +{ + kdDebug() << "addSkzThemeToDialog(): file = " << file << endl; + addThemeToList(file); + writeNewStuffConfig(file); +} + +void ThemesDlg::addThemeToDialog(const KArchiveDirectory *archiveDir, + const QString& destDir) +{ + kdDebug() << "addThemeToDialog(): destDir = " << destDir << endl; + QStringList entries = archiveDir->entries(); + + QStringList::Iterator end( entries.end() ); + for(QStringList::Iterator it = entries.begin(); it != end; ++it) + { + if(archiveDir->entry(*it)->isDirectory()) + { + addThemeToDialog(static_cast(archiveDir->entry(*it)), + destDir + *it + "/"); + } + else + { + QFileInfo fi(*it); + if(fi.extension( FALSE ) == "theme") + { + addThemeToList(destDir + *it); + writeNewStuffConfig(destDir); + } + } + } +} + +void ThemesDlg::writeNewStuffConfig(const QString &file) +{ +#ifdef HAVE_KNEWSTUFF + KConfig* config = KGlobal::config(); + QStringList keys = config->entryMap("KNewStuffStatus").keys(); + + for(QStringList::Iterator it = m_newStuffStatus.begin(); + it != m_newStuffStatus.end(); ++it) + { + keys.remove(*it); + } + if(!keys.isEmpty()) + { + config->setGroup("KNewStuffNames"); + config->writeEntry(file, keys[0]); + config->sync(); + } +#endif +} + +void ThemesDlg::configSanityCheck() +{ +#ifdef HAVE_KNEWSTUFF + KConfig* config = KGlobal::config(); + QStringList statusKeys = config->entryMap("KNewStuffStatus").keys(); + QStringList nameKeys = config->entryMap("KNewStuffNames").keys(); + QStringList removeList; + + for(QStringList::Iterator it = statusKeys.begin(); + it != statusKeys.end(); ++it) + { + QString keyName(*it); + bool removeKey = true; + config->setGroup("KNewStuffNames"); + for(QStringList::Iterator it2 = nameKeys.begin(); + it2 != nameKeys.end(); ++it2) + { + QString tempName(config->readEntry(*it2)); + if( tempName.compare(keyName) == 0) + { + removeKey = false; + } + + } + if( removeKey ) + { + kdDebug() << "sanityCheck() deleting entry " << keyName << endl; + config->setGroup("KNewStuffStatus"); + config->deleteEntry( keyName ); + } + } + config->sync(); +#endif +} + +int ThemesDlg::addThemeToList(const QString &file) +{ + kdDebug() << "addThemeToList() file: " << file << endl; + int i = themeIndex(file); + if(i < 0) + { + ThemeWidget* item = new ThemeWidget(new ThemeFile(file)); + + i = tableThemes->insertItem(item); + item->buttonGo->setText(i18n("Uninstall")); + connect(item->buttonGo, SIGNAL(clicked()), + this, SLOT(uninstall())); + } + tableThemes->setSelected(i); + return i; +} + +int ThemesDlg::addTheme(const QString& , const QString &file) +{ + int i = addThemeToList(file); + int result = -1; + + ThemeWidget* w = static_cast(tableThemes->item(i)); + if(w) + result = w->addInstance(); + karambaApp->buildToolTip(); + return result; +} + +void ThemesDlg::removeTheme(const QString&, const QString& file, int instance) +{ + int i = themeIndex(file); + + ThemeWidget* w = static_cast(tableThemes->item(i)); + if(w) + w->removeInstance(instance); + karambaApp->buildToolTip(); +} + +void ThemesDlg::search(const QString&) +{ + tableThemes->showItems(&filter, this); +} + +bool ThemesDlg::filter(int index, QWidget* widget, void* data) +{ + if(index < 2) + return true; + + ThemesDlg* dlg = static_cast(data); + ThemeWidget* w = static_cast(widget); + + if(dlg->comboShow->currentItem() == 1) // Running themes + if(w->instances() == 0) + return false; + + QString searchText = dlg->editSearch->text().lower(); + if(searchText.isEmpty()) + { + return true; + } + else + { + if(w->themeName->text().lower().contains(searchText)) + return true; + if(w->description->text().lower().contains(searchText)) + return true; + } + return false; +} + +bool ThemesDlg::isDownloaded( const QString& path ) +{ + kdDebug() << "isDownloaded path: " << path << endl; + KConfig* config = KGlobal::config(); + config->setGroup("KNewStuffNames"); + return !config->readEntry(path).isEmpty(); +} + +void ThemesDlg::uninstall() +{ + ThemeWidget* w = static_cast(tableThemes->selectedItem()); + ThemeFile* tf = w->themeFile(); + KURL trash("trash:/"); + KURL theme(tf->file()); + QString tempPath(tf->path()); + + karambaApp->dcopIface()->closeTheme(tf->name()); + if(!KProtocolInfo::isKnownProtocol(trash)) + trash = KGlobalSettings::trashPath(); + + if(!tf->isZipTheme()) + { + kdDebug() << "encountered unpacked theme" << endl; + //Don't move it to the trash if it is a local theme + if(isDownloaded(tempPath)) + { + QFileInfo remPath(tf->path()); + QDir remDir(remPath.dir()); + remDir.cdUp(); + kdDebug() << "moving " << remDir.path() << " to the trash" << endl; + KIO::move(remDir.path(), trash); + } + tableThemes->removeItem(w); + + //some themes have multiple .theme files + //find all .themes that could be listed in the dialog for the directory removed + QPtrList list; + for(uint i = 2; i < tableThemes->count(); ++i) + { + ThemeWidget* tempW = static_cast(tableThemes->item(i)); + ThemeFile* tempTf = tempW->themeFile(); + if( tempTf->path().compare( tempPath ) == 0 ) + { + list.append( tempW ); + } + } + ThemeWidget *twPtr; + for ( twPtr = list.first(); twPtr; twPtr = list.next() ) + { + karambaApp->dcopIface()->closeTheme(twPtr->themeFile()->name()); + tableThemes->removeItem( twPtr ); + } +#ifdef HAVE_KNEWSTUFF + // Remove theme from KNewStuffStatus + KConfig* config = KGlobal::config(); + config->setGroup("KNewStuffNames"); + QString name = config->readEntry(tempPath); + if(!name.isEmpty()) + { + kdDebug() << "removing " << tempPath << " under KNewStuffNames from superkarambarc" + << endl; + kapp->config()->deleteEntry(tempPath); + config->setGroup("KNewStuffStatus"); + kdDebug() << "removing " << name << " under KNewStuffStatus from superkarambarc" + << endl; + kapp->config()->deleteEntry(name); + kapp->config()->sync(); + } +#endif + + } + else + { + kdDebug() << "encountered skz theme" << endl; + if(isDownloaded(theme.path())) + { + QFileInfo remPath(theme.path()); + QDir remDir(remPath.dir()); + kdDebug() << "moving " << remDir.path() << " to the trash" << endl; + KIO::move(remDir.path(), trash); + } + tableThemes->removeItem(w); +#ifdef HAVE_KNEWSTUFF + // Remove theme from KNewStuffStatus + KConfig* config = KGlobal::config(); + config->setGroup("KNewStuffNames"); + QString name = config->readEntry(theme.path()); + if(!name.isEmpty()) + { + kdDebug() << "removing " << theme.path() << " from superkarambarc" << endl; + kapp->config()->deleteEntry(theme.path()); + config->setGroup("KNewStuffStatus"); + kdDebug() << "removing " << name << " from superkarambarc" << endl; + kapp->config()->deleteEntry(name); + kapp->config()->sync(); + } +#endif + } + selectionChanged(tableThemes->selected()); +} + +QStringList ThemesDlg::runningThemes() +{ + QStringList list; + ThemeWidget* w; + + for(uint i = 2; i < tableThemes->count(); ++i) + { + w = static_cast(tableThemes->item(i)); + + if(w->instances() > 0) + list.append(w->themeFile()->name()); + } + return list; +} + +#include "themesdlg.moc" diff --git a/superkaramba/src/themesdlg.h b/superkaramba/src/themesdlg.h new file mode 100644 index 0000000..268a392 --- /dev/null +++ b/superkaramba/src/themesdlg.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2005 Petri Damstn + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ + +#ifndef THEMESDLG_H +#define THEMESDLG_H + +#include +#include "karambaapp.h" + +#ifdef HAVE_CONFIG_H + #include +#endif + +/** +@author See README for the list of authors +*/ +#ifdef HAVE_KNEWSTUFF +class SKNewStuff; +#endif +class ThemeFile; +class KArchiveDirectory; + +class ThemesDlg : public ThemesLayout +{ + Q_OBJECT + + public: + ThemesDlg(QWidget *parent = 0, const char *name = 0); + ~ThemesDlg(); + + int addTheme(const QString &appId, const QString &file); + void removeTheme(const QString &appId, const QString &file, int instance); + int addThemeToList(const QString &file); + void addSkzThemeToDialog(const QString &file); + void addThemeToDialog(const KArchiveDirectory *archiveDir, const QString& destDir); + void writeNewStuffConfig(const QString &file); + void configSanityCheck(); + bool isDownloaded(const QString &path); + void saveUserAddedThemes(); + QStringList runningThemes(); + + protected slots: + virtual void addToDesktop(); + virtual void selectionChanged(int); + virtual void openLocalTheme(); + virtual void getNewStuff(); + virtual void search(const QString& text); + virtual void uninstall(); + + protected: + static bool filter(int index, QWidget* widget, void* data); + void populateListbox(); + int themeIndex(QString file); + QStringList themes(); + +#ifdef HAVE_KNEWSTUFF + private: + SKNewStuff *mNewStuff; + QStringList m_newStuffStatus; +#endif +}; + +#endif diff --git a/superkaramba/src/themewidget.cpp b/superkaramba/src/themewidget.cpp new file mode 100644 index 0000000..c28e3cf --- /dev/null +++ b/superkaramba/src/themewidget.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2005 Petri Damstn + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#include "themewidget.h" +#include "themelocale.h" +#include +#include +#include +#include +#include + +ThemeWidget::ThemeWidget(QWidget *parent, const char *name) + : ThemeWidgetLayout(parent, name), m_themeFile(0) +{ + running->setText(""); + setDescriptionMaxHeight(); +} + +ThemeWidget::ThemeWidget(ThemeFile* tf) + : m_themeFile(tf) +{ + QPixmap pixmap = m_themeFile->icon(); + if(!pixmap.isNull()) + icon->setPixmap(pixmap); + QString version; + if(!m_themeFile->version().isEmpty()) + version = " - " + m_themeFile->version(); + themeName->setText( + m_themeFile->locale()->translate(m_themeFile->name().ascii()) + version); + description->setText( + m_themeFile->locale()->translate(m_themeFile->description().ascii())); + running->setText(""); + buttonGo->hide(); + setDescriptionMaxHeight(); +} + +ThemeWidget::~ThemeWidget() +{ + delete m_themeFile; +} + +int ThemeWidget::addInstance() +{ + int i = 1; + while(m_instancePool.find(i) != m_instancePool.end()) + ++i; + m_instancePool.append(i); + updateRunning(); + return i; +} + +void ThemeWidget::removeInstance(int instance) +{ + m_instancePool.remove(instance); + updateRunning(); +} + +void ThemeWidget::updateRunning() +{ + int i = instances(); + if(i > 0) + running->setText(i18n("

    %1 running

    ").arg(i)); + else + running->setText(""); +} + +void ThemeWidget::setDescriptionText(QString text) +{ + description->setText(text); +} + +void ThemeWidget::setHeaderText(QString text) +{ + themeName->setText(text); +} + +void ThemeWidget::showButton(bool show) +{ + if(show) + buttonGo->show(); + else + buttonGo->hide(); + setDescriptionMaxHeight(); +} + +void ThemeWidget::setDescriptionMaxHeight() +{ + if(layoutText->geometry().height() <= 0) + return; + int height = layoutText->geometry().height() - themeName->height() - + layoutText->spacing(); + if(buttonGo->isVisible()) + height -= layoutButton->geometry().height() + layoutText->spacing(); + description->setMaximumHeight(height); +} + +#include "themewidget.moc" diff --git a/superkaramba/src/themewidget.h b/superkaramba/src/themewidget.h new file mode 100644 index 0000000..4107716 --- /dev/null +++ b/superkaramba/src/themewidget.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2005 Petri Damstn + * + * This file is part of SuperKaramba. + * + * SuperKaramba is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SuperKaramba is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SuperKaramba; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ****************************************************************************/ +#ifndef THEMEWIDGET_H +#define THEMEWIDGET_H + +#include "themefile.h" +#include + +/** +@author See README for the list of authors +*/ + +class ThemeWidget : public ThemeWidgetLayout +{ + Q_OBJECT + public: + ThemeWidget(QWidget *parent = 0, const char *name = 0); + ThemeWidget(ThemeFile* tf); + ~ThemeWidget(); + + ThemeFile* themeFile() const { return m_themeFile; }; + + int addInstance(); + int instances() const { return m_instancePool.count(); }; + void removeInstance(int instance); + + void setDescriptionText(QString text); + void setHeaderText(QString text); + void showButton(bool show); + + protected: + void updateRunning(); + void setDescriptionMaxHeight(); + + private: + ThemeFile* m_themeFile; + QValueList m_instancePool; +}; + +#endif diff --git a/superkaramba/src/themewidget_layout.ui b/superkaramba/src/themewidget_layout.ui new file mode 100644 index 0000000..eb91f0a --- /dev/null +++ b/superkaramba/src/themewidget_layout.ui @@ -0,0 +1,182 @@ + +ThemeWidgetLayout + + + ThemeWidgetLayout + + + + 0 + 0 + 377 + 112 + + + + + 250 + 248 + 241 + + + + + unnamed + + + + layoutIcon + + + + unnamed + + + + icon + + + + 76 + 0 + + + + + + + image0 + + + AlignCenter + + + + + running + + + + 5 + 1 + 0 + 0 + + + + + 8 + + + + <p align="center">1 running</p> + + + RichText + + + + + + + layoutText + + + + unnamed + + + + themeName + + + + 7 + 5 + 0 + 0 + + + + + 1 + + + + Header + + + + + description + + + + 7 + 7 + 0 + 0 + + + + Description + + + WordBreak|AlignTop + + + + + layoutButton + + + + unnamed + + + + spacer + + + Horizontal + + + Expanding + + + + 40 + 20 + + + + + + buttonGo + + + + + + + + + + + + + + + + + + + 89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de0000136349444154789ccd9b79701cd59dc73fdd3d3da76634b22559b66ccbb66c832f81011f9804dbc460ee04024b4ced5661b2542559425249259b4a422d816443b612925425454208098b03213e30068c39623026061bdf3696e54bb264dd1a5d73f774f7db3fbae7d0686449beb2bfaae77e6f34d3fdbedff7bbfaf79ee112486a2ddf32d7d32b36205efa16f30137205d8a679f4d8410c817f301fa3a569beb697028fc42f2058a0116cfe4274039e038eb6f5f26a8bdc4fed80b1cfcd1bd5401ce8b31c78b42406a2dcbf5756c53649e939cae2a662d81950f40692553cab9e5f1552c038a18420bf497099a26ef23b8429198f7d51b79e77feee76ac035d46fce552ee8cde22f335555f89522732700d58b60d61250652005d16e787b0d6dbd1c1eff2077038d4032f71e03c02f5a8d103ada872f90d289fced63bef4d0b3bc07c40171bef3bd60262036104cade5d76e95538acc9d8c9f032bbf0d353781eac49aab006f114c9a494590b9bf79885b003f395a3810fc9791a72d44a9be0af5ba7b90a1e88bd7f0d797becadd80970ba4bde7a501620341dde05b8acc23924431a53360d64d503a09d0725aca6aa60e89286c7d996858eb28ba9f65403d9048fd95a01069f00f214f5b88b5d009208e196a24ba690d4622c99e53fc60c5cff90d1001cc739efff96880be8ed542b0dfa1f0a8e42b2d66f1d7e0b3df80d26964563cbf09010e2754cdc6e7a6fcb5eff300103cfc14634566e5bf823c6d49963452808e3c760cde3bee06878bf993f8c9e647780408709e9a306a0d48ad65b92cf32b59a206d507b3ee86eacf6199b296732da001866eb5440cb66d408b6bd1ef3ecfbd4fdecfcf149979caa2af214f5b4ceeca5b57bb090d118bd0f7caeba43aba69ed65d3154ff020d007e8a3c52284183901b683fbb322733d00b35641f5cda03a86016f13207208307444d371cc831fa3a5883a247ccaa287ed958fe7b41cf024c14881ae21a2517a5e7d1badb397961e5ebffa49be0c748f9684119980d840505fc7f3b683bb9ec92b61e5f370f99740f590557133af9f3bce31012120a521a21184090e099f34e506e469d73350edb3ea0f3a08c3f221a681e45028b9e57adcd593a8f0737bed0ff9f0df1650cd39e40a432623690727048f2832c5945e05355f87e22aac954e16005e88883478fbbe674e601eda85d03484d38b88c7314e6c452a9b8e327dc160e0e9be69806137534772c80497cc43a40c8c632d33bef7395e8f697c61fd018e63a9dd88a47022b28ed5b2c42f258962bc9570f5e3503a2f0778aecae78e0b99810da8a311b1fb7dcc6818213b90a7cd46ae9c027bde23d11dc3481a38a62fc675fdbd0c527d53035d03dd320152a901fdf0e10642bb4e11d7687bb78e071fd9c87b392b34a414f401a9b52c77286c450d40cda330f9f63ca0f94d2b70cd697d2d70701b664733480ea8988c5c3915dc1e70a8b0771b0289785b1f465cc731e36a3ccbefc882279907dc26229543889e2272ac958e1d0da474221b0f71fff7b6f0778649988672828abe8e7ac51598c4ca6da0ba86216008f0b14ea8dd068d9f629a2005c7214d9c0a5ebf053cddf66f0749420848b48749764791c78cc37fd7bd482ec95afd0cd8c1c073c7d1d321da3e6a261937a3b5edfcf89e17f92d1065885c612827288eb7f228a97ea8fd15598796df8688f5a9181c7d1fb63e078d9f223c7ee4e957204dbd0c3c3e5094bce600878ae474e2995c865ae227d5d14edfba971189986df376336c5f60eab63f1838f655f898f8d909a8aaec9b5dca4f5fbc67f85c61a830e8e95bc3b6809705acdc02ded26156deee9fdc0ab5ef402a014e0f944f027fc9c015cf6f077780248124832c8324116fed2372a21da9c84ff0d6e53882fec2663084592442315a76f510ebd1a9efe67777fe95ef03fd8031120d00481e6fe5bf0138f8b3b3acbc3d6e3d006f3d01075fb3c25569254cba0c7cc5202b676fb606e050adbea2e2995c867fd624f4de305d6bb7906aefb2f3876c28cc8e8d6c84b0fbee2289aa6b8b70fb65aa027ce5ed553c0f945020ea0d458079cd77d8d21be55d5adf83aedd79a06de05db5b0fde7f0f13390e805ff18a8980a81b105547d889601ee0087dd1415f7a43282d74c47e8069debb7123d529f170a8d3c22069a85a2184cbe4ac534a1d4c31dd7543017f00d2220b596e5bd6b5801a87984685bf6f15d006aff3070e5631db0e769d8fe2474d581db076593a1b8cccaf5875bf5821a600147b1fb0e15776529a54be7220c41d7dff71139d298e7038c214831301206f53b358409af1ee38fbbdbc0c638c0ec1d0e85adc55e101b20aef1514ae74022c5c1a62edebbe63bd42d9bcb9f2ad8b79ad60fa07436d43e0f273759bf565de00b82cb6d0338cb4a0f458043cdf101f655b27c01b28c5aeaa4eca62be9da7e94cead874975575152337ef0eae78c8da4ce89ed0962bd828d753cf7f83f781de8c28aad03c2a2d4fa1c5fab08f2db827620e88f2638eaf7b010b5c8fa3015b156cde5039727c7a139cfeeec0a35c5094777679c5f067c86882c31a666d2f2ea6e12edfdf8ab4b19b77862c15068c4344e6c8b10eb31d3e05f034e61155ffac90989e93cc0f7d1937c73f14c7e8c1a84c52f40aa1dfaf643e747d0b567202baa7b2070e53c08903d70fc93b36a402e31a6a6d3b2690fd1862e8a2606a858548e221919f0f1ae048d3ba3c47a0c5ea9e3b927ce023e970019086cfe210facb8821fabee808fc54f43e95c200644a1ef309c78051ab7596aeb0b5a959e0180464980e202fc50bf63e06a6780cb0588b1aeadafeda5775f03ce6217539697a14806f1ae3827b6f6a127c588c0a709506c9bd0fef201472a4a38706555f276a56983135f19144f04e2e076c384b9106b83de26cbd63c45034257c6938fa8a920798022089fb1fd41da8738ac7eda412a4aded8817ff6248c844effd176c267e2385c50bfbd7f54e0011e7bec31943419406af31e1a2797b16f5e1577286d1f38f18d81e2f164decf275c06520ad17e12924970fb905cae8cd71e3101b2cb028f1fa20d03812ab9440c4d4cd1e513514bfc847635d0d390c4d4a13b4653733f47af9b406cf51c9caf9ea4966cf2529080fc4c50023c8fddc7c26fdec1b3c55eaaa95e093577dbe66011214eefc6dcf926020565f254a4a2c0e81c9f540414034168df52c0de076686854c43eb89d2be791fa18f8e234c102698f65598565048f77583a694419330e94dea1cbafd2d1e07924208a3502a2c019efbae63c6335f655dc0cb74262f84abef22b74a639e3a84fef17b0849419d713972a078e48e8f0056621684d0a651f90023a1d3f5fe61dadfd88b69826f6280aa9ba6e0f442b23b86d61d43e829fa1b6308dd20d2a913e93488f70984092983c88d5b58009c1142440a154404107ff91f1c753ab8eba9d5bc50dab8eb4ad0a066a9954a981af2c4a9a8cbbc24b7bd4db2b60e75da341c13270e13ff1d58bb62de6c53d4821ebf905684de3f4cfbe63de8510d57b99fca15d329aaf45a6130a5e10aa8b8bc1e482904ca65123d09e23d7a06fc893eb63f778c172ddbb3d2e2e16a824ea0fcd4d33c5355ca2d225086b2f44e2b6ed80f35439d243edc8ea9a570cd99833aa56a08d55741f6e5acbedd222f0eab01bdbb8ed1be79375a5718b5d84bf9b2cb1853332e3307eba528dbf46892964f7a68de1b251517b445a97bfe386b3637710868079a810e21447224455175fb13dc79ed4cd6992610188b7add8d1675f6c3cd5088d8ee7d18b104eeb97370cdbaac00016e9bf8205082de7286f8ee0d988933046ebe19c9ed1e940cc54eb4d2b1f91322c75a905d4ec67ee632c6dd707961e076bf635f17a7dee9241537896884d61ce7d9174fb00be804dab032c208a00b21c488aac2cdcf7053999fb72459c6d04cf097a0d65c85ecf5661e2ee231229f1c22d517c3396d0a454b97e4393e1f508c193688ef7e9764ddf6ccfd95b163295aba0ca5b40c2499544f84b60d1fd27fe014c284b14be751bef20a14074302ef3edc49fde626e23d1a118dd0fbcd6cfcd97ede024240ab4d4018eb1d5ec028cae29dcfb222e0e11d87cf8d3004c9fe24c82aee050b903deecc24443c4effbee3a4fa1338675613b87169c6f109cd49e2e03ee2bbdf29f80cc9e5c277e36d843ea8a577672da609c185f328bb7501ce31ae82a04969f41feba4e9ed7afa4ef691d489edede4dddf1ce2d586304d58eade01f4dac00b6682c34ac73316016ab008d9e9408fa64884a208d98177fe3c148f3333219188133ed141bc3d825a399ee0ddb7933cfc2989437b11c944c1fb0b13623d10ebb6de6b3cd5d594ddb214df8c0a200e2269e7fd59e0c98e3ecebc514bc7ae168409ad11eabebd83a74e873983a5ea1d408f7583a14b6267dda34f8b69c7586407389c388a9d783c2ea28dbd8477ecc333b30a576911e829244c0255018496227aba95f65fff0167c032ef4292ec8768c8c2e6089632e1ae2fe2af9949767324ed0c2540c288eb9cd97488d6bf5bf1df1b940977999ceee7e8e9300d581960bbfde361374a464400c22af408c501aaf54aada84e7c5355fa8f771239729ad4f8121c2e07aa5746910d8a27bac0300877e824bac15d62f9b6b4a4e210e9b0804b4e1fe3573d40f1c2456413aef46b8a051c49a2f9b503b4bd7d845444c33fcec1a4f92e840907374591ad72572f595b1f918c8880744665bdf9a5375f2414bf13ffe52ae1139dc49a7ab2df93241c2e19a75be00940a41b226d566931adeea918484e3f636fbc87314b6f43f6c85805dc34e82cf8aeed47695ebf93644718d5a750bdd44fd94c17007d67aca207028145c2a8768b4767028ac3deefcfb941c049c9554508c344eb89a1f52749866224fb12c47acd01696ab8ddb2716182525cc9d89b1ea268de221b7c6c10f8f0d1469ad6bc49b4a11d599599bc2448458d37edc3adc551cc4c0a7c2e32320d48e7d5e9f255aeef94ac7f24155ce3ddb82658d11e24b4de045a6f9c78479464778c4457dc224380d1d54ccb9ac7329397dd3e5c13aa10c2c03d713cb1d34df41f39893061c282122aaef0a338e50cf00c09b261cded1ccf8b8cd2041c59139032ffd8e3c15ece59eac45916a06886fd41d9e7c15489edfd1d08413c94c0489a180983586702113e4db8294adfa77556fcbfbc98098bc6e20ad8d314e9ba245902143db340e722a38c02ea201328ecdea51c6e72fe9e3c09c904deca6200bc95e965cb6e9e66fb69a0394b2b067f5fc8294b8b4602a4808c4a03b226401e7069c065d020ddcd94bfed7b14043a4a32949105b2a164f42630400386039ea71d99dabf7d702a175c2ef0416414d202bb7f290830856d02bac7ceebed3fe4fb81b4e4034f8f151514ddd6803c5b8673d3824ba901b1fa668acbc643516af0aa0fe2a1c0670e07188eb31090db1f21199782804f5b3830bf9223c6e986d9424804af5d044506280c033ccf0fa4eb7d691f7036702335894b41c0e77f4be8cb4bf8c2c34bf963d9a9facfea099d319f59825ce6c8dee1ac0ed01ecb794e1018bcaab9fd1168817c7e048cf48c9df9c71d9c9eff53563585d81c3bdd44fbe67730bb015db5de0f327b03f6fe80eab4f70ef2f60bd28e7444fb09cea1bf23bb40f342d27b490800eb7dbae3da5ff260730f6f243abb69d9f8267a4b0c34dbb3abb9c07340a43fcb0d8343821d8614c90909177abbcca98d751cf8fd3f00e84ad0c9594ae043c9b91c957500635e58c5c3d74ee65149755279d7adb8aaca61ac2befb6f9b9c278d0c260368d2cd9c95c84158afa4c880b5a3f6ee0d4e64f8987a2c474421f74b0f11747d808d4014d58a5eb6165540725f3c40114bfb88affb87a023f92542793eebe1df794f150e6cf039d7b2d07a317c4993cb085faf6d810d09f8288414f5d07475ed8453c14453789ede862d313077905eb90648bdd86dc09ca97f32100ec3dc517efe3eb73cbf94f057c13562c23387f2e549659657060a01694029d205ab20087d20243405f02fa347a8eb6736af3117a8e77a09bc4f6f7f0eeef8ef1eae9282d58d59f76ace3b20946f13a7cbe04804dc2f7af67c5bfcce1cf32f826aef81c2557d540e5f89cac31fd98127bbe6d30e0a80dd9be61424f0c7a62243a23d4addf4fe7c166004e84d9f1a713acdd15e218d97a5fbaec35e0fccf48e44210001609bec79672c31d33f98b22f095cebf92ca1b96c39469d679c0cc63025805daf6f4141840426f183afbd0fbe31c7b652f2d3beb01e84850b7e6146bde6cc9d4f5dbb0d43ec6391c924ecb852200ecedb4af5ccdc2fb67f1accf41f598d9739872eb6d30712a148fb1bfe2c5da930831007c4f2fb487d0fba2346e3f4ae30775e8718d3e8da6f58dfce5a5063ea1405d9f737f09042e2c01609370d35466fc6031eb3c0ad383d53398b6f25694993530763cd67ff969c6d25a01a12e686b034da375f749ea5efb043daee57af62d5880d3c007d4f5cf572e34016091e0bc751a33be319f178a55aef4948e63f67dff8a63ea1ca89c053441b8099a9b2012a6f34803c75edf49bc2792efe09ac896b7fb2850d73f5fb91804a4c50994afbf8d672a3cdce22dade0f2bbeec33d6536e82d106ea5a7a185faad7be83ed50ac0a7bdbcf3542d7f6b8cd2cc6007774181a7e5621200d63ef2d8f537f36cb99bdb64d54dcdaa0771b8921c7f7b2b1db5f50813cec4d8f7741dffbb2bc449b20e2e0dfc9c1ddc48e462130076d6f8fc727e52e5e3df15d58d164f204c688f51f77a331b5eaacf6c5cb66279c7281719785a2e0501609110fce5221eae29e1bfa21a5d6f34f1d2ef8fb30d0b783b590797e20239b891c8a52200acca41e0de292c5cdb808195b474d82dedd92f8a9d9f4d2e250160254c5eacd35106562c4ff24f009e1671ae9b09e721b97b5eff74114220fd3358f8ff24ff07d25c4baf04fdecaa0000000049454e44ae426082 + + + + + + kpushbutton.h + + diff --git a/superkaramba/src/uptimesensor.cpp b/superkaramba/src/uptimesensor.cpp new file mode 100644 index 0000000..5d794a2 --- /dev/null +++ b/superkaramba/src/uptimesensor.cpp @@ -0,0 +1,119 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include + +#if defined __FreeBSD__ +#include +#include +#endif + +#if defined(Q_OS_NETBSD) +#include +#include +#include +#endif + +#include "uptimesensor.h" + +UptimeSensor::UptimeSensor( int interval ) : Sensor( interval ) +{} +UptimeSensor::~UptimeSensor() +{} + +void UptimeSensor::update() +{ +#if defined __FreeBSD__ || defined(Q_OS_NETBSD) + struct timeval boottime; + time_t now; /* the current time of day */ + + double avenrun[3]; + time_t uptime; + int days, hours, i, mins, secs; + int mib[2]; + size_t size; + char buf[256]; + + /* + * Get time of day. + */ + (void)time(&now); + + /* + * Determine how long system has been up. + * (Found by looking getting "boottime" from the kernel) + */ + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + size = sizeof(boottime); + if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && + boottime.tv_sec != 0) { + uptime = now - boottime.tv_sec; + if (uptime > 60) + uptime += 30; + days = uptime / 86400; + uptime %= 86400; + hours = uptime / 3600; + uptime %= 3600; + mins = uptime / 60; + secs = uptime % 60; + } +#else + QFile file("/proc/uptime"); + QString line; + if ( file.open(IO_ReadOnly | IO_Translate) ) + { + // file opened successfully + QTextStream t( &file ); // use a text stream + line = t.readLine(); // line of text excluding '\n' + file.close(); + + QRegExp rx( "^\\d+" ); + rx.search(line); + int uptime = rx.cap(0).toInt(); + int days = uptime / 86400; + uptime -= days * 86400; + int hours = uptime / 3600; + uptime -= hours * 3600; + int mins = uptime / 60; + uptime -= mins * 60; + int secs = uptime; +#endif + + QString format; + SensorParams *sp; + Meter *meter; + + QObjectListIt it( *objList ); + while (it != 0) + { + sp = (SensorParams*)(*it); + meter = sp->getMeter(); + format = sp->getParam("FORMAT"); + + if (format.length() == 0 ) + { + format = "%dd %h:%M"; + } + format.replace( QRegExp("%d"), QString::number(days)); + format.replace( QRegExp("%H"), QString::number(hours).rightJustify(2,'0')); + format.replace( QRegExp("%M"), QString::number(mins).rightJustify(2,'0')); + format.replace( QRegExp("%S"), QString::number(secs).rightJustify(2,'0')); + format.replace( QRegExp("%h"), QString::number(hours)); + format.replace( QRegExp("%m"), QString::number(mins)); + format.replace( QRegExp("%s"), QString::number(secs)); + + meter->setValue(format); + ++it; + } + +#if !defined __FreeBSD__ && !defined(Q_OS_NETBSD) + } +#endif +} diff --git a/superkaramba/src/uptimesensor.h b/superkaramba/src/uptimesensor.h new file mode 100644 index 0000000..061a876 --- /dev/null +++ b/superkaramba/src/uptimesensor.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef UPTIMESENSOR_H +#define UPTIMESENSOR_H +#include "sensor.h" + +#include +#include +#include +#include +#include + +class UptimeSensor : public Sensor +{ + +public: + UptimeSensor(int interval); + ~UptimeSensor(); + void update(); + +}; + +#endif // UPTIMESENSOR_H diff --git a/superkaramba/src/widget_python.cpp b/superkaramba/src/widget_python.cpp new file mode 100644 index 0000000..8d5d8e7 --- /dev/null +++ b/superkaramba/src/widget_python.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +* widget_python.h - Functions for widget python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include "karamba.h" +#include "meter.h" +#include "meter_python.h" +#include "widget_python.h" + +/* now a method we need to expose to Python */ +int getWidgetXCoordinate(long widget) +{ + karamba* currTheme = (karamba*)widget; + return currTheme->x(); +} + +/* now a method we need to expose to Python */ +int getWidgetYCoordinate(long widget) +{ + karamba* currTheme = (karamba*)widget; + return currTheme->y(); +} + +PyObject* py_get_widget_position(PyObject *, PyObject *args) +{ + long widget; + if(!PyArg_ParseTuple(args, (char*)"l:getWidgetPosition", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"(i,i)", getWidgetXCoordinate(widget), + getWidgetYCoordinate(widget)); +} + +/* now a method we need to expose to Python */ +long createWidgetMask(long widget, char* path) +{ + karamba* currTheme = (karamba*)widget; + QBitmap bm; + QString maskpath; + QString rootPath; + rootPath.setAscii(currTheme->theme().path().ascii()); + + currTheme->clearMask(); + + maskpath.setAscii(path); + rootPath.append(maskpath.ascii()); + + if(currTheme->theme().isZipTheme()) + { + QByteArray ba = currTheme->theme().readThemeFile(path); + bm.loadFromData(ba); + } + else + { + bm.load(rootPath); + } + currTheme->setMask(bm); + + return (long)currTheme->widgetMask; +} + +PyObject* py_create_widget_mask(PyObject *, PyObject *args) +{ + long widget; + char *text; + if (!PyArg_ParseTuple(args, (char*)"ls:createWidgetMask", &widget, &text)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", createWidgetMask(widget, text)); +} + +/* now a method we need to expose to Python */ +long redrawWidgetBackground(long widget) +{ + karamba* currTheme = (karamba*)widget; + currTheme->kroot->repaint(true); + return 1; +} + +PyObject* py_redraw_widget_background(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:redrawWidgetBackground", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", redrawWidgetBackground(widget)); +} + +/* now a method we need to expose to Python */ +long redrawWidget(long widget) +{ + karamba* currTheme = (karamba*)widget; + currTheme->externalStep(); + return 1; +} + +PyObject* py_redraw_widget(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:redrawWidget", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", redrawWidget(widget)); +} + +/* now a method we need to expose to Python */ +long resizeWidget(long widget, long x, long y) +{ + karamba* currTheme = (karamba*)widget; + //currTheme->test = true; + currTheme->setFixedSize((int)x,(int)y); + //currTheme->test = false; + return 1; +} + +PyObject* py_resize_widget(PyObject *, PyObject *args) +{ + long widget, x, y; + if (!PyArg_ParseTuple(args, (char*)"lll:resizeWidget", &widget, &x, &y)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", resizeWidget(widget, x, y)); +} + +/* now a method we need to expose to Python */ +long moveWidget(long widget, long x, long y) +{ + karamba* currTheme = (karamba*)widget; + currTheme->move((int)x, (int)y); + return 1; +} + +PyObject* py_move_widget(PyObject *, PyObject *args) +{ + long widget, x, y; + if (!PyArg_ParseTuple(args, (char*)"lll:moveWidget", &widget, &x, &y)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", moveWidget(widget, x, y)); +} + +/* now a method we need to expose to Python */ +long widgetSetOnTop(long widget, bool b) { + karamba* currTheme = (karamba*)widget; + + if (currTheme != 0) + { + currTheme->setAlwaysOnTop(b); + } + return 1; +} + +PyObject* py_set_widget_on_top(PyObject *, PyObject *args) +{ + long widget; + long b; + if (!PyArg_ParseTuple(args, (char*)"ll:setWidgetOnTop", &widget, &b )) + return NULL; + return Py_BuildValue((char*)"l", widgetSetOnTop(widget, b)); +} + +/* now a method we need to expose to Python */ +long toggleWidgetRedraw(long widget, bool b) +{ + karamba* currTheme = (karamba*)widget; + if (currTheme != 0) + { + currTheme->toggleWidgetUpdate( b ); + } + return 0; +} + +PyObject* py_toggle_widget_redraw(PyObject *, PyObject *args) +{ + long widget, b; + + if (!PyArg_ParseTuple(args, (char*)"ll:toggleWidgetRedraw", &widget, &b )) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", toggleWidgetRedraw(widget, b)); +} diff --git a/superkaramba/src/widget_python.h b/superkaramba/src/widget_python.h new file mode 100644 index 0000000..97cc263 --- /dev/null +++ b/superkaramba/src/widget_python.h @@ -0,0 +1,131 @@ +/**************************************************************************** +* widget_python.h - Functions for widget python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (c) 2004 Petri Damstn +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifndef WIDGET_PYTHON_H +#define WIDGET_PYTHON_H + +/** Widget/getWidgetPosition +* +* SYNOPSIS +* tuple getWidgetPosition(widget) +* DESCRIPTION +* Returns a Python Tuple containing the x and y position of you widget. +* widget is a reference to the current widget. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* position of the widget +*/ +PyObject* py_get_widget_position(PyObject *self, PyObject *args); + +/** Widget/createWidgetMask +* +* SYNOPSIS +* long createWidgetMask(widget, mask) +* DESCRIPTION +* This function doesn't work currently due to a bug in KDE. Please use +* MASK= in your .theme file for the time being. +* ARGUMENTS +* * long widget -- karamba +* * string mask -- The name of the widget mask file. +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_create_widget_mask(PyObject *self, PyObject *args); + +/** Widget/redrawWidgetBackground +* +* SYNOPSIS +* long redrawWidgetBackground(widget) +* DESCRIPTION +* Redraws widget background. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_redraw_widget_background(PyObject *self, PyObject *args); + +/** Widget/redrawWidget +* +* SYNOPSIS +* long redrawWidget(widget) +* DESCRIPTION +* This is THE most important function. After you do a bunch of other calls +* (moving images, adding images or text, etc), you call this to update the +* widget display area. You will not see your changes until you call this. +* Redraws widget background. +* ARGUMENTS +* * long widget -- karamba +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_redraw_widget(PyObject *self, PyObject *args); + +/** Widget/resizeWidget +* +* SYNOPSIS +* long resizeWidget(widget, w, h) +* DESCRIPTION +* Resizes your karamba widget to width=w, height=h +* ARGUMENTS +* * long widget -- karamba +* * long w -- width +* * long h -- height +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_resize_widget(PyObject *self, PyObject *args); + +/** Widget/moveWidget +* +* SYNOPSIS +* long moveWidget(widget, x, y) +* DESCRIPTION +* Moves your karamba widget to a new screen location +* ARGUMENTS +* * long widget -- karamba +* * long x -- x coordinate +* * long y -- y coordinate +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_move_widget(PyObject *self, PyObject *args); + +/** Widget/toggleWidgetRedraw +* +* SYNOPSIS +* long toggleWidgetRedraw(widget, b) +* DESCRIPTION +* Toggles widget redraw. +* ARGUMENTS +* * long widget -- karamba +* * long b -- 1 = widget is drawn +* RETURN VALUE +* 1 if successful +*/ +PyObject* py_toggle_widget_redraw(PyObject *self, PyObject *args); +PyObject* py_set_widget_on_top(PyObject *self, PyObject *args); + +#endif // WIDGET_PYTHON_H diff --git a/superkaramba/src/xmmssensor.cpp b/superkaramba/src/xmmssensor.cpp new file mode 100644 index 0000000..a55209e --- /dev/null +++ b/superkaramba/src/xmmssensor.cpp @@ -0,0 +1,149 @@ +/*************************************************************************** +* Copyright (C) 2003 by Hans Karlsson * +* karlsson.h@home.se * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +***************************************************************************/ +#include "xmmssensor.h" + +#ifdef HAVE_XMMS +#include +#endif // HAVE_XMMS + +XMMSSensor::XMMSSensor( int interval, const QString &encoding ) + : Sensor( interval ) +{ + if( !encoding.isEmpty() ) + { + codec = QTextCodec::codecForName( encoding.ascii() ); + if ( codec == 0) + codec = QTextCodec::codecForLocale(); + } + else + codec = QTextCodec::codecForLocale(); + +} +XMMSSensor::~XMMSSensor() +{} + +void XMMSSensor::update() +{ + QString format; + SensorParams *sp; + Meter *meter; + QObjectListIt it( *objList ); + +#ifdef HAVE_XMMS + + int pos; + QString title; + int songLength = 0; + int currentTime = 0; + bool isPlaying = false; + bool isRunning = xmms_remote_is_running(0); + + if( isRunning ) + { + isPlaying = xmms_remote_is_playing(0); + pos = xmms_remote_get_playlist_pos(0); + qDebug("unicode start"); + title = codec->toUnicode( QCString( xmms_remote_get_playlist_title( 0, pos ) ) ); + qDebug("unicode end"); + if( title.isEmpty() ) + title = "XMMS"; + + qDebug("Title: %s", title.ascii()); + songLength = xmms_remote_get_playlist_time( 0, pos ); + currentTime = xmms_remote_get_output_time( 0 ); + } +#endif // HAVE_XMMS + + while (it != 0) + { + sp = (SensorParams*)(*it); + meter = sp->getMeter(); + +#ifdef HAVE_XMMS + + if( isRunning ) + { + + format = sp->getParam("FORMAT"); + + + if (format.length() == 0 ) + { + format = "%title %time / %length"; + } + + if( format == "%ms" ) + { + meter->setMax( songLength ); + meter->setValue( currentTime ); + } + else + + if ( format == "%full" ) + { + meter->setValue( 1 ); + } + else + + { + + + format.replace( QRegExp("%title", false), title ); + + format.replace( QRegExp("%length", false), QTime( 0,0,0 ). + addMSecs( songLength ) + .toString( "h:mm:ss" ) ); + + format.replace( QRegExp("%time", false), QTime( 0,0,0 ). + addMSecs( currentTime ) + .toString( "h:mm:ss" ) ); + + if( isPlaying ) + { + format.replace( QRegExp("%remain", false), QTime( 0,0,0 ). + addMSecs( songLength ) + .addMSecs(-currentTime ) + .toString( "h:mm:ss" ) ); + } + + else + { + format.replace( QRegExp("%remain", false), QTime( 0,0,0 ).toString("h:mm:ss" ) ); + } + meter->setValue(format); + } + } + else +#endif // HAVE_XMMS + + { + meter->setValue(""); + } + ++it; + + } + +} + +void XMMSSensor::setMaxValue( SensorParams *sp) +{ + Meter *meter; + meter = sp->getMeter(); + QString f; + f = sp->getParam("FORMAT"); + + if ( f == "%full" ) + meter->setMax( 1 ); + +} + + + +#include "xmmssensor.moc" diff --git a/superkaramba/src/xmmssensor.h b/superkaramba/src/xmmssensor.h new file mode 100644 index 0000000..f5fd6ef --- /dev/null +++ b/superkaramba/src/xmmssensor.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (C) 2003 by Hans Karlsson * + * karlsson.h@home.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef XMMSSENSOR_H +#define XMMSSENSOR_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "sensor.h" + +class XMMSSensor : public Sensor +{ + Q_OBJECT +public: + XMMSSensor( int interval, const QString &encoding=QString::null ); + ~XMMSSensor(); + void update(); + void setMaxValue( SensorParams *); + +private: + QTextCodec *codec; + +}; + + +#endif // XMMSSENSOR_H -- cgit v1.2.3